Spring中AOP特性詳解
動(dòng)態(tài)代理的實(shí)現(xiàn)原理
要了解Spring的AOP就必須先了解的動(dòng)態(tài)代理的原理,因?yàn)锳OP就是基于動(dòng)態(tài)代理實(shí)現(xiàn)的。動(dòng)態(tài)代理還要從JDK本身說(shuō)起。
在Jdk的java.lang.reflect包下有個(gè)Proxy類,它正是構(gòu)造代理類的入口。這個(gè)類的結(jié)構(gòu)入下:

圖16.Proxy類結(jié)構(gòu)
從上圖發(fā)現(xiàn)最后面四個(gè)是公有方法。而最后一個(gè)方法newProxyInstance就是創(chuàng)建代理對(duì)象的方法。這個(gè)方法的源碼如下:
清單6.Proxy.newProxyInstance
public static Object newProxyInstance(ClassLoader loader,
Class> [] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
if (h == null) {
throw new NullPointerException();
}
Class cl = getProxyClass (loader, interfaces);
try {
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
} !
這個(gè)方法需要三個(gè)參數(shù):ClassLoader,用于加載代理類的Loader類,通常這個(gè)Loader和被代理的類是同一個(gè)Loader類。Interfaces,是要被代理的那些那些接口。InvocationHandler,就是用于執(zhí)行 除了被代理接口中方法之外的用戶自定義的操作,他也是用戶需要代理的最終目的。用戶調(diào)用目標(biāo)方法都被代理到InvocationHandler類中定義的唯一方法invoke中。這在后面再詳解。
下面還是看看Proxy如何產(chǎn)生代理類的過(guò)程,他構(gòu)造出來(lái)的代理類到底是什么樣子?下面揭曉啦。

圖17.創(chuàng)建代理對(duì)象時(shí)序圖
其實(shí)從上圖中可以發(fā)現(xiàn)正在構(gòu)造代理類的是在ProxyGenerator的generateProxyClass的方法中。ProxyGenerator類在sun.misc包下,感興趣的話可以看看他的源碼。
假如有這樣一個(gè)接口,如下:
清單7.SimpleProxy類
public interface SimpleProxy {
public void simpleMethod1();
public void simpleMethod2();
}
代理來(lái)生成的類結(jié)構(gòu)如下:
清單 8.$Proxy2類
public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{
java.lang.reflect.Method m0;
java.lang.reflect.Method m1;
java.lang.reflect.Method m2;
java.lang.reflect.Method m3;
java.lang.reflect.Method m4;
int hashCode();
boolean equals(java.lang.Object);
java.lang.String toString();
void simpleMethod1();
void simpleMethod2();
}
這個(gè)類中的方法里面將會(huì)是調(diào)用InvocationHandler的invoke方法,而每個(gè)方法也將對(duì)應(yīng)一個(gè)屬性變量,這個(gè)屬性變量m也將傳給invoke方法中的Method參數(shù)。整個(gè)代理就是這樣實(shí)現(xiàn)的。
SpringAOP如何實(shí)現(xiàn)
從前面代理的原理我們知道,代理的目的是調(diào)用目標(biāo)方法時(shí)我們可以轉(zhuǎn)而執(zhí)行InvocationHandler類的invoke方法,所以如何在InvocationHandler上做文章就是Spring實(shí)現(xiàn)Aop的關(guān)鍵所在。
Spring的Aop實(shí)現(xiàn)是遵守Aop聯(lián)盟的約定。同時(shí)Spring又?jǐn)U展了它,增加了如Pointcut、Advisor等一些接口使得更加靈活。
下面是Jdk動(dòng)態(tài)代理的類圖:

圖18.Jdk動(dòng)態(tài)代理的類圖
上圖清楚的顯示了Spring引用了Aop Alliance定義的接口。姑且不討論Spring如何擴(kuò)展Aop Alliance,先看看Spring如何實(shí)現(xiàn)代理類的,要實(shí)現(xiàn)代理類在Spring的配置文件中通常是這樣定一個(gè)Bean的 ,如下:
清單9.配置代理類Bean
class="org.springframework.aop.framework.ProxyFactoryBean">
org.springframework.aop.framework.PrototypeTargetTests$TestBean
value>
property>
ref> property>