DynForCache

This commit is contained in:
redkale
2023-12-20 18:13:39 +08:00
parent 0c1e34c2cc
commit ff7ed50e82
4 changed files with 75 additions and 36 deletions

View File

@@ -4,7 +4,9 @@
package org.redkale.asm; package org.redkale.asm;
import java.io.InputStream; import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -44,18 +46,29 @@ public interface AsmMethodBoost<T> {
return rs; return rs;
} }
/**
* 获取需屏蔽的方法上的注解
*
* @param method 方法
*
* @return 需要屏蔽的注解
*/
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
/** /**
* 对方法进行动态加强处理 * 对方法进行动态加强处理
* *
* @param cw 动态字节码Writer * @param cw 动态字节码Writer
* @param newDynName 动态新类名 * @param newDynName 动态新类名
* @param fieldPrefix 动态字段的前缀 * @param fieldPrefix 动态字段的前缀
* @param filterAnns 需要过滤的注解
* @param method 操作的方法 * @param method 操作的方法
* @param newMethodName 新的方法名, 可能为null * @param newMethodName 新的方法名, 可能为null
* *
* @return 下一个新的方法名不做任何处理应返回参数newMethodName * @return 下一个新的方法名不做任何处理应返回参数newMethodName
*/ */
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, Method method, @Nullable String newMethodName); public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
List<Class<? extends Annotation>> filterAnns, Method method, @Nullable String newMethodName);
/** 处理所有动态方法后调用 /** 处理所有动态方法后调用
* *
@@ -92,11 +105,29 @@ public interface AsmMethodBoost<T> {
} }
@Override @Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, Method method, String newMethodName) { public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
List<Class<? extends Annotation>> list = null;
for (AsmMethodBoost item : items) {
if (item != null) {
List<Class<? extends Annotation>> sub = item.filterMethodAnnotations(method);
if (sub != null) {
if (list == null) {
list = new ArrayList<>();
}
list.addAll(sub);
}
}
}
return list;
}
@Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
List<Class<? extends Annotation>> filterAnns, Method method, String newMethodName) {
String newName = newMethodName; String newName = newMethodName;
for (AsmMethodBoost item : items) { for (AsmMethodBoost item : items) {
if (item != null) { if (item != null) {
newName = item.doMethod(cw, newDynName, fieldPrefix, method, newName); newName = item.doMethod(cw, newDynName, fieldPrefix, filterAnns, method, newName);
} }
} }
return newName; return newName;

View File

@@ -41,6 +41,8 @@ import org.redkale.util.RedkaleException;
*/ */
public class CacheAsmMethodBoost implements AsmMethodBoost { public class CacheAsmMethodBoost implements AsmMethodBoost {
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class);
protected final Class serviceType; protected final Class serviceType;
public CacheAsmMethodBoost(Class serviceType) { public CacheAsmMethodBoost(Class serviceType) {
@@ -48,7 +50,12 @@ public class CacheAsmMethodBoost implements AsmMethodBoost {
} }
@Override @Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, Method method, final String newMethodName) { public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
return FILTER_ANN;
}
@Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) {
Cached cached = method.getAnnotation(Cached.class); Cached cached = method.getAnnotation(Cached.class);
if (cached == null) { if (cached == null) {
return newMethodName; return newMethodName;
@@ -69,7 +76,7 @@ public class CacheAsmMethodBoost implements AsmMethodBoost {
nowMethodName = newMethodName; nowMethodName = newMethodName;
} }
final String rsMethodName = method.getName() + "_cache"; final String rsMethodName = method.getName() + "_afterCache";
{ {
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType); Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method); AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
@@ -96,20 +103,21 @@ public class CacheAsmMethodBoost implements AsmMethodBoost {
//mv.setDebug(true); //mv.setDebug(true);
Label l0 = new Label(); Label l0 = new Label();
mv.visitLabel(l0); mv.visitLabel(l0);
{ av = mv.visitAnnotation(cacheDynDesc, true);
av = mv.visitAnnotation(cacheDynDesc, true); av.visitEnd();
av.visitEnd(); if (newMethodName == null) {
//给方法加上原有的Annotation
final Annotation[] anns = method.getAnnotations(); final Annotation[] anns = method.getAnnotations();
for (Annotation ann : anns) { for (Annotation ann : anns) {
if (ann.annotationType() != Cached.class) { if (ann.annotationType() != Cached.class
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann); Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
} }
} }
} //给参数加上原有的Annotation
{ //给参数加上原有的Annotation final Annotation[][] annss = method.getParameterAnnotations();
final Annotation[][] anns = method.getParameterAnnotations(); for (int k = 0; k < annss.length; k++) {
for (int k = 0; k < anns.length; k++) { for (Annotation ann : annss[k]) {
for (Annotation ann : anns[k]) {
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann); Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
} }
} }

View File

@@ -27,6 +27,8 @@ import org.redkale.util.RedkaleException;
*/ */
public class LockAsmMethodBoost implements AsmMethodBoost { public class LockAsmMethodBoost implements AsmMethodBoost {
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Locked.class);
protected final Class serviceType; protected final Class serviceType;
public LockAsmMethodBoost(Class serviceType) { public LockAsmMethodBoost(Class serviceType) {
@@ -34,7 +36,12 @@ public class LockAsmMethodBoost implements AsmMethodBoost {
} }
@Override @Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, Method method, final String newMethodName) { public List<Class<? extends Annotation>> filterMethodAnnotations(Method method) {
return FILTER_ANN;
}
@Override
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) {
Locked cached = method.getAnnotation(Locked.class); Locked cached = method.getAnnotation(Locked.class);
if (cached == null) { if (cached == null) {
return newMethodName; return newMethodName;
@@ -55,12 +62,12 @@ public class LockAsmMethodBoost implements AsmMethodBoost {
nowMethodName = newMethodName; nowMethodName = newMethodName;
} }
final String rsMethodName = method.getName() + "_lock"; final String rsMethodName = method.getName() + "_afterLock";
{ {
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType); Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method); AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
final String cacheDynDesc = Type.getDescriptor(DynForLock.class); final String lockDynDesc = Type.getDescriptor(DynForLock.class);
MethodDebugVisitor mv; MethodDebugVisitor mv;
AnnotationVisitor av; AnnotationVisitor av;
String signature = null; String signature = null;
@@ -82,20 +89,21 @@ public class LockAsmMethodBoost implements AsmMethodBoost {
//mv.setDebug(true); //mv.setDebug(true);
Label l0 = new Label(); Label l0 = new Label();
mv.visitLabel(l0); mv.visitLabel(l0);
{ av = mv.visitAnnotation(lockDynDesc, true);
av = mv.visitAnnotation(cacheDynDesc, true); av.visitEnd();
av.visitEnd(); if (newMethodName == null) {
//给方法加上原有的Annotation
final Annotation[] anns = method.getAnnotations(); final Annotation[] anns = method.getAnnotations();
for (Annotation ann : anns) { for (Annotation ann : anns) {
if (ann.annotationType() != Locked.class) { if (ann.annotationType() != Locked.class
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann); Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
} }
} }
} //给参数加上原有的Annotation
{ //给参数加上原有的Annotation final Annotation[][] annss = method.getParameterAnnotations();
final Annotation[][] anns = method.getParameterAnnotations(); for (int k = 0; k < annss.length; k++) {
for (int k = 0; k < anns.length; k++) { for (Annotation ann : annss[k]) {
for (Annotation ann : anns[k]) {
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann); Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
} }
} }

View File

@@ -568,7 +568,8 @@ public abstract class Sncp {
continue; continue;
} }
methodKeys.add(mk); methodKeys.add(mk);
String newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, method, null); List<Class<? extends Annotation>> filterAnns = methodBoost.filterMethodAnnotations(method);
String newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, filterAnns, method, null);
if (newMethodName != null) { if (newMethodName != null) {
String desc = Type.getMethodDescriptor(method); String desc = Type.getMethodDescriptor(method);
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method); AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
@@ -586,20 +587,11 @@ public abstract class Sncp {
signature = methodBean.getSignature(); signature = methodBean.getSignature();
exceptions = methodBean.getExceptions(); exceptions = methodBean.getExceptions();
} }
//注意: 新方法会丢失原方法中的泛型信息signature
//需要定义一个新方法调用 super.method //需要定义一个新方法调用 super.method
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PRIVATE, newMethodName, desc, signature, exceptions)); mv = new MethodDebugVisitor(cw.visitMethod(ACC_PRIVATE, newMethodName, desc, signature, exceptions));
Label l0 = new Label(); Label l0 = new Label();
mv.visitLabel(l0); mv.visitLabel(l0);
//mv.setDebug(true); //mv.setDebug(true);
{ //给参数加上原有的Annotation
final Annotation[][] anns = method.getParameterAnnotations();
for (int k = 0; k < anns.length; k++) {
for (Annotation ann : anns[k]) {
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
}
}
}
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
//传参数 //传参数
Class[] paramTypes = method.getParameterTypes(); Class[] paramTypes = method.getParameterTypes();