AsmMethodBoost
This commit is contained in:
@@ -6,12 +6,28 @@ package org.redkale.asm;
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.annotation.Nullable;
|
||||
import static org.redkale.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.redkale.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.redkale.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.redkale.asm.Opcodes.ALOAD;
|
||||
import static org.redkale.asm.Opcodes.ARETURN;
|
||||
import static org.redkale.asm.Opcodes.DLOAD;
|
||||
import static org.redkale.asm.Opcodes.DRETURN;
|
||||
import static org.redkale.asm.Opcodes.FLOAD;
|
||||
import static org.redkale.asm.Opcodes.FRETURN;
|
||||
import static org.redkale.asm.Opcodes.ILOAD;
|
||||
import static org.redkale.asm.Opcodes.IRETURN;
|
||||
import static org.redkale.asm.Opcodes.LLOAD;
|
||||
import static org.redkale.asm.Opcodes.LRETURN;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
@@ -21,7 +37,15 @@ import org.redkale.util.Utility;
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
public interface AsmMethodBoost<T> {
|
||||
public abstract class AsmMethodBoost<T> {
|
||||
|
||||
protected final AtomicInteger fieldIndex = new AtomicInteger();
|
||||
|
||||
protected final Class serviceType;
|
||||
|
||||
protected AsmMethodBoost(Class serviceType) {
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
public static AsmMethodBoost create(Collection<AsmMethodBoost> list) {
|
||||
return new AsmMethodBoosts(list);
|
||||
@@ -31,6 +55,124 @@ public interface AsmMethodBoost<T> {
|
||||
return new AsmMethodBoosts(items);
|
||||
}
|
||||
|
||||
protected AsmMethodBean getMethodBean(Method method) {
|
||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||
return AsmMethodBean.get(methodBeans, method);
|
||||
}
|
||||
|
||||
protected MethodVisitor createMethodVisitor(ClassWriter cw, Method method, String newMethodName, AsmMethodBean methodBean) {
|
||||
return new MethodDebugVisitor(cw.visitMethod(getAcc(method, newMethodName),
|
||||
getNowMethodName(method, newMethodName), Type.getMethodDescriptor(method),
|
||||
getMethodSignature(method, methodBean), getMethodExceptions(method, methodBean)));
|
||||
}
|
||||
|
||||
protected int getAcc(Method method, String newMethodName) {
|
||||
if (newMethodName != null) {
|
||||
return ACC_PRIVATE;
|
||||
}
|
||||
return Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
|
||||
}
|
||||
|
||||
protected String getNowMethodName(Method method, String newMethodName) {
|
||||
return newMethodName == null ? method.getName() : newMethodName;
|
||||
}
|
||||
|
||||
protected String getMethodSignature(Method method, AsmMethodBean methodBean) {
|
||||
return methodBean != null ? methodBean.getSignature() : null;
|
||||
}
|
||||
|
||||
protected String[] getMethodExceptions(Method method, AsmMethodBean methodBean) {
|
||||
if (methodBean == null) {
|
||||
String[] exceptions = null;
|
||||
Class<?>[] expTypes = method.getExceptionTypes();
|
||||
if (expTypes.length > 0) {
|
||||
exceptions = new String[expTypes.length];
|
||||
for (int i = 0; i < expTypes.length; i++) {
|
||||
exceptions[i] = expTypes[i].getName().replace('.', '/');
|
||||
}
|
||||
}
|
||||
return exceptions;
|
||||
} else {
|
||||
return methodBean.getExceptions();
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitRawAnnotation(Method method, String newMethodName, MethodVisitor mv, Class selfAnnType, List filterAnns) {
|
||||
if (newMethodName == null) {
|
||||
//给方法加上原有的Annotation
|
||||
final Annotation[] anns = method.getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() != selfAnnType
|
||||
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
|
||||
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
//给参数加上原有的Annotation
|
||||
final Annotation[][] annss = method.getParameterAnnotations();
|
||||
for (int k = 0; k < annss.length; k++) {
|
||||
for (Annotation ann : annss[k]) {
|
||||
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Integer> visitVarInsnParamTypes(MethodVisitor mv, Method method) {
|
||||
//传参数
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
List<Integer> insns = new ArrayList<>();
|
||||
int insn = 0;
|
||||
for (Class pt : paramTypes) {
|
||||
insn++;
|
||||
if (pt.isPrimitive()) {
|
||||
if (pt == long.class) {
|
||||
mv.visitVarInsn(LLOAD, insn++);
|
||||
} else if (pt == float.class) {
|
||||
mv.visitVarInsn(FLOAD, insn++);
|
||||
} else if (pt == double.class) {
|
||||
mv.visitVarInsn(DLOAD, insn++);
|
||||
} else {
|
||||
mv.visitVarInsn(ILOAD, insn);
|
||||
}
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, insn);
|
||||
}
|
||||
insns.add(insn);
|
||||
}
|
||||
return insns;
|
||||
}
|
||||
|
||||
protected void visitInsnReturn(MethodVisitor mv, Method method, Label l0, List<Integer> insns, AsmMethodBean methodBean) {
|
||||
if (method.getGenericReturnType() == void.class) {
|
||||
mv.visitInsn(RETURN);
|
||||
} else {
|
||||
Class returnclz = method.getReturnType();
|
||||
if (returnclz.isPrimitive()) {
|
||||
if (returnclz == long.class) {
|
||||
mv.visitInsn(LRETURN);
|
||||
} else if (returnclz == float.class) {
|
||||
mv.visitInsn(FRETURN);
|
||||
} else if (returnclz == double.class) {
|
||||
mv.visitInsn(DRETURN);
|
||||
} else {
|
||||
mv.visitInsn(IRETURN);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
if (methodBean != null && paramTypes.length > 0) {
|
||||
Label l2 = new Label();
|
||||
mv.visitLabel(l2);
|
||||
//mv.visitLocalVariable("this", thisClassDesc, null, l0, l2, 0);
|
||||
List<String> fieldNames = methodBean.getFieldNames();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
mv.visitLocalVariable(fieldNames.get(i), Type.getDescriptor(paramTypes[i]), null, l0, l2, insns.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
|
||||
@@ -53,7 +195,7 @@ public interface AsmMethodBoost<T> {
|
||||
*
|
||||
* @return 需要屏蔽的注解
|
||||
*/
|
||||
public List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
|
||||
public abstract List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
|
||||
|
||||
/**
|
||||
* 对方法进行动态加强处理
|
||||
@@ -67,7 +209,7 @@ public interface AsmMethodBoost<T> {
|
||||
*
|
||||
* @return 下一个新的方法名,不做任何处理应返回参数newMethodName
|
||||
*/
|
||||
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
|
||||
public abstract String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
|
||||
List<Class<? extends Annotation>> filterAnns, Method method, @Nullable String newMethodName);
|
||||
|
||||
/** 处理所有动态方法后调用
|
||||
@@ -76,14 +218,14 @@ public interface AsmMethodBoost<T> {
|
||||
* @param newDynName 动态新类名
|
||||
* @param fieldPrefix 动态字段的前缀
|
||||
*/
|
||||
public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix);
|
||||
public abstract void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix);
|
||||
|
||||
/**
|
||||
* 实例对象进行操作,通常用于给动态的字段赋值
|
||||
*
|
||||
* @param service 实例对象
|
||||
*/
|
||||
public void doInstance(T service);
|
||||
public abstract void doInstance(T service);
|
||||
|
||||
/**
|
||||
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
|
||||
@@ -92,15 +234,17 @@ public interface AsmMethodBoost<T> {
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
static class AsmMethodBoosts<T> implements AsmMethodBoost<T> {
|
||||
static class AsmMethodBoosts<T> extends AsmMethodBoost<T> {
|
||||
|
||||
private final AsmMethodBoost[] items;
|
||||
|
||||
public AsmMethodBoosts(Collection<AsmMethodBoost> list) {
|
||||
super(null);
|
||||
this.items = list.toArray(new AsmMethodBoost[list.size()]);
|
||||
}
|
||||
|
||||
public AsmMethodBoosts(AsmMethodBoost... items) {
|
||||
super(null);
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@ package org.redkale.cache.spi;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.asm.AnnotationVisitor;
|
||||
import org.redkale.asm.AsmMethodBean;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
@@ -17,7 +14,7 @@ import org.redkale.asm.Asms;
|
||||
import org.redkale.asm.ClassWriter;
|
||||
import org.redkale.asm.FieldVisitor;
|
||||
import org.redkale.asm.Label;
|
||||
import org.redkale.asm.MethodDebugVisitor;
|
||||
import org.redkale.asm.MethodVisitor;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.cache.Cached;
|
||||
@@ -27,16 +24,12 @@ import org.redkale.util.RedkaleException;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class CacheAsmMethodBoost implements AsmMethodBoost {
|
||||
public class CacheAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Cached.class, DynForCache.class);
|
||||
|
||||
private final AtomicInteger fieldIndex = new AtomicInteger();
|
||||
|
||||
protected final Class serviceType;
|
||||
|
||||
public CacheAsmMethodBoost(Class serviceType) {
|
||||
this.serviceType = serviceType;
|
||||
super(serviceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,123 +43,38 @@ public class CacheAsmMethodBoost implements AsmMethodBoost {
|
||||
if (cached == null) {
|
||||
return newMethodName;
|
||||
}
|
||||
if (method.getAnnotation(DynForCache.class) != null) {
|
||||
return newMethodName;
|
||||
}
|
||||
if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
|
||||
throw new RedkaleException("@" + Cached.class.getSimpleName() + " can not on final or static method, but on " + method);
|
||||
}
|
||||
if (!Modifier.isProtected(method.getModifiers()) && !Modifier.isPublic(method.getModifiers())) {
|
||||
throw new RedkaleException("@" + Cached.class.getSimpleName() + " must on protected or public method, but on " + method);
|
||||
}
|
||||
int acc;
|
||||
String nowMethodName;
|
||||
if (newMethodName == null) {
|
||||
nowMethodName = method.getName();
|
||||
acc = Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
|
||||
} else {
|
||||
acc = ACC_PRIVATE;
|
||||
nowMethodName = newMethodName;
|
||||
}
|
||||
|
||||
final String rsMethodName = method.getName() + "_afterCache";
|
||||
final String dynFieldName = fieldPrefix + "_" + method.getName() + "CacheAction" + fieldIndex.incrementAndGet();
|
||||
{
|
||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||
|
||||
{ //定义一个新方法调用 this.rsMethodName
|
||||
final AsmMethodBean methodBean = getMethodBean(method);
|
||||
final String cacheDynDesc = Type.getDescriptor(DynForCache.class);
|
||||
MethodDebugVisitor mv;
|
||||
AnnotationVisitor av;
|
||||
String signature = null;
|
||||
String[] exceptions = null;
|
||||
if (methodBean == null) {
|
||||
Class<?>[] expTypes = method.getExceptionTypes();
|
||||
if (expTypes.length > 0) {
|
||||
exceptions = new String[expTypes.length];
|
||||
for (int i = 0; i < expTypes.length; i++) {
|
||||
exceptions[i] = expTypes[i].getName().replace('.', '/');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
signature = methodBean.getSignature();
|
||||
exceptions = methodBean.getExceptions();
|
||||
}
|
||||
//需要定义一个新方法调用 this.rsMethodName
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(acc, nowMethodName, Type.getMethodDescriptor(method), signature, exceptions));
|
||||
final MethodVisitor mv = createMethodVisitor(cw, method, newMethodName, methodBean);
|
||||
//mv.setDebug(true);
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
av = mv.visitAnnotation(cacheDynDesc, true);
|
||||
AnnotationVisitor av = mv.visitAnnotation(cacheDynDesc, true);
|
||||
av.visit("dynField", dynFieldName);
|
||||
Asms.visitAnnotation(av, cached);
|
||||
if (newMethodName == null) {
|
||||
//给方法加上原有的Annotation
|
||||
final Annotation[] anns = method.getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() != Cached.class
|
||||
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
|
||||
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
//给参数加上原有的Annotation
|
||||
final Annotation[][] annss = method.getParameterAnnotations();
|
||||
for (int k = 0; k < annss.length; k++) {
|
||||
for (Annotation ann : annss[k]) {
|
||||
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
}
|
||||
visitRawAnnotation(method, newMethodName, mv, Cached.class, filterAnns);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
//传参数
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
List<Integer> insns = new ArrayList<>();
|
||||
int insn = 0;
|
||||
for (Class pt : paramTypes) {
|
||||
insn++;
|
||||
if (pt.isPrimitive()) {
|
||||
if (pt == long.class) {
|
||||
mv.visitVarInsn(LLOAD, insn++);
|
||||
} else if (pt == float.class) {
|
||||
mv.visitVarInsn(FLOAD, insn++);
|
||||
} else if (pt == double.class) {
|
||||
mv.visitVarInsn(DLOAD, insn++);
|
||||
} else {
|
||||
mv.visitVarInsn(ILOAD, insn);
|
||||
}
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, insn);
|
||||
}
|
||||
insns.add(insn);
|
||||
}
|
||||
List<Integer> insns = visitVarInsnParamTypes(mv, method);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, newDynName, rsMethodName, Type.getMethodDescriptor(method), false);
|
||||
if (method.getGenericReturnType() == void.class) {
|
||||
mv.visitInsn(RETURN);
|
||||
} else {
|
||||
Class returnclz = method.getReturnType();
|
||||
if (returnclz.isPrimitive()) {
|
||||
if (returnclz == long.class) {
|
||||
mv.visitInsn(LRETURN);
|
||||
} else if (returnclz == float.class) {
|
||||
mv.visitInsn(FRETURN);
|
||||
} else if (returnclz == double.class) {
|
||||
mv.visitInsn(DRETURN);
|
||||
} else {
|
||||
mv.visitInsn(IRETURN);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
if (methodBean != null && paramTypes.length > 0) {
|
||||
Label l2 = new Label();
|
||||
mv.visitLabel(l2);
|
||||
//mv.visitLocalVariable("this", thisClassDesc, null, l0, l2, 0);
|
||||
List<String> fieldNames = methodBean.getFieldNames();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
mv.visitLocalVariable(fieldNames.get(i), Type.getDescriptor(paramTypes[i]), null, l0, l2, insns.get(i));
|
||||
}
|
||||
}
|
||||
visitInsnReturn(mv, method, l0, insns, methodBean);
|
||||
mv.visitMaxs(20, 20);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
{ //定义字段
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE, dynFieldName, Type.getDescriptor(CacheAction.class), null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
@@ -6,17 +6,14 @@ package org.redkale.lock.spi;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.redkale.asm.AnnotationVisitor;
|
||||
import org.redkale.asm.AsmMethodBean;
|
||||
import org.redkale.asm.AsmMethodBoost;
|
||||
import org.redkale.asm.Asms;
|
||||
import org.redkale.asm.ClassWriter;
|
||||
import org.redkale.asm.Label;
|
||||
import org.redkale.asm.MethodDebugVisitor;
|
||||
import org.redkale.asm.MethodVisitor;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
import org.redkale.lock.Locked;
|
||||
@@ -26,16 +23,12 @@ import org.redkale.util.RedkaleException;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class LockAsmMethodBoost implements AsmMethodBoost {
|
||||
public class LockAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
private static final List<Class<? extends Annotation>> FILTER_ANN = List.of(Locked.class, DynForLock.class);
|
||||
|
||||
private final AtomicInteger fieldIndex = new AtomicInteger();
|
||||
|
||||
protected final Class serviceType;
|
||||
|
||||
public LockAsmMethodBoost(Class serviceType) {
|
||||
this.serviceType = serviceType;
|
||||
super(serviceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,8 +38,11 @@ public class LockAsmMethodBoost implements AsmMethodBoost {
|
||||
|
||||
@Override
|
||||
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, List filterAnns, Method method, final String newMethodName) {
|
||||
Locked cached = method.getAnnotation(Locked.class);
|
||||
if (cached == null) {
|
||||
Locked locked = method.getAnnotation(Locked.class);
|
||||
if (locked == null) {
|
||||
return newMethodName;
|
||||
}
|
||||
if (method.getAnnotation(DynForLock.class) != null) {
|
||||
return newMethodName;
|
||||
}
|
||||
if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
|
||||
@@ -55,114 +51,24 @@ public class LockAsmMethodBoost implements AsmMethodBoost {
|
||||
if (!Modifier.isProtected(method.getModifiers()) && !Modifier.isPublic(method.getModifiers())) {
|
||||
throw new RedkaleException("@" + Locked.class.getSimpleName() + " must on protected or public method, but on " + method);
|
||||
}
|
||||
int acc;
|
||||
String nowMethodName;
|
||||
if (newMethodName == null) {
|
||||
nowMethodName = method.getName();
|
||||
acc = Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
|
||||
} else {
|
||||
acc = ACC_PRIVATE;
|
||||
nowMethodName = newMethodName;
|
||||
}
|
||||
|
||||
final String rsMethodName = method.getName() + "_afterLock";
|
||||
final String dynFieldName = fieldPrefix + "_" + method.getName() + "LockAction" + fieldIndex.incrementAndGet();
|
||||
{
|
||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||
|
||||
{ //定义一个新方法调用 this.rsMethodName
|
||||
final AsmMethodBean methodBean = getMethodBean(method);
|
||||
final String lockDynDesc = Type.getDescriptor(DynForLock.class);
|
||||
MethodDebugVisitor mv;
|
||||
AnnotationVisitor av;
|
||||
String signature = null;
|
||||
String[] exceptions = null;
|
||||
if (methodBean == null) {
|
||||
Class<?>[] expTypes = method.getExceptionTypes();
|
||||
if (expTypes.length > 0) {
|
||||
exceptions = new String[expTypes.length];
|
||||
for (int i = 0; i < expTypes.length; i++) {
|
||||
exceptions[i] = expTypes[i].getName().replace('.', '/');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
signature = methodBean.getSignature();
|
||||
exceptions = methodBean.getExceptions();
|
||||
}
|
||||
//需要定义一个新方法调用 this.rsMethodName
|
||||
mv = new MethodDebugVisitor(cw.visitMethod(acc, nowMethodName, Type.getMethodDescriptor(method), signature, exceptions));
|
||||
final MethodVisitor mv = createMethodVisitor(cw, method, newMethodName, methodBean);
|
||||
//mv.setDebug(true);
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
av = mv.visitAnnotation(lockDynDesc, true);
|
||||
AnnotationVisitor av = mv.visitAnnotation(lockDynDesc, true);
|
||||
av.visit("dynField", dynFieldName);
|
||||
Asms.visitAnnotation(av, cached);
|
||||
if (newMethodName == null) {
|
||||
//给方法加上原有的Annotation
|
||||
final Annotation[] anns = method.getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() != Locked.class
|
||||
&& (filterAnns == null || !filterAnns.contains(ann.annotationType()))) {
|
||||
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
//给参数加上原有的Annotation
|
||||
final Annotation[][] annss = method.getParameterAnnotations();
|
||||
for (int k = 0; k < annss.length; k++) {
|
||||
for (Annotation ann : annss[k]) {
|
||||
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
|
||||
}
|
||||
}
|
||||
}
|
||||
Asms.visitAnnotation(av, locked);
|
||||
visitRawAnnotation(method, newMethodName, mv, Locked.class, filterAnns);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
//传参数
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
List<Integer> insns = new ArrayList<>();
|
||||
int insn = 0;
|
||||
for (Class pt : paramTypes) {
|
||||
insn++;
|
||||
if (pt.isPrimitive()) {
|
||||
if (pt == long.class) {
|
||||
mv.visitVarInsn(LLOAD, insn++);
|
||||
} else if (pt == float.class) {
|
||||
mv.visitVarInsn(FLOAD, insn++);
|
||||
} else if (pt == double.class) {
|
||||
mv.visitVarInsn(DLOAD, insn++);
|
||||
} else {
|
||||
mv.visitVarInsn(ILOAD, insn);
|
||||
}
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, insn);
|
||||
}
|
||||
insns.add(insn);
|
||||
}
|
||||
List<Integer> insns = visitVarInsnParamTypes(mv, method);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, newDynName, rsMethodName, Type.getMethodDescriptor(method), false);
|
||||
if (method.getGenericReturnType() == void.class) {
|
||||
mv.visitInsn(RETURN);
|
||||
} else {
|
||||
Class returnclz = method.getReturnType();
|
||||
if (returnclz.isPrimitive()) {
|
||||
if (returnclz == long.class) {
|
||||
mv.visitInsn(LRETURN);
|
||||
} else if (returnclz == float.class) {
|
||||
mv.visitInsn(FRETURN);
|
||||
} else if (returnclz == double.class) {
|
||||
mv.visitInsn(DRETURN);
|
||||
} else {
|
||||
mv.visitInsn(IRETURN);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
if (methodBean != null && paramTypes.length > 0) {
|
||||
Label l2 = new Label();
|
||||
mv.visitLabel(l2);
|
||||
//mv.visitLocalVariable("this", thisClassDesc, null, l0, l2, 0);
|
||||
List<String> fieldNames = methodBean.getFieldNames();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
mv.visitLocalVariable(fieldNames.get(i), Type.getDescriptor(paramTypes[i]), null, l0, l2, insns.get(i));
|
||||
}
|
||||
}
|
||||
visitInsnReturn(mv, method, l0, insns, methodBean);
|
||||
mv.visitMaxs(20, 20);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user