读书人

JDK Proxy AOP兑现

发布时间: 2012-10-09 10:21:45 作者: rapoo

JDK Proxy AOP实现
JDK Proxy AOP实现

java.lang.reflect.Proxy,
Proxy 提供用于创建动态代理类和实例的静态方法. 只能针对接口创建代理
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
(详见api文档)

java.lang.reflect.InvocationHandler,
InvocationHandler 是代理实例的调用处理程序 实现的接口。
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

?

动态代理的使用代码示例如下:?1?public?static?void?main(String[]?args)?{
?2?????????
?3?????????InvocationHandler?ih?=?new?InvocationHandler()?{
?4?
?5?????????????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)
?6?????????????????????throws?Throwable?{
?7?????????????????//?拦截方法处理
?8?????????????????return?null;
?9?????????????}
10?????????????
11?????????};
12?????????
13?????????Class<?>[]?interfaces?=?new?Class<?>[]?{BankAccount.class};
14?????????
15?????????BankAccount?bankAccount?=?(BankAccount)?Proxy.newProxyInstance(ProxyTest??
16?????????????????.class.getClassLoader(),?interfaces,?ih);??
17???}
18?

?

下面是动态代理生成的代码对应(通过反编译工具对字节码进行处理)

接口代码:

?

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?public?interface?BankAccount?{
?2?
?3?????boolean?deposit(BigDecimal?money);
?4?????
?5?????boolean?withdraw(BigDecimal?money);
?6?????
?7?????String?getName();
?8?????
?9?????String?getId();
10?}
11?

?

动态代理生成的字节码(反编译后的Java代码)

?

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?public?final?class?BankAccount$1?extends?Proxy?implements?BankAccount?{
?2?????private?static?Method?m6;?//?getId
?3?????private?static?Method?m4;?//?withdraw
?4?????private?static?Method?m5;?//?getName
?5?????private?static?Method?m2;?//?toString
?6?????private?static?Method?m0;?//?hashCode
?7?????private?static?Method?m3;?//?deposit
?8?????private?static?Method?m1;?//?equals
?9?
10?????public?BankAccount$1(InvocationHandler?ih)?{
11?????????super(ih);
12?????}
13?
14?????public?final?String?getId()?{
15?????????try?{
16?????????????return?(String)?this.h.invoke(this,?m6,?null);
17?????????}?catch?(RuntimeException?e)?{
18?????????????throw?e;
19?????????}?catch?(Throwable?t)?{
20?????????????throw?new?UndeclaredThrowableException(t);
21?????????}
22?????}
23?
24?????public?final?boolean?withdraw(BigDecimal?paramBigDecimal)?{
25?????????try?{
26?????????????return?((Boolean)?this.h.invoke(this,?m4,
27?????????????????????new?Object[]?{?paramBigDecimal?})).booleanValue();
28?????????}?catch?(RuntimeException?e)?{
29?????????????throw?e;
30?????????}?catch?(Throwable?t)?{
31?????????????throw?new?UndeclaredThrowableException(t);
32?????????}
33?????}
34?
35?????public?final?String?getName()?{
36?????????try?{
37?????????????return?(String)?this.h.invoke(this,?m5,?null);
38?????????}?catch?(RuntimeException?e)?{
39?????????????throw?e;
40?????????}?catch?(Throwable?t)?{
41?????????????throw?new?UndeclaredThrowableException(t);
42?????????}
43?????}
44?
45?????public?final?String?toString()?{
46?????????try?{
47?????????????return?(String)?this.h.invoke(this,?m2,?null);
48?????????}?catch?(RuntimeException?localRuntimeException)?{
49?????????????throw?localRuntimeException;
50?????????}?catch?(Throwable?t)?{
51?????????????throw?new?UndeclaredThrowableException(t);
52?????????}
53?????}
54?
55?????public?final?int?hashCode()?{
56?????????try?{
57?????????????return?((Integer)?this.h.invoke(this,?m0,?null)).intValue();
58?????????}?catch?(RuntimeException?e)?{
59?????????????throw?e;
60?????????}?catch?(Throwable?t)?{
61?????????????throw?new?UndeclaredThrowableException(t);
62?????????}
63?????}
64?
65?????public?final?boolean?deposit(BigDecimal?paramBigDecimal)?{
66?????????try?{
67?????????????return?((Boolean)?this.h.invoke(this,?m3,
68?????????????????????new?Object[]?{?paramBigDecimal?})).booleanValue();
69?????????}?catch?(RuntimeException?localRuntimeException)?{
70?????????????throw?localRuntimeException;
71?????????}?catch?(Throwable?localThrowable)?{
72?????????????throw?new?UndeclaredThrowableException(localThrowable);
73?????????}
74?????}
75?
76?????static?{
77?????????try?{
78?????????????m6?=?Class.forName("BankAccount").getMethod("getId",?new?Class[0]);
79?????????????m4?=?Class.forName("BankAccount").getMethod("withdraw",
80?????????????????????new?Class[]?{?Class.forName("java.math.BigDecimal")?});
81?????????????m5?=?Class.forName("BankAccount")
82?????????????????????.getMethod("getName",?new?Class[0]);
83?????????????m2?=?Class.forName("java.lang.Object").getMethod("toString",
84?????????????????????new?Class[0]);
85?????????????m0?=?Class.forName("java.lang.Object").getMethod("hashCode",
86?????????????????????new?Class[0]);
87?????????????m3?=?Class.forName("BankAccount").getMethod("deposit",
88?????????????????????new?Class[]?{?Class.forName("java.math.BigDecimal")?});
89?????????????m1?=?Class.forName("java.lang.Object").getMethod("equals",
90?????????????????????new?Class[]?{?Class.forName("java.lang.Object")?});
91?????????}?catch?(NoSuchMethodException?e)?{
92?????????????throw?new?NoSuchMethodError(e.getMessage());
93?????????}?catch?(ClassNotFoundException?e)?{
94?????????????throw?new?NoClassDefFoundError(e.getMessage());
95?????????}
96?????}
97?}
98?

?

从动态代理生成的代码可以分析得到,所有的方法的调用,都会回调InvokeHanlder接口的实现类的invoke方法,并把实际调用的反射相关信息作为参数传给invoke方法。

?

Cglib Proxy AOP实现

cglib是一个开源项目! 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Spring很多地方借助该项目实现AOP的功能封装。

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。通过使用CGLIB来为那些没有接口的类创建代理对象。

?

Cglib的Proxy与JDK Proxy还是有一定的相似的,下面的例子,给大家一个基本的演示

?

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->1?public?class?SimpleBean?{
2?
3?????public?void?hello()?{
4?????????System.out.println("hi?matthew!");
5?????}
6?}

Cglib 代理后(只给出了部分核心反编译后的Java代码)

?

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->?1?class??SimpleBean$$EnhancerByCGLIB$$4c4a66a?extends?SimpleBean?{
?2?????private??static??final??Method?CGLIB$hello$0$Method?;
?3?
?4?????public??final??void??hello(?)?{
?5?????if(!this.CGLIB$CONSTRUCTED)
?6?????{
?7???????super.hello();
?8???????return;
?9????
10?????}
11?????if(this.CGLIB$CALLBACK_0==?null)
12?????{
13???????CGLIB$BIND_CALLBACKS(this);
14????
15?????}
16?????if(this.CGLIB$CALLBACK_0!=??null)
17?????{
18???????this.CGLIB$CALLBACK_0.intercept(this,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$hello$0$Method,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$emptyArgs,SimpleBean$$EnhancerByCGLIB$$4c4a66a.CGLIB$hello$0$Proxy);
19???????return;
20????
21?????}
22?????super.hello();
23?????return;
24?????catch(RuntimeException??aRuntimeException2)
25?????{
26???????catch(Throwable??aRuntimeException2)
27???????{
28?????????UndeclaredThrowableException?JdecGenerated57?=?new?UndeclaredThrowableException(
29??}
30?}
31?
32?final????void?CGLIB$hello$0(?)?
33??{
34?????super.hello();
35?????return;
36??}
37?注: 从上面的实现代理来看,Cglib对于标识 final 关键字的class无法进行代理操作。?????? 对于标识final的方法,也无法进行代理

读书人网 >编程

热点推荐