Nutz:从新发明车轮:自各儿下手,用字节码工具做一个Aop阻截器

Aop听得太多了, 用过Aop的JEer也不少,什么Spring Aop,AspectJ之类.

换个视角,为何不自各儿写一个Aop阻截器呢? 从新发明车轮又何以?

现下就用最基本的字节码工具来DIY一个Aop. 用反照就太没风度了,那货色,谁不会?!

成效预览:
原有的种

Java代码
一.public class Aop一{
2.
3. public void doSomething() throws Throwable{
4. //打我啊,拍我啊!
5. }
6.
7.}
public class Aop一{

public void doSomething() throws Throwable{
//打我啊,拍我啊!
}

}

改建后


Java代码
一.public class Aop一$$Aop extend Aop一{
2.
3. @Override
4. public void doSomething() throws Throwable{
5. try {
6. if (_Nut_before(188)) {
7. super.doSomething();
8. }
9. _Nut_after(188, null);
10. } catch (Exception e) {
11. if(_Nut_Exception(188, e))
12. throw e;
13. } catch (Throwable e) {
14. if(_Nut_Error(188, e))
15. throw e;
16. }
17. }
18.
19. private static Method[] _$$Nut_methodArray;
20.
21. private static List[] _$$Nut_methodInterceptorList;
22.
23. private boolean _Nut_before(int flag_int, Object... args) {
24. Method method = _$$Nut_methodArray[flag_int];
25. List miList = _$$Nut_methodInterceptorList[flag_int];
26. boolean flag = true;
27. for (MethodInterceptor methodInterceptor : miList)
28. flag &= methodInterceptor.beforeInvoke(this, method, args);
29. return flag;
30. }
31.
32. private Object _Nut_after(int flag_int, Object src_return, Object... args) {
33. Method method = _$$Nut_methodArray[flag_int];
34. List miList = _$$Nut_methodInterceptorList[flag_int];
35. for (MethodInterceptor methodInterceptor : miList)
36. src_return = methodInterceptor.afterInvoke(this, src_return, method, args);
37. return src_return;
38. }
39.
40. private boolean _Nut_Exception(int flag_int, Exception e, Object... args) {
41. Method method = _$$Nut_methodArray[flag_int];
42. List miList = _$$Nut_methodInterceptorList[flag_int];
43. boolean flag = true;
44. for (MethodInterceptor methodInterceptor : miList)
45. flag &= methodInterceptor.whenException(e, this, method, args);
46. return flag;
47. }
48.
49. private boolean _Nut_Error(int flag_int, Throwable e, Object... args) {
50. Method method = _$$Nut_methodArray[flag_int];
51. List miList = _$$Nut_methodInterceptorList[flag_int];
52. boolean flag = true;
53. for (MethodInterceptor methodInterceptor : miList)
54. flag &= methodInterceptor.whenError(e, this, method, args);
55. return flag;
56. }
57.
58.}
public class Aop一$$Aop extend Aop一{

@Override
public void doSomething() throws Throwable{
try {
if (_Nut_before(188)) {
super.doSomething();
}
_Nut_after(188, null);
} catch (Exception e) {
if(_Nut_Exception(188, e))
throw e;
} catch (Throwable e) {
if(_Nut_Error(188, e))
throw e;
}
}

private static Method[] _$$Nut_methodArray;

private static List[] _$$Nut_methodInterceptorList;

private boolean _Nut_before(int flag_int, Object... args) {
Method method = _$$Nut_methodArray[flag_int];
List miList = _$$Nut_methodInterceptorList[flag_int];
boolean flag = true;
for (MethodInterceptor methodInterceptor : miList)
flag &= methodInterceptor.beforeInvoke(this, method, args);
return flag;
}

private Object _Nut_after(int flag_int, Object src_return, Object... args) {
Method method = _$$Nut_methodArray[flag_int];
List miList = _$$Nut_methodInterceptorList[flag_int];
for (MethodInterceptor methodInterceptor : miList)
src_return = methodInterceptor.afterInvoke(this, src_return, method, args);
return src_return;
}

private boolean _Nut_Exception(int flag_int, Exception e, Object... args) {
Method method = _$$Nut_methodArray[flag_int];
List miList = _$$Nut_methodInterceptorList[flag_int];
boolean flag = true;
for (MethodInterceptor methodInterceptor : miList)
flag &= methodInterceptor.whenException(e, this, method, args);
return flag;
}

private boolean _Nut_Error(int flag_int, Throwable e, Object... args) {
Method method = _$$Nut_methodArray[flag_int];
List miList = _$$Nut_methodInterceptorList[flag_int];
boolean flag = true;
for (MethodInterceptor methodInterceptor : miList)
flag &= methodInterceptor.whenError(e, this, method, args);
return flag;
}

}

内中MethodInterceptor是步骤阻截器接口:

Java代码
一.public interface MethodInterceptor {
2.
3. /**
4. * 在被阻截步骤调用事前,将调用该步骤。 你可用经过这个步骤的回到值,来统制是不是真个的调用"被阻截步骤"。
5. *
6. * @param obj
7. * 被调用范例
8. * @param method
9. * 范例被调用步骤
10. * @param args
11. * 被调用步骤所需参数
12. * @return true,持续调用被阻截步骤。false 将不会调用被阻截步骤
13. */
14. boolean beforeInvoke(Object obj, Method method, Object... args);
15.
16. /**
17. * 你可以经过这个函数,批改被阻截步骤的回到值。默许的,你直接将 returnObj 回来即可
18. *
19. * @param obj
20. * 被调用范例
21. * @param returnObj
22. * 范例被调用步骤的回来
23. * @param method
24. * 范例被调用步骤
25. * @param args
26. * 被调用步骤所需参数
27. * @return 调用者真个将拿到的对象。 如若,你回来的对象门类是差错的,例如调用者希望失去一个 long, 但是,你阻截了这个步骤,并回到一个
28. * String,那么将发作一个门类变换的差错
29. */
30. Object afterInvoke(Object obj, Object returnObj, Method method, Object... args);
31.
32. /**
33. * 应被阻截步骤发作异常(Exception),这个步骤会被调用。
34. *
35. * @param e
36. * 异常
37. * @param obj
38. * 被调用范例
39. * @param method
40. * 被调用步骤
41. * @param args
42. * 被调用步骤所需参数
43. *
44. * @return 是不是持续抛出异常
45. */
46. boolean whenException(Exception e, Object obj, Method method, Object... args);
47.
48. /**
49. * 应被阻截步骤发作差错(Error),这个步骤会被调用。
50. *
51. * @param e
52. * 错处
53. * @param obj
54. * 被调用范例
55. * @param method
56. * 被调用步骤
57. * @param args
58. * 被调用步骤所需参数
59. *
60. * @return 是不是持续抛疏失误
61. */
62. boolean whenError(Throwable e, Object obj, Method method, Object... args);
63.
64.}
public interface MethodInterceptor {

/**
* 在被阻截步骤调用先期,将调用该步骤。 你可用经过这个步骤的回来值,来统制是不是真个的调用"被阻截步骤"。
*
* @param obj
* 被调用范例
* @param method
* 范例被调用步骤
* @param args
* 被调用步骤所需参数
* @return true,持续调用被阻截步骤。false 将不会调用被阻截步骤
*/
boolean beforeInvoke(Object obj, Method method, Object... args);

/**
* 你可以经过这个函数,批改被阻截步骤的回来值。默许的,你直接将 returnObj 回来即可
*
* @param obj
* 被调用范例
* @param returnObj
* 范例被调用步骤的回来
* @param method
* 范例被调用步骤
* @param args
* 被调用步骤所需参数
* @return 调用者真个将拿到的对象。 如若,你回到的对象部类是错处的,例如调用者希望失去一个 long, 但是,你阻截了这个步骤,并回来一个
* String,那么将产生一个部类变换的差错
*/
Object afterInvoke(Object obj, Object returnObj, Method method, Object... args);

/**
* 应被阻截步骤发作异常(Exception),这个步骤会被调用。
*
* @param e
* 异常
* @param obj
* 被调用范例
* @param method
* 被调用步骤
* @param args
* 被调用步骤所需参数
*
* @return 是不是持续抛出异常
*/
boolean whenException(Exception e, Object obj, Method method, Object... args);

/**
* 应被阻截步骤发作差错(Error),这个步骤会被调用。
*
* @param e
* 错处
* @param obj
* 被调用范例
* @param method
* 被调用步骤
* @param args
* 被调用步骤所需参数
*
* @return 是不是持续抛失误误
*/
boolean whenError(Throwable e, Object obj, Method method, Object... args);

}

美,动工!

兑现方法,用个接口来表述吧:

Java代码
一.public interface ClassEnhander{
2.
3. void addFields();
4. void addConstructors();
5. void addAopMethods();
6. void enhandMethod();
7.}
public interface ClassEnhander{

void addFields();
void addConstructors();
void addAopMethods();
void enhandMethod();
}

第一步,新建一个种Aop一$$Aop, 等一下, 是用你的字节码工具新建一个类哦,可不用打开eclipse的new class对话框了
asm示范代码:

Java代码
一.ClassWriter cw= new ClassWriter(ClassWriter.COMPUTE_MAXS);
二.cw.visit(V一_六, ACC_PUBLIC, myName, "", enhancedSuperName, new String[]{});
ClassWriter cw= new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V一_六, ACC_PUBLIC, myName, "", enhancedSuperName, new String[]{});

此中,myName乃是"Aop一$$Aop", enhancedSuperName乃是父类的名字

第二步, 安插字段(回望一下子改建后的种,可是有两个静态私有字段的哦)
asm示范代码:

Java代码
一.FieldVisitor fv = cv.visitField(ACC_PRIVATE + ACC_STATIC, "_$$Nut_methodArray", "[Ljava/lang/reflect/Method;", null, null);
二.fv.visitEnd();
FieldVisitor fv = cv.visitField(ACC_PRIVATE + ACC_STATIC, "_$$Nut_methodArray", "[Ljava/lang/reflect/Method;", null, null);
fv.visitEnd();


Java代码
一.FieldVisitor fv = cv.visitField(ACC_PRIVATE + ACC_STATIC, "_$$Nut_methodInterceptorList", "[Ljava/util/List;",
2."[Ljava/util/List;", null);
三.fv.visitEnd();
FieldVisitor fv = cv.visitField(ACC_PRIVATE + ACC_STATIC, "_$$Nut_methodInterceptorList", "[Ljava/util/List;",
"[Ljava/util/List;", null);
fv.visitEnd();

第三步,沿袭父类的结构步骤(去除private的结构步骤),记得增添父类结构步骤抛出的异常哦:
asm示范代码:

Java代码
一.MethodVisitor mv = cw.visitMethod(access, "", desc,null, expClasses);
二.mv.visitCode();
三.mv.visitVarInsn(ALOAD, 零);
四.loadArgs();
五.mv.visitMethodInsn(INVOKESPECIAL, superClassName, "", desc);
六.mv.visitInsn(RETURN);
七.mv.visitMaxs(二, 二);
八.mv.visitEnd();
MethodVisitor mv = cw.visitMethod(access, "", desc,null, expClasses);
mv.visitCode();
mv.visitVarInsn(ALOAD, 零);
loadArgs();
mv.visitMethodInsn(INVOKESPECIAL, superClassName, "", desc);
mv.visitInsn(RETURN);
mv.visitMaxs(二, 二);
mv.visitEnd();

第四步,安插Aop模板步骤(乃是那几个private的_Nut_肇端的步骤)
asm示范代码:
比如安插_Nut_whenError

Java代码
一.MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_VARARGS, "_Nut_Error", "(ILjava/lang/Throwable;[Ljava/lang/Object;)Z", null, null);
二.mv.visitCode();
三.mv.visitFieldInsn(GETSTATIC, _Nut_myName, "_$$Nut_methodArray", "[Ljava/lang/reflect/Method;");
四.mv.visitVarInsn(ILOAD, 一);
五.mv.visitInsn(AALOAD);
六.mv.visitVarInsn(ASTORE, 四);
七.mv.visitFieldInsn(GETSTATIC, _Nut_myName, "_$$Nut_methodInterceptorList", "[Ljava/util/List;");
八.mv.visitVarInsn(ILOAD, 一);
九.mv.visitInsn(AALOAD);
十.mv.visitVarInsn(ASTORE, 五);
11.mv.visitInsn(ICONST_一);
12.mv.visitVarInsn(ISTORE, 六);
13.mv.visitVarInsn(ALOAD, 五);
14.mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;");
15.mv.visitVarInsn(ASTORE, 八);
16.Label l零 = new Label();
17.mv.visitJumpInsn(GOTO, l零);
18.Label l一 = new Label();
19.mv.visitLabel(l一);
20.mv.visitFrame(Opcodes.F_FULL, 九, new Object[] {_Nut_myName, Opcodes.INTEGER, "java/lang/Throwable", "[Ljava/lang/Object;",
21.
22."java/lang/reflect/Method", "java/util/List", Opcodes.INTEGER, Opcodes.TOP, "java/util/Iterator"}, 零, new Object[] {});
23.mv.visitVarInsn(ALOAD, 八);
24.mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
25.mv.visitTypeInsn(CHECKCAST, "org/nutz/aop/MethodInterceptor");
26.mv.visitVarInsn(ASTORE, 七);
27.mv.visitVarInsn(ILOAD, 六);
28.mv.visitVarInsn(ALOAD, 七);
29.mv.visitVarInsn(ALOAD, 二);
30.mv.visitVarInsn(ALOAD, 零);
31.mv.visitVarInsn(ALOAD, 四);
32.mv.visitVarInsn(ALOAD, 三);
33.mv.visitMethodInsn(INVOKEINTERFACE, "org/nutz/aop/MethodInterceptor", "whenError",
34.
35."(Ljava/lang/Throwable;Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Z");
36.mv.visitInsn(IAND);
37.mv.visitVarInsn(ISTORE, 六);
38.mv.visitLabel(l零);
39.mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
40.mv.visitVarInsn(ALOAD, 八);
41.mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
42.mv.visitJumpInsn(IFNE, l一);
43.mv.visitVarInsn(ILOAD, 六);
44.mv.visitInsn(IRETURN);
45.mv.visitMaxs(六, 九);
46.mv.visitEnd();
MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_VARARGS, "_Nut_Error", "(ILjava/lang/Throwable;[Ljava/lang/Object;)Z", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, _Nut_myName, "_$$Nut_methodArray", "[Ljava/lang/reflect/Method;");
mv.visitVarInsn(ILOAD, 一);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ASTORE, 四);
mv.visitFieldInsn(GETSTATIC, _Nut_myName, "_$$Nut_methodInterceptorList", "[Ljava/util/List;");
mv.visitVarInsn(ILOAD, 一);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ASTORE, 五);
mv.visitInsn(ICONST_一);
mv.visitVarInsn(ISTORE, 六);
mv.visitVarInsn(ALOAD, 五);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;");
mv.visitVarInsn(ASTORE, 八);
Label l零 = new Label();
mv.visitJumpInsn(GOTO, l零);
Label l一 = new Label();
mv.visitLabel(l一);
mv.visitFrame(Opcodes.F_FULL, 九, new Object[] {_Nut_myName, Opcodes.INTEGER, "java/lang/Throwable", "[Ljava/lang/Object;",

"java/lang/reflect/Method", "java/util/List", Opcodes.INTEGER, Opcodes.TOP, "java/util/Iterator"}, 零, new Object[] {});
mv.visitVarInsn(ALOAD, 八);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, "org/nutz/aop/MethodInterceptor");
mv.visitVarInsn(ASTORE, 七);
mv.visitVarInsn(ILOAD, 六);
mv.visitVarInsn(ALOAD, 七);
mv.visitVarInsn(ALOAD, 二);
mv.visitVarInsn(ALOAD, 零);
mv.visitVarInsn(ALOAD, 四);
mv.visitVarInsn(ALOAD, 三);
mv.visitMethodInsn(INVOKEINTERFACE, "org/nutz/aop/MethodInterceptor", "whenError",

"(Ljava/lang/Throwable;Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Z");
mv.visitInsn(IAND);
mv.visitVarInsn(ISTORE, 六);
mv.visitLabel(l零);
mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
mv.visitVarInsn(ALOAD, 八);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
mv.visitJumpInsn(IFNE, l一);
mv.visitVarInsn(ILOAD, 六);
mv.visitInsn(IRETURN);
mv.visitMaxs(六, 九);
mv.visitEnd();

第五步,压轴戏,覆写急需Aop阻截的步骤:
第一,急需处置第一个偏题: 有无回来值
至于无回来值的步骤,解决方案比较简单:
asm示范代码:

Java代码
一.MethodVisitor mv = cw.visitMethod(methodAccess, methodName,methodDesc,null, convertExp(method.getExceptionTypes()));
二.mv.visitCode();
三.Label l零 = new Label();
四.Label l一 = new Label();
五.Label l二 = new Label();
6. mv.visitTryCatchBlock(l零, l一, l二, "java/lang/Exception");
7. Label l三 = new Label();
8. mv.visitTryCatchBlock(l零, l一, l三, "java/lang/Throwable");
9. mv.visitLabel(l零);
10. mv.visitVarInsn(ALOAD, 零);
11. mv.visitIntInsn(SIPUSH, methodIndex);
12. loadArgsAsArray();
13. mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_before", "(I[Ljava/lang/Object;)Z");
14. Label l四 = new Label();
15. mv.visitJumpInsn(IFEQ, l四);
16. mv.visitVarInsn(ALOAD, 零);
17. loadArgs();
18. mv.visitMethodInsn(INVOKESPECIAL, enhancedSuperName, methodName, desc);
19. mv.visitLabel(l四);
20. mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
21. mv.visitVarInsn(ALOAD, 零);
22. mv.visitIntInsn(SIPUSH, methodIndex);
23. mv.visitInsn(ACONST_NULL);
24. loadArgsAsArray();
25. mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_after", "(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
26. mv.visitInsn(POP);
27. mv.visitLabel(l一);
28. Label l五 = new Label();
29. mv.visitJumpInsn(GOTO, l五);
30. mv.visitLabel(l二);
31. mv.visitFrame(Opcodes.F_SAME一, 零, null, 一, new Object[] {"java/lang/Exception"});
32. mv.visitVarInsn(ASTORE, lastIndex);
33. mv.visitVarInsn(ALOAD, 零);
34. mv.visitIntInsn(SIPUSH, methodIndex);
35. mv.visitVarInsn(ALOAD, lastIndex);
36. loadArgsAsArray();
37. mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_Exception", "(ILjava/lang/Exception;[Ljava/lang/Object;)Z");
38. mv.visitJumpInsn(IFEQ, l五);
39. mv.visitVarInsn(ALOAD, lastIndex);
40. mv.visitInsn(ATHROW);
41. mv.visitLabel(l三);
42. mv.visitFrame(Opcodes.F_SAME一, 零, null, 一, new Object[] {"java/lang/Throwable"});
43. mv.visitVarInsn(ASTORE, lastIndex);
44. mv.visitVarInsn(ALOAD, 零);
45. mv.visitIntInsn(SIPUSH, methodIndex);
46. mv.visitVarInsn(ALOAD, lastIndex);
47. loadArgsAsArray();
48. mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_Error", "(ILjava/lang/Throwable;[Ljava/lang/Object;)Z");
49. mv.visitJumpInsn(IFEQ, l五);
50. mv.visitVarInsn(ALOAD, lastIndex);
51. mv.visitInsn(ATHROW);
52. mv.visitLabel(l五);
53. mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
54. mv.visitInsn(RETURN);
55. mv.visitMaxs(一, 一); // 自动计算
56. mv.visitEnd();
MethodVisitor mv = cw.visitMethod(methodAccess, methodName,methodDesc,null, convertExp(method.getExceptionTypes()));
mv.visitCode();
Label l零 = new Label();
Label l一 = new Label();
Label l二 = new Label();
mv.visitTryCatchBlock(l零, l一, l二, "java/lang/Exception");
Label l三 = new Label();
mv.visitTryCatchBlock(l零, l一, l三, "java/lang/Throwable");
mv.visitLabel(l零);
mv.visitVarInsn(ALOAD, 零);
mv.visitIntInsn(SIPUSH, methodIndex);
loadArgsAsArray();
mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_before", "(I[Ljava/lang/Object;)Z");
Label l四 = new Label();
mv.visitJumpInsn(IFEQ, l四);
mv.visitVarInsn(ALOAD, 零);
loadArgs();
mv.visitMethodInsn(INVOKESPECIAL, enhancedSuperName, methodName, desc);
mv.visitLabel(l四);
mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
mv.visitVarInsn(ALOAD, 零);
mv.visitIntInsn(SIPUSH, methodIndex);
mv.visitInsn(ACONST_NULL);
loadArgsAsArray();
mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_after", "(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
mv.visitInsn(POP);
mv.visitLabel(l一);
Label l五 = new Label();
mv.visitJumpInsn(GOTO, l五);
mv.visitLabel(l二);
mv.visitFrame(Opcodes.F_SAME一, 零, null, 一, new Object[] {"java/lang/Exception"});
mv.visitVarInsn(ASTORE, lastIndex);
mv.visitVarInsn(ALOAD, 零);
mv.visitIntInsn(SIPUSH, methodIndex);
mv.visitVarInsn(ALOAD, lastIndex);
loadArgsAsArray();
mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_Exception", "(ILjava/lang/Exception;[Ljava/lang/Object;)Z");
mv.visitJumpInsn(IFEQ, l五);
mv.visitVarInsn(ALOAD, lastIndex);
mv.visitInsn(ATHROW);
mv.visitLabel(l三);
mv.visitFrame(Opcodes.F_SAME一, 零, null, 一, new Object[] {"java/lang/Throwable"});
mv.visitVarInsn(ASTORE, lastIndex);
mv.visitVarInsn(ALOAD, 零);
mv.visitIntInsn(SIPUSH, methodIndex);
mv.visitVarInsn(ALOAD, lastIndex);
loadArgsAsArray();
mv.visitMethodInsn(INVOKESPECIAL, myName, "_Nut_Error", "(ILjava/lang/Throwable;[Ljava/lang/Object;)Z");
mv.visitJumpInsn(IFEQ, l五);
mv.visitVarInsn(ALOAD, lastIndex);
mv.visitInsn(ATHROW);
mv.visitLabel(l五);
mv.visitFrame(Opcodes.F_SAME, 零, null, 零, null);
mv.visitInsn(RETURN);
mv.visitMaxs(一, 一); // 自动计算
mv.visitEnd();

关于有回到值的步骤,分三种状况, 回来Object(仅仅指这类步骤 public Object dz()),回来根本数据部类,回到其余对象(如回来数组,字符串,枚举,接口,除

Object外的对象)
回来值为Object时,把_Nut_after的回来值直接回来即可,应抛出异常等,则回来null
回到值为根本数据部类时,如int/long/double,把_Nut_after的回来值解包,应抛出异常等,则回来零/false
回到值为其余对象时, 把_Nut_after的回到值 check cast一下子,进展强转即可.

解包的代码:

Java代码
一.if(type.equals(Type.BOOLEAN_TYPE)){
2. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
3. }else if(type.equals(Type.BYTE_TYPE)){
4. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
5. }else if(type.equals(Type.CHAR_TYPE)){
6. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
7. }else if(type.equals(Type.SHORT_TYPE)){
8. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
9. }else if(type.equals(Type.INT_TYPE)){
10. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
11. }else if(type.equals(Type.LONG_TYPE)){
12. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
13. }else if(type.equals(Type.FLOAT_TYPE)){
14. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
15. }else if(type.equals(Type.DOUBLE_TYPE)){
16. mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
17. }
if(type.equals(Type.BOOLEAN_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
}else if(type.equals(Type.BYTE_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
}else if(type.equals(Type.CHAR_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
}else if(type.equals(Type.SHORT_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
}else if(type.equals(Type.INT_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
}else if(type.equals(Type.LONG_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
}else if(type.equals(Type.FLOAT_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
}else if(type.equals(Type.DOUBLE_TYPE)){
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
}

对了对了, 再有一个难题, 处置步骤的参数列表,因为_Nut_XXX接受的是Object...args,即一个Object[].
问题就来了, 如其内中某个参数是根本部类呢?恩, 那就得封包了

封包的代码:

Java代码
一.if(type.equals(Type.BOOLEAN_TYPE)){
2. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
3. }else if(type.equals(Type.BYTE_TYPE)){
4. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
5. }else if(type.equals(Type.CHAR_TYPE)){
6. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
7. }else if(type.equals(Type.SHORT_TYPE)){
8. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
9. }else if(type.equals(Type.INT_TYPE)){
10. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
11. }else if(type.equals(Type.LONG_TYPE)){
12. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
13. }else if(type.equals(Type.FLOAT_TYPE)){
14. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
15. }else if(type.equals(Type.DOUBLE_TYPE)){
16. mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
17. }
if(type.equals(Type.BOOLEAN_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
}else if(type.equals(Type.BYTE_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
}else if(type.equals(Type.CHAR_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}else if(type.equals(Type.SHORT_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
}else if(type.equals(Type.INT_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}else if(type.equals(Type.LONG_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
}else if(type.equals(Type.FLOAT_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
}else if(type.equals(Type.DOUBLE_TYPE)){
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
}

参数转向Object[]的代码:

Java代码
一.int index = getArgIndex(零);
2. for (int i = 零; i < argumentTypes.length; i++) {
3. mv.visitInsn(DUP);
4. visitX(i);
5. Type t = argumentTypes[i];
6. loadInsn(t, index);
7. index += t.getSize();
8. packagePrivateData(t);
9. mv.visitInsn(AASTORE);
10. }
int index = getArgIndex(零);
for (int i = 零; i < argumentTypes.length; i++) {
mv.visitInsn(DUP);
visitX(i);
Type t = argumentTypes[i];
loadInsn(t, index);
index += t.getSize();
packagePrivateData(t);
mv.visitInsn(AASTORE);
}
此中visitX为

Java代码
一.void visitX(int i){
2. if(i < 六){
3. mv.visitInsn(i + ICONST_零);
4. }else{
5. mv.visitIntInsn(BIPUSH, i);
6. }
7.}
void visitX(int i){
if(i < 六){
mv.visitInsn(i + ICONST_零);
}else{
mv.visitIntInsn(BIPUSH, i);
}
}
最后,完成!!

附具体兑现(基于asm): [url]http://code.google.com/p/nutzlab/source/browse/#svn/trunk/Nutz.Aop-ASM/Nutz.Aop-ASM[/curl
也许参照除此以外一篇博文: http://wendal.javaeye.com/blog/543681


本文来源:
我的异常网
Java Exception
Dotnet Exception
Oracle Exception

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值