- 概述
- 在Spring中配置
- 通過配置檔案實作增強
- 配置檔案
- ProxyFactory Bean配置檔案當中常用的屬性
- 測試類
- 其他代碼
- 通過配置檔案實作增強
概述
在上篇博文的案例中
Spring-AOP 建立增強類-前置增強
我們使用org.springframework.aop.framework.ProxyFactory通過編碼的方式将GreetingBeforeAdvice的增強織入目标類NaiveWaiter中
結合我們前面說的
Java-JDK動态代理
Java-CGLib動态代理
動态代理技術是不是很相似?
我們看下的源碼 ProxyFactoryBean#setProxyInterfaces
可以發現,ProxyFactoryBean的内部其實就是使用JDK或者CGLib動态代理技術将增強應用到目标類中的。
Spring定義的AOPProxy類具有兩個final類型的實作類,如下圖所示
- Cglib2AopProxy是使用cglib代理技術來建立代理
- JdkDynamicAopProxy是使用jdk代理技術來建立代理
如果通過ProxyFactory的setInterfaces(Class[] interfaces)方法指定目标接口進行代理,則ProxyFactory使用JdkDynamaicAopProxy,如果針對類的代理,則使用Cglib2AopProxy.
此外,還可以通過ProxyFactory的setOptimize(true)方法讓ProxyFactory啟動優化代理方式,這樣,針對接口的代理也會使用Cglib2AopProxy。
我們使用JDK代理來實作 Spring-AOP 增強(Advice)類型和建立增強類 中的業務測試類
//建立代理工廠對象
ProxyFactory factory=new ProxyFactory();
//設定代理接口
factory.setInterfaces(target.getClass().getInterfaces());
//設定代理類
factory.setTarget(target);
//設定增強類
factory.addAdvice(advice);
複制
使用CGLib代理實作則為:
ProxyFactory factory=new ProxyFactory();
//設定代理接口
factory.setInterfaces(target.getClass().getInterfaces());
//啟用優化,将啟用cglib代理方式
factory.setOptimize(true);
//設定代理類
factory.setTarget(target);
//添加增強類
factory.addAdvice(advice);
複制
ProxyFactory通過addAdvice來增加一個增強。 使用者可以使用該方法增加多個增強,通過增強形成一個增強鍊,他們的調用順序和添加順序是一緻的
在Spring中配置
代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster
通過配置檔案實作增強
配置檔案
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="target" class="com.xgj.aop.spring.advice.proxyFactory.NaiveWaiter"/>
<bean id="greetingBeforeAdvice" class="com.xgj.aop.spring.advice.proxyFactory.GreetingBeforeAdvice"/>
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.xgj.aop.spring.advice.proxyFactory.Waiter"
p:interceptorNames="greetingBeforeAdvice"
p:target-ref="target"/>
beans>
複制
ProxyFactory Bean配置檔案當中常用的屬性
- target:我們需要代理的目标對象
- proxyInterfaces:代理所要實作的接口,可以是多個接口
- interceptorNames:需要織入的目标對象的Bean的清單(增強類的Bean清單),使用Bean的名稱來指定。
- singleton:确定傳回的代理是不是單執行個體的,系統預設傳回的是單執行個體的。
- optimize:當值為true時,強制使用cglib代理。當是singleton的執行個體時我們推薦使用cglib代理,當是其他作用域的時候,推薦使用JDK的代理。原因是cglib建立代理速度比較慢,但是運作效率高。JDK代理則剛好相反。
- proxyTargetClass:是否對類進行代理而不是對接口進行代理,當值為true的時候使用cglib代理
将proxyTargetClass設定為true後,無需再設定proxyInterfaces屬性,即使設定了也會被ProxyFactory忽略
測試類
package com.xgj.aop.spring.advice.proxyFactory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeforceAdivceByXmlTest {
@Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:com/xgj/aop/spring/advice/proxyFactory/beans.xml");
Waiter waiter = ctx.getBean("waiter", Waiter.class);
waiter.greetTo("Xiao");
waiter.serverTo("GongJiang");
}
}
複制
運作單元測試:
其他代碼
業務接口類:Waiter.Java
業務實作類:NativeWaiter.java
業務增強類:GreetingBeforeAdvice.java
參考 Spring-AOP 增強(Advice)類型和建立增強類#執行個體-通過代碼實作增強