標籤:location 聯合 servet ack aspectj 目標 stat 不同 exe
在前面我們使用Pointcut和Advice描述切點和增強, 並使用Advisor整合兩者描述切面[email protected]使用註解來描述切點和增強.兩者使用的方式不同, 但是在本質上都是一樣的.
我們還是用以前的例子來舉例, 學習如何使用@AspectJ來描述切點和增強.首先看一個簡單的例子.
package com.bao.bao.aspectj;/** * Created by xinfengyao on 16-10-23. */public interface Waiter { public void greetTo(String clientName); public void serveTo(String clientName);}
package com.bao.bao.aspectj;/** * Created by xinfengyao on 16-10-23. */public class NaiveWaiter implements Waiter { @Override public void greetTo(String clientName) { System.out.println("NaiveWaiter greetTo " + clientName + "..."); } @Override public void serveTo(String clientName) { System.out.println("NaiveWaiter serveTo " + clientName + "..."); }}
下面我們使用AspectJ定義一個切面
package com.bao.bao.aspectj;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;/** * Created by xinfengyao on 16-10-23. */@Aspectpublic class PreGreetingAspect { @Before("execution(* greetTo(..))") public void beforeGreeting() { System.out.println("Here are you!"); }}
我們發現, 這個類沒用實現任何特殊的介面, 只是一個普通的POJO, 特殊之處是使用了@AspectJ註解.
首先在PreGreetingAspect上面標註了@Aspect的註解, 第三方程式就可以使用這個註解來判斷某個類是否是一個切面;其次, 我們在beforeGreeting()方法上面標註了註解@Before, 並提供了參數execution(*greetTo(..), 這個註解提供了兩個資訊, @Before註解表示該增強是一個前置增強,而成員值是一個AspectJ運算式, 含義是:在目標類的greetTo()方法上織入增強, greetTo()方法可以帶任意的入參和返回任意值;最後在beforeGreeting()方法中定義的就是增強邏輯, 該橫切邏輯在目標方法前調用.
PreGreetingAspect通過註解, 將切點, 增強類型和增強邏輯糅合在一起, 是切面的定義渾然天成.PreGreetingAspect就相當於我們之前定義的BeforeAdvice, NameMatchMethodPointcut以及DefaultPointcutAdvisor聯合表達的資訊.
下面我們通過org.springframework.aop.aspectj.annotation.AspectJProxyFactory為NaiveWaiter產生織入PreGreetingAspect切面的代理.
package com.bao.bao.aspectj;import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;/** * Created by xinfengyao on 16-10-23. */public class AspectJProxyTest { public static void main(String[] args) { AspectJProxyFactory proxyFactory = new AspectJProxyFactory(); Waiter target = new NaiveWaiter(); proxyFactory.setTarget(target); proxyFactory.addAspect(PreGreetingAspect.class); Waiter proxy = proxyFactory.getProxy(); proxy.greetTo("tom"); proxy.serveTo("marry"); }}
運行結果:
Here are you!NaiveWaiter greetTo tom...NaiveWaiter serveTo marry...
通過輸出資訊我們可以看到, 代理對象的greetTo()方法已經織入了切面類所定義的橫切邏輯.
雖然可以通過編程的方式織入切面, 但一般都是通過spring設定檔的方式完成織入切面的工作.
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" 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="waiter" class="com.bao.bao.aspectj.NaiveWaiter"/> <bean class="com.bao.bao.aspectj.PreGreetingAspect"/> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/></beans>
在前面我們介紹過兩種自動代理建立器, AnnotationAwareAspectJAutoProxyCreator能夠將@AspectJ註解的切面自動織入到目標bean中.
如果使用基於schema的aop命名空間進行配置就更簡單了.
<bean id="waiter" class="com.bao.bao.aspectj.NaiveWaiter"/> <bean class="com.bao.bao.aspectj.PreGreetingAspect"/> <aop:aspectj-autoproxy/>
通過aop命名空間的<aop:aspectj-autoproxy/>自動為spring容器中的那些匹配@AspectJ切面的bean自動建立代理, 完成切面織入.其實spring在內部的原理還是使用AnnotationAwareAspectJAutoProxyCreator進行自動代理的建立工作.
基於@AspectJ和schema的aop(一)