Spring AOP的三種實現方式

原文地址:http://blog.csdn.net/udbnny/article/details/5870076
三種方式分別爲:
<1>經典的基於代理的AOP
<2>@AspectJ註解的切面
<3>純POJO切面

方式一:經典的基於代理的AOP
需要如下步驟:
1.創建通知:實現這幾個接口,把其中的方法實現了
2.定義切點和通知者:在Spring配製文件中配置這些信息
3.使用ProxyFactoryBean來生成代理

具體做法:
(1.1)首先寫一個接口叫Sleepable,這是一個牛X的接口,所有具有睡覺能力的東西都可以實現該接口
public interface Sleepable{
    void sleep(); 
}
(1.2)然後寫一個Human類,他實現了這個接口
public Human implements Sleepable{
   public void sleep(){
      System.out.println("睡覺了!夢中自有顏如玉!");
   }
}
(1.3)編寫一個SleepHelper類,它裏面包含了睡覺的輔助工作,用AOP術語來說它就應該是通知了
public class SleepHelper implements MethodBeforeAdvice,AfterReturningAdvice{
    public void before(Method mtd, Object[] arg1, Object arg2) throws Throwable {
        System.out.println("通常情況下睡覺之前要脫衣服!");
    }
    public void afterReturning(Object arg0, Method arg1, Object[] arg2,
            Object arg3) throws Throwable {
        System.out.println("起牀後要先穿衣服!");
    }
}
(1.4)spring配置文件中進行配置
<bean id="sleepHelper" class="test.spring.aop.bean.SleepHelper"></bean>

(2.1)配置一個切點
Spring使用org.springframework.aop.support.JdkRegexpMethodPointcut來定義正則表達式切點
<bean id="spleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
  <property name="pattern" value=".*sleep"/>
</bean>

pattern屬性指定了正則表達式,它匹配所有的sleep方法

(2.2)配置通知
切點僅僅是定義了故事發生的地點,還有故事發生的時間以及最重要的故事的內容,就是通知了,我們需要
把通知跟切點結合起來,我們要使用的通知者是:org.springframework.aop.support.DefaultPointcutAdvisor

<bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
     <property name="advice" ref="sleepHelper"/>
     <property name="pointcut" ref="sleepPointcut"/>
</bean>

(3)調用ProxyFactoryBean產生代理對象
<bean id="humanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
     <property name="target" ref="human"/>
     <property name="interceptorNames" value="sleepHelperAdvisor" />
     <property name="proxyInterfaces" value="test.spring.aop.bean.Sleepable" />
</bean>
ProxyFactoryBean是一個代理,我們可以把它轉換爲proxyInterfaces中指定的實現該interface的代理對象
(4)編寫測試類
public class Test {
    public static void main(String[] args){
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Sleepable sleeper = (Sleepable)appCtx.getBean("humanProxy");
        sleeper.sleep();
    }
}

程序運行產生結果:
通常情況下睡覺之前要脫衣服!
睡覺啦~夢中自有顏如玉!
起牀後要先穿衣服!

上面這個過程貌似有點複雜,尤其是配置切點跟通知,Spring提供了一種自動代理的功能,能讓切點跟通知自動進行匹配,修改配置文件如下:
 <bean id="sleepHelper" class="test.spring.aop.bean.SleepHelper">
  </bean>
  <bean id="sleepAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice" ref="sleepHelper"/>
    <property name="pattern" value=".*sleep"/>
  </bean>
  <bean id="human" class="test.spring.aop.bean.Human">
  </bean>
  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

執行程序:
public class Test {
    public static void main(String[] args){
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Sleepable sleeper = (Sleepable)appCtx.getBean("human");
        sleeper.sleep();
    }
}
成功輸出結果跟前面一樣!
只要我們聲明瞭org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator就能爲方法匹配的bean自動創建代理!
方式二:@AspectJ註解的切面
@Aspect
public class SleepHelper {
    public SleepHelper(){    
    }
    
    @Pointcut("execution(* *.sleep())")
    public void sleeppoint(){}
    
    @Before("sleeppoint()")
    public void beforeSleep(){
        System.out.println("睡覺前要脫衣服!");
    }
   
    @AfterReturning("sleeppoint()")
    public void afterSleep(){
        System.out.println("睡醒了要穿衣服!");
    }  
}
用@Aspect的註解來標識切面,注意不要把它漏了,否則Spring創建代理的時候會找不到它,@Pointcut註解指定了切點,@Before和@AfterReturning指定了運行時的通知,注意的是要在註解中傳入切點的名稱
意的是要在註解中傳入切點的名稱

然後我們在Spring配置文件上下點功夫,首先是增加AOP的XML命名空間和聲明相關schema命名空間:
xmlns:aop="http://www.springframework.org/schema/aop"
schema聲明:
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd

然後加上這個標籤:
<aop:aspectj-autoproxy/> 有了這個Spring就能夠自動掃描被@Aspect標註的切面了

最後是運行,很簡單方便了:
public class Test {

    public static void main(String[] args){
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Sleepable human = (Sleepable)appCtx.getBean("human");
        human.sleep();
    }
}
方式三:純POJO切面
只是修改配置文件,加入AOP配置即可:
<aop:config>
    <aop:aspect ref="sleepHelper">
    <aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))"/>
    <aop:after method="afterSleep" pointcut="execution(* *.sleep(..))"/>
    </aop:aspect>
</aop:config>

Spring在aop的命名空間裏面還提供了其他的配置元素:
<aop:advisor> 定義一個AOP通知者
<aop:after> 後通知
<aop:after-returning> 返回後通知
<aop:after-throwing> 拋出後通知
<aop:around> 周圍通知
<aop:aspect>定義一個切面
<aop:before>前通知
<aop:config>頂級配置元素,類似於<beans>這種東西
<aop:pointcut>定義一個切點
發佈了6 篇原創文章 · 獲贊 8 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章