Spring AOP 增強介紹
目錄
advance,通知,在Spring中叫增強也許更加合理。所謂增強,其實就是向各個程式內部注入一些程式碼從而增強原有程式的功能。
Spring使用增強類定義橫切邏輯,同時由於Spring只支援方法連線點,增強還包括在方法的哪一點加入橫切程式碼的方位資訊,所以增強即包括橫切邏輯,又包含部分連線點的資訊。
按照增強在目標類方法連線點的位置可以將增強劃分為以下五類:
增強名稱 | 介面 | 描述 |
前置增強 |
org.springframework.aop.BeforeAdvice 因為Spring只支援方法級的增強,所以MethodBeforeAdvance介面是目前可用的前置增強。 |
在目標方法執行前來實施增強 |
後置增強 | org.springframework.aop.AfterReturningAdvice | 在目標方法執行後來實施增強 |
環繞增強 | org.aopalliance.intercept.MethodInterceptor | 在目標方法執行前、後實施增強。環繞增強是AOP聯盟定義的介面,其他四種增強介面則是Spring定義的介面。 |
異常丟擲增強 | org.springframework.aop.ThrowsAdvice | 在目標方法丟擲異常後來實施增強 |
引介增強 | org.springframework.aop.Introductioninterceptor | 表示在目標類中新增一些新的方法和屬性。引介增強是一種特殊的增強。他可以在目標類中新增屬性和方法,通過攔截定義一個介面,讓目標代理實現這個介面。他的連線點是類級別的,而前面的幾種則是方法級別的。 |
通過實現這些增強介面,在實現這些介面的方法當中定義橫切邏輯,就可以將它們織入目標類方法的相應連線點位置。
一、前置增強
增強目標類
public class NativeWaiter {
public void greetTo(String name) {
System.out.println("greet to " + name + "...");
}
public void serveTo(String name) {
System.out.println("serving to " + name + "...");
}
}
增強類,實現 MethodBeforeAdvice 介面
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
/**
* 前置增強方法
* 當該方法發生異常時,將阻止目標方法的執行
*
* @param method 目標類方法
* @param objects 目標類方法入參
* @param o 目標類物件例項
*/
public void before(Method method, Object[] objects, Object o) throws Throwable {
String name = (String) objects[0];
System.out.println("How are you!Mr." + name + ".");
}
}
測試類,使用cglib生成代理物件
@Test
public void before_cglib_proxy() {
//建立目標物件
NativeWaiter target = new NativeWaiter();
//建立前置增強器
BeforeAdvice advice = new GreetingBeforeAdvice();
//建立代理工廠物件
ProxyFactory pf = new ProxyFactory();
//設定代理類
pf.setTarget(target);
//也可以啟動優化代理方式,會使用cglib來生成代理。當使用介面時,只要呼叫了該方法,都會使用cglib方式來生成代理物件
//pf.setOptimize(true);
//設定增強類
pf.addAdvice(advice);
//生成代理例項
NativeWaiter proxy = (NativeWaiter) pf.getProxy();
proxy.greetTo("John");
proxy.serveTo("Tom");
}
執行結果
How are you!Mr.John.
greet to John...
How are you!Mr.Tom.
serving to Tom...
總結:
1、增強器類,實現 MethodBeforeAdvice 介面;
2、利用Spring的ProxyFactory,加入代理目標和增強類,然後生成代理物件;
二、ProxyFactory介紹
1、基本使用
其實ProxyFactory代理技術就是利用jdk代理或者cglib代理的技術,將增強應用到目標類當中。
Spring定義的AopProxy介面具有兩個final型別的實現類:
CglibAopProxy : 是使用cglib代理技術來建立代理
JdkDynamicAopProxy : 是使用jdk代理技術來建立代理
使用proxyFactory.setInterfaces(target.getClass().getInterfaces())的方法指定目標介面進行代理,則ProxyFactory使用JdkDynamicAopProxy;如果針對類的代理,則使用CglibAopProxy,此外還可以通過ProxyFactory的setOptimize(true)方法啟動優化代理方式,這樣針對介面的代理也會使用CglibAopProxy。比如上面的前置增強BeforeAdviceTest就是使用CglibAopProxy來生成動態代理類的。
那麼使用JDK代理如何來實現的呢?程式碼如下:
首先,定義介面Waiter,並讓NaiveWaiter實現該介面
public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}
public class NaiveWaiter implements Waiter {
//該類具體實現程式碼不變
}
然後,使用jdk代理具體實現方法
@Test
public void before_jdk_proxy() {
//建立目標物件
Waiter target = new NaiveWaiter();
//建立前置增強器
BeforeAdvice advice = new GreetingBeforeAdvice();
//建立代理工廠物件
ProxyFactory pf = new ProxyFactory();
//設定代理介面
pf.setInterfaces(target.getClass().getInterfaces());
//設定代理類
pf.setTarget(target);
//設定增強類
pf.addAdvice(advice);
//生成代理例項
Waiter proxy = (Waiter) pf.getProxy();
proxy.greetTo("John");
proxy.serveTo("Tom");
}
如上ProxyFactory.setInterfaces(target.getClass().getInterfaces())方法,該方法會獲取到介面並將其載入進去。當目標物件如果沒有實現任何介面時,那麼即使使用了該方法,生成代理物件時也是使用CglibAopProxy來生成的。如果目標物件實現了一個介面,那麼ProxyFactory.getProxy()方法,返回物件必須轉換成介面型別。
ProxyFactory通過addAdvice來增加一個增強。使用者可以使用該方法增加多個增強,通過增強形成一個增強鏈,他們的呼叫順序和新增順序是一致的
2、Spring通過配置檔案實現增強
在bean.xml配置檔案中進行如下配置
<bean id="gerrtingBefore" class=" demo04.advance.GreetingBeforeAdvice"/>
<bean id="target" class="demo04.advance.NativeWaiter"/>
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="demo04.advance.Waiter"
p:interceptorNames="gerrtingBefore"
p:target-ref="target"
/>
根據以上配置資訊,介紹下ProxyFactoryBean配置檔案當中常用的屬性:
target:我們需要代理的目標物件
proxyInterfaces:代理所要實現的介面,可以是多個介面
interceptorNames:需要織入的目標物件的Bean的列表(增強類的Bean列表),使用Bean的名稱來指定。
singleton:確定返回的代理是不是單例項的,系統預設返回的是單例項的。
optimize:當值為true時,強制使用cglib代理。當是singleton的例項時我們推薦使用cglib代理,當是其他作用域的時候,推薦使用JDK的代理。原因是cglib建立代理速度比較慢,但是執行效率高。JDK代理則剛好相反。
proxyTargetClass:是否對類進行代理而不是對介面進行代理,當值為true的時候使用cglib代理。
測試程式碼:
@Test
public void before_advice_xml_test() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans/beans.xml");
Waiter waiter = context.getBean("waiter", Waiter.class);
waiter.greetTo("JayChou");
}
三、後置增強和異常增強
在上面的例子中,前置增強實現了MethodBeforeAdvice介面,後置增強、異常增強和前置增強一樣,只需實現相應的介面就可以了。
四、環繞增強
實現介面MethodInterceptor,其他與前置增強一樣
public class GreetingInterceptor implements MethodInterceptor{
/**
* 業務邏輯實現類
* @param methodInvocation 封裝了目標方法和入引數組以及目標方法所帶的例項物件
* @return 代理物件
* @throws Throwable
*/
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//獲取目標方法的入參
Object[] args=methodInvocation.getArguments();
//獲取方法名稱
String clickName= (String) args[0];
System.out.println("GreetingInterceptor:How are you!");
//利用反射機制來呼叫目標方法
Object object=methodInvocation.proceed();
System.out.println("GreetingInterceptor: please enjoy youself!");
return object;
}
}
五、引介增強
引介增強的連線點是類級別的而非方法級別的,通過引介增強我們可以為目標類新增一個介面的實現即原來目標類未實現某個介面,那麼通過引介增強可以為目標類建立實現某介面的代理。Spring為引介增強提供了Introductioninterceptor介面,該介面未提供任何方法,所以一般在它的實現類DelegatingIntroductionInterceptor中進行擴充套件。
總結:
1、按照增強在目標類方法連線點的位置可以將增強劃分為五類:前置增強、後置增強、環繞增強、異常增強、引介增強;
2、Spring定義了內部代理工廠類ProxyFactory,它利用jdk代理或者cglib代理的技術,將增強應用到目標類當中。
3、Spring定義的AopProxy介面具有兩個final型別的實現類:
CglibAopProxy : 是使用cglib代理技術來建立代理
JdkDynamicAopProxy : 是使用jdk代理技術來建立代理
4、實現一個目標類的增強,首先實現增強相關介面,然後將目標類和增強物件放入代理工廠中,最後代理工廠生成代理物件;
相關文章
- Spring AOP介紹Spring
- 4、Spring+AOP介紹與使用Spring
- Spring AOP 使用介紹,從前世到今生Spring
- Spring基礎只是—AOP的概念介紹Spring
- FreeSql aop功能介紹SQL
- Spring(2)-AOP簡介Spring
- Spring AOP學習筆記03:AOP的核心實現之獲取增強器Spring筆記
- AOP的簡單介紹
- Spring AOP基礎簡介Spring
- Spring WebApplicationContext 介紹SpringWebAPPContext
- Spring Cache 介紹Spring
- Spring AOT介紹Spring
- 基於SAP Kyma的訂單編排增強介紹
- 第70篇 AOP的簡單介紹
- Spring框架學習筆記(一):官方文件介紹,IoC與AOP概念學習Spring框架筆記
- Spring Data JDBC介紹SpringJDBC
- spring框架的介紹Spring框架
- AOP - 自己寫 JDK 動態代理增強 beanJDKBean
- 《AOP挖掘記》概念介紹及原理初探(一)
- Spring第9天Aop簡介,Aopxml開發,Aop註解開發SpringXML
- Spring事物入門簡介及AOP陷阱分析Spring
- 開源speex的語音增強(去噪)演算法介紹演算法
- FastWiki(增強AI對話功能)企業級智慧客服功能介紹ASTAI
- Spring bean詳細介紹SpringBean
- Spring BeanFactory與ApplicationContext 介紹SpringBeanAPPContext
- Spring Shell入門介紹Spring
- Spring框架之IOC介紹Spring框架
- (2)Spring Cloud版本介紹SpringCloud
- spring-boot-starters介紹Springboot
- [Spring]AOPSpring
- spring AOPSpring
- Spring Boot學習(一)——Spring Boot介紹Spring Boot
- 使用aop來監控方法進行增強處理
- 介紹Spring Cloud斷路器SpringCloud
- Spring的Factories機制介紹Spring
- Java之Spring Cloud概念介紹JavaSpringCloud
- Spring Cloud 中的元件介紹SpringCloud元件
- Spring Reactor基本介紹和案例SpringReact