CacheAction
This commit is contained in:
@@ -50,6 +50,10 @@ public class AsmMethodBean {
|
||||
}
|
||||
}
|
||||
|
||||
public String[] fieldNameArray() {
|
||||
return fieldNames == null ? null : fieldNames.toArray(new String[fieldNames.size()]);
|
||||
}
|
||||
|
||||
public List<String> getFieldNames() {
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,8 @@ public abstract class AsmMethodBoost<T> {
|
||||
* @param newDynName 动态新类名
|
||||
* @param fieldPrefix 动态字段的前缀
|
||||
*/
|
||||
public abstract void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix);
|
||||
public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例对象进行操作,通常用于给动态的字段赋值
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.util.function.Supplier;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import org.redkale.annotation.Resource;
|
||||
import org.redkale.cache.CacheManager;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.sncp.Sncp;
|
||||
import org.redkale.util.Environment;
|
||||
@@ -38,7 +37,7 @@ public class CacheAction {
|
||||
@Resource
|
||||
private CacheManager manager;
|
||||
|
||||
private final Cached cached;
|
||||
private final CacheEntry cached;
|
||||
|
||||
//Supplier对象的类型
|
||||
private final Type resultType;
|
||||
@@ -55,6 +54,9 @@ public class CacheAction {
|
||||
//无法获取动态的Method,只能存方法名
|
||||
private final String methodName;
|
||||
|
||||
//获取动态的字段名
|
||||
private final String fieldName;
|
||||
|
||||
//方法参数类型
|
||||
@Nullable
|
||||
private final Class[] paramTypes;
|
||||
@@ -66,9 +68,6 @@ public class CacheAction {
|
||||
//缓存的hash
|
||||
private String hash;
|
||||
|
||||
//缓存的key
|
||||
private String key;
|
||||
|
||||
//缓存的key
|
||||
private MultiHashKey dynKey;
|
||||
|
||||
@@ -78,25 +77,27 @@ public class CacheAction {
|
||||
//远程缓存过期时长
|
||||
private Duration remoteExpire;
|
||||
|
||||
CacheAction(Cached cached, Type returnType, Class serviceClass, Class[] paramTypes, String[] paramNames, String methodName) {
|
||||
CacheAction(CacheEntry cached, Type returnType, Class serviceClass, Class[] paramTypes,
|
||||
String[] paramNames, String methodName, String fieldName) {
|
||||
this.cached = cached;
|
||||
this.nullable = cached.nullable();
|
||||
this.nullable = cached.isNullable();
|
||||
this.serviceClass = Objects.requireNonNull(serviceClass);
|
||||
this.paramTypes = paramTypes;
|
||||
this.paramNames = paramNames;
|
||||
this.methodName = Objects.requireNonNull(methodName);
|
||||
this.fieldName = Objects.requireNonNull(fieldName);
|
||||
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
|
||||
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
|
||||
}
|
||||
|
||||
void init() {
|
||||
this.hash = cached.hash().trim().isEmpty()
|
||||
this.hash = cached.getHash().trim().isEmpty()
|
||||
? Sncp.getResourceType(serviceClass).getSimpleName()
|
||||
: environment.getPropertyValue(cached.hash());
|
||||
this.key = environment.getPropertyValue(cached.key());
|
||||
: environment.getPropertyValue(cached.getHash());
|
||||
String key = environment.getPropertyValue(cached.getKey());
|
||||
this.dynKey = MultiHashKey.create(paramNames, key);
|
||||
this.localExpire = createDuration(cached.localExpire());
|
||||
this.remoteExpire = createDuration(cached.remoteExpire());
|
||||
this.localExpire = createDuration(cached.getLocalExpire());
|
||||
this.remoteExpire = createDuration(cached.getRemoteExpire());
|
||||
}
|
||||
|
||||
public <T> T get(Supplier<T> supplier, Object... args) {
|
||||
@@ -115,7 +116,7 @@ public class CacheAction {
|
||||
} else if ("0".equals(str)) {
|
||||
return Duration.ZERO;
|
||||
} else {
|
||||
return Duration.ofMillis(cached.timeUnit().toMillis(Long.parseLong(str)));
|
||||
return Duration.ofMillis(cached.getTimeUnit().toMillis(Long.parseLong(str)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,14 +125,10 @@ public class CacheAction {
|
||||
return "{"
|
||||
+ "\"serviceClass\":" + serviceClass.getName()
|
||||
+ ",\"methodName\":\"" + methodName + "\""
|
||||
+ ",\"fieldName\":\"" + fieldName + "\""
|
||||
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(paramTypes)
|
||||
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
|
||||
+ ",\"hash\":\"" + cached.hash() + "\""
|
||||
+ ",\"key\":" + JsonConvert.root().convertTo(key)
|
||||
+ ",\"localExpire\":\"" + cached.localExpire() + "\""
|
||||
+ ",\"remoteExpire\":\"" + cached.remoteExpire() + "\""
|
||||
+ ",\"timeUnit\":\"" + cached.timeUnit() + "\""
|
||||
+ ",\"nullable\":" + cached.nullable()
|
||||
+ ",\"cache\":" + cached
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.redkale.asm.AnnotationVisitor;
|
||||
import org.redkale.asm.AsmMethodBean;
|
||||
@@ -20,6 +23,7 @@ import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.TypeToken;
|
||||
|
||||
@@ -34,6 +38,8 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
|
||||
|
||||
private Map<String, CacheAction> actionMap;
|
||||
|
||||
public CacheAsmMethodBoost(Class serviceType) {
|
||||
super(serviceType);
|
||||
}
|
||||
@@ -45,6 +51,11 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
@Override
|
||||
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) {
|
||||
Map<String, CacheAction> actions = this.actionMap;
|
||||
if (actions == null) {
|
||||
actions = new LinkedHashMap<>();
|
||||
this.actionMap = actions;
|
||||
}
|
||||
Cached cached = method.getAnnotation(Cached.class);
|
||||
if (cached == null) {
|
||||
return newMethodName;
|
||||
@@ -61,7 +72,6 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
if (method.getReturnType() == void.class || FUTURE_VOID.equals(method.getGenericReturnType())) {
|
||||
throw new RedkaleException("@" + Cached.class.getSimpleName() + " cannot on void method, but on " + method);
|
||||
}
|
||||
|
||||
final String rsMethodName = method.getName() + "_afterCache";
|
||||
final String dynFieldName = fieldPrefix + "_" + method.getName() + "CacheAction" + fieldIndex.incrementAndGet();
|
||||
{ //定义一个新方法调用 this.rsMethodName
|
||||
@@ -82,6 +92,9 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
visitInsnReturn(mv, method, l0, insns, methodBean);
|
||||
mv.visitMaxs(20, 20);
|
||||
mv.visitEnd();
|
||||
CacheAction action = new CacheAction(new CacheEntry(cached), method.getGenericReturnType(), serviceType,
|
||||
method.getParameterTypes(), methodBean.fieldNameArray(), method.getName(), dynFieldName);
|
||||
actions.put(dynFieldName, action);
|
||||
}
|
||||
{ //定义字段
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE, dynFieldName, Type.getDescriptor(CacheAction.class), null, null);
|
||||
@@ -90,13 +103,35 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
return rsMethodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInstance(ResourceFactory resourceFactory, Object service) {
|
||||
Class clazz = service.getClass();
|
||||
if (actionMap == null) { //为null表示没有调用过doMethod, 动态类在编译是已经生成好了
|
||||
actionMap = new LinkedHashMap<>();
|
||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(clazz);
|
||||
for (final Method method : clazz.getDeclaredMethods()) {
|
||||
DynForCache cached = method.getAnnotation(DynForCache.class);
|
||||
if (cached != null) {
|
||||
String dynFieldName = cached.dynField();
|
||||
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||
CacheAction action = new CacheAction(new CacheEntry(cached), method.getGenericReturnType(), serviceType,
|
||||
method.getParameterTypes(), methodBean.fieldNameArray(), method.getName(), dynFieldName);
|
||||
actionMap.put(dynFieldName, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
actionMap.forEach((field, action) -> {
|
||||
try {
|
||||
Field c = clazz.getDeclaredField(field);
|
||||
c.setAccessible(true);
|
||||
resourceFactory.inject(action);
|
||||
action.init();
|
||||
c.set(service, action);
|
||||
RedkaleClassLoader.putReflectionField(clazz.getName(), c);
|
||||
} catch (Exception e) {
|
||||
throw new RedkaleException("field (" + field + ") in " + clazz.getName() + " set error", e);
|
||||
}
|
||||
});
|
||||
//do nothing
|
||||
}
|
||||
|
||||
|
||||
101
src/main/java/org/redkale/cache/spi/CacheEntry.java
vendored
Normal file
101
src/main/java/org/redkale/cache/spi/CacheEntry.java
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.cache.spi;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.redkale.cache.Cached;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class CacheEntry {
|
||||
|
||||
private String key;
|
||||
|
||||
private String hash;
|
||||
|
||||
private String localExpire;
|
||||
|
||||
private String remoteExpire;
|
||||
|
||||
private TimeUnit timeUnit;
|
||||
|
||||
private boolean nullable;
|
||||
|
||||
public CacheEntry() {
|
||||
}
|
||||
|
||||
public CacheEntry(DynForCache cached) {
|
||||
this.key = cached.key();
|
||||
this.hash = cached.hash();
|
||||
this.localExpire = cached.localExpire();
|
||||
this.remoteExpire = cached.remoteExpire();
|
||||
this.timeUnit = cached.timeUnit();
|
||||
this.nullable = cached.nullable();
|
||||
}
|
||||
|
||||
public CacheEntry(Cached cached) {
|
||||
this.key = cached.key();
|
||||
this.hash = cached.hash();
|
||||
this.localExpire = cached.localExpire();
|
||||
this.remoteExpire = cached.remoteExpire();
|
||||
this.timeUnit = cached.timeUnit();
|
||||
this.nullable = cached.nullable();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public String getLocalExpire() {
|
||||
return localExpire;
|
||||
}
|
||||
|
||||
public void setLocalExpire(String localExpire) {
|
||||
this.localExpire = localExpire;
|
||||
}
|
||||
|
||||
public String getRemoteExpire() {
|
||||
return remoteExpire;
|
||||
}
|
||||
|
||||
public void setRemoteExpire(String remoteExpire) {
|
||||
this.remoteExpire = remoteExpire;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
|
||||
public void setTimeUnit(TimeUnit timeUnit) {
|
||||
this.timeUnit = timeUnit;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public void setNullable(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ public class CacheExpire {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonConvert.root().convertTo(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user