Spring 中AOP 特性詳解

Spring 框架的設計理念與設計模式分析--- SpringAOP 特性詳解


動態代理的實現原理

要了解 Spring AOP 就必須先了解的動態代理的原理,因爲 AOP 就是基於動態代理實現的。動態代理還要從 JDK 本身說起。

Jdk java.lang.reflect 包下有個 Proxy 類,它正是構造代理類的入口。這個類的結構入下:


16. Proxy 類結構

從上圖發現最後面四個是公有方法。而最後一個方法 newProxyInstance 就是創建代理對象的方法。這個方法的源碼如下:


清單 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());

}

}

這個方法需要三個參數:ClassLoader,用於加載代理類的 Loader 類,通常這個 Loader 和被代理的類是同一個 Loader 類。Interfaces,是要被代理的那些那些接口。InvocationHandler,就是用於執行除了被代理接口中方法之外的用戶自定義的操作,他也是用戶需要代理的最終目的。用戶調用目標方法都被代理到 InvocationHandler 類中定義的唯一方法 invoke 中。這在後面再詳解。

下面還是看看 Proxy 如何產生代理類的過程,他構造出來的代理類到底是什麼樣子?下面揭曉啦。


17. 創建代理對象時序圖

其實從上圖中可以發現正在構造代理類的是在 ProxyGenerator generateProxyClass 的方法中。ProxyGenerator 類在 sun.misc 包下,感興趣的話可以看看他的源碼。

假如有這樣一個接口,如下:


清單 7. SimpleProxy

public interface SimpleProxy {

public void simpleMethod1();

public void simpleMethod2();

}

代理來生成的類結構如下:


清單 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();

}

這個類中的方法裏面將會是調用 InvocationHandler invoke 方法,而每個方法也將對應一個屬性變量,這個屬性變量 m 也將傳給 invoke 方法中的 Method 參數。整個代理就是這樣實現的。

Spring AOP 如何實現

從前面代理的原理我們知道,代理的目的是調用目標方法時我們可以轉而執行 InvocationHandler 類的 invoke 方法,所以如何在 InvocationHandler 上做文章就是 Spring 實現 Aop 的關鍵所在。

Spring Aop 實現是遵守 Aop 聯盟的約定。同時 Spring 又擴展了它,增加了如 PointcutAdvisor 等一些接口使得更加靈活。

下面是 Jdk 動態代理的類圖:


18. Jdk 動態代理的類圖

上圖清楚的顯示了 Spring 引用了 Aop Alliance 定義的接口。姑且不討論 Spring 如何擴展 Aop Alliance,先看看 Spring 如何實現代理類的,要實現代理類在 Spring 的配置文件中通常是這樣定一個 Bean 的,如下:


清單 9. 配置代理類 Bean

<bean id="testBeanSingleton"

class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="proxyInterfaces">

<value>

org.springframework.aop.framework.PrototypeTargetTests$TestBean

</value>

</property>

<property name="target"><ref local="testBeanTarget"></ref> </property>

<property name="singleton"><value>true</value></property>

<property name="interceptorNames">

<list>

<value>testInterceptor</value>

<value>testInterceptor2</value>

</list>

</property>

</bean>

配置上看到要設置被代理的接口,和接口的實現類也就是目標類,以及攔截器也就在執行目標方法之前被調用,這裏 Spring 中定義的各種各樣的攔截器,可以選擇使用。

下面看看 Spring 如何完成了代理以及是如何調用攔截器的。

前面提到 Spring Aop 也是實現其自身的擴展點來完成這個特性的,從這個代理類可以看出它正是繼承了 FactoryBean ProxyFactoryBeanFactoryBean 之所以特別就在它可以讓你自定義對象的創建方法。當然代理對象要通過 Proxy 類來動態生成。

下面是 Spring 創建的代理對象的時序圖:


19.Spring 代理對象的產生

Spring 創建了代理對象後,當你調用目標對象上的方法時,將都會被代理到 InvocationHandler 類的 invoke 方法中執行,這在前面已經解釋。在這裏 JdkDynamicAopProxy 類實現了 InvocationHandler 接口。

下面再看看 Spring 是如何調用攔截器的,下面是這個過程的時序圖:


20.Spring 調用攔截器

以上所說的都是 Jdk 動態代理,Spring 還支持一種 CGLIB 類代理,感興趣自己看吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章