歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Spring學習之第一個AOP程序

Spring學習之第一個AOP程序

日期:2017/3/1 9:15:02   编辑:Linux編程

IOC和AOP是Spring的兩大基石,AOP(面向方面編程),也可稱為面向切面編程,是一種編程范式,提供從另一個角度來考慮程序結構從而完善面向對象編程(OOP)。

在進行 OOP 開發時,都是基於對組件(比如類)進行開發,然後對組件進行組合,OOP 最大問題就是無法解耦組件進行開發,比如我們上邊舉例,而 AOP 就是為了克服這個問題而出現的,它來進行這種耦合的分離。AOP 為開發者提供一種進行橫切關注點(比如日志關注點)分離並織入的機制,把橫切關注點分離,然後通過某種技術織入到系統中,從而無耦合的完成了我們的功能。

1、AOP基本概念

  • 連接點( Jointpoint) : 表示需要在程序中插入橫切關注點的擴展點,連接點可能是類初始化、方法執行、 方法調用、字段調用或處理異常等等, Spring 只支持方法執行連接點, 在 AOP 中表示為“在哪裡干” ;
  • 切入點( Pointcut) : 選擇一組相關連接點的模式, 即可以認為連接點的集合,Spring 支持 perl5 正則表達式和 AspectJ 切入點模式, Spring 默認使用 AspectJ 語法, 在 AOP 中表示為“在哪裡干的集合” ;
  • 通知( Advice) : 在連接點上執行的行為, 通知提供了在 AOP 中需要在切入點所選擇的連接點處進行擴展現有行為的手段; 包括前置通知( before advice)、後置通知(after advice)、環繞通知( around advice), 在 Spring 中通過代理模式實現AOP,並通過攔截器模式以環繞連接點的攔截器鏈織入通知; 在 AOP 中表示為“干什麼”;
  • 方面/切面( Aspect): 橫切關注點的模塊化,可以認為是通知、引入和切入點的組合; 在 Spring 中可以使用 Schema 和@AspectJ 方式進行組織實現; 在 AOP 中表示為“在哪干和干什麼集合” ;
  • 引入( inter-type declaration) : 也稱為內部類型聲明, 為已有的類添加額外新的字段或方法, Spring 允許引入新的接口(必須對應一個實現)到所有被代理對象(目標對象) , 在 AOP 中表示為“干什麼(引入什麼) ” ;
  • 目標對象( Target Object) : 需要被織入橫切關注點的對象,即該對象是切入點選擇的對象,需要被通知的對象,從而也可稱為“被通知對象”;由於 Spring AOP通過代理模式實現,從而這個對象永遠是被代理對象, 在 AOP 中表示為“對誰干” ;
  • AOP 代理( AOP Proxy) : AOP 框架使用代理模式創建的對象,從而實現在連接點處插入通知(即應用切面) ,就是通過代理來對目標對象應用切面。在 Spring中, AOP 代理可以用 JDK 動態代理或 CGLIB 代理實現,而通過攔截器模型應用切面。
  • 織入( Weaving) : 織入是一個過程,是將切面應用到目標對象從而創建出 AOP代理對象的過程, 織入可以在編譯期、類裝載期、運行期進行。

Spring有哪些通知類型呢?

  • 前置通知( Before Advice) :在切入點選擇的連接點處的方法之前執行的通知,該通知不影響正常程序執行流程(除非該通知拋出異常,該異常將中斷當前方法鏈的執行而返回)。
  • 後置通知( After Advice) : 在切入點選擇的連接點處的方法之後執行的通知,包括如下類型的後置通知:
    • 後置返回通知( After returning Advice) :在切入點選擇的連接點處的方法正常執行完畢時執行的通知, 必須是連接點處的方法沒拋出任何異常正常返回時才調用後置通知。
    • 後置異常通知( After throwing Advice) : 在切入點選擇的連接點處的方法拋出異常返回時執行的通知, 必須是連接點處的方法拋出任何異常返回時才調用異常通知。
    • 後置最終通知( After finally Advice) : 在切入點選擇的連接點處的方法返回時執行的通知,不管拋沒拋出異常都執行,類似於 Java 中的 finally 塊。
  • 環繞通知( Around Advices): 環繞著在切入點選擇的連接點處的方法所執行的通知,環繞通知可以在方法調用之前和之後自定義任何行為,並且可以決定是否執行連接點處的方法、替換返回值、拋出異常等等。

  在 AOP 中,通過切入點選擇目標對象的連接點,然後在目標對象的相應連接點處織入通知,而切入點和通知就是切面(橫切關注點),而在目標對象連接點處應用切面的實現方式是通過 AOP 代理對象,如圖所示。

2、AOP的HelloWorld程序

  AOP代理就是 AOP框架通過代理模式創建的對象,Spring使用 JDK動態代理或 CGLIB代理來實現, Spring 缺省使用 JDK 動態代理來實現,從而任何接口都可被代理,如果被代理的對象實現不是接口將默認使用 CGLIB 代理,不過 CGLIB 代理當然也可應用到接口。AOP 代理的目的就是將切面織入到目標對象。

  新建工程,導入Spring中對應的包,最後引入的jar包如下所示(有些包spring的lib下沒有,需要另外下載):

(1)定義目標接口

package com.log;

public interface IHelloWorldService {
    public void sayHello();
}

(2)定義目標接口實現類

package com.log;

public class HelloWorldService implements IHelloWorldService {
    @Override
    public void sayHello() {
        System.out.println("---hello world---");
    }
}

(3)定義切面支持類

package com.log;

public class HelloWorldAspect {
    public void beforeAdvice() {
        System.out.println("---before advice---");
    }
    
    public void afterAdvice() {
        System.out.println("---after advice---");
    }
}

(4)在XML中進行配置

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

    <!-- 配置目標類 -->
    <bean id="helloWorldService" class="com.log.HelloWorldService"/>
    <!-- 配置切面 -->
    <bean id="aspect" class="com.log.HelloWorldAspect"/>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.log..*.*(..))"/>
        <!-- aop:aspect的ref引用切面支持類的方法 -->
        <aop:aspect ref="aspect">
            <aop:before pointcut-ref="pointcut"
                method="beforeAdvice"/>
            <aop:after pointcut-ref="pointcut"
                method="afterAdvice"/>
        </aop:aspect>
    </aop:config>
</beans>

  切入點使用<aop:config>標簽下的<aop:pointcut>配置, expression屬性用於定義切入點模式,默認是AspectJ語法,“ execution(* cn.javass..*.*(..))”表示匹配cn.javass包及子包下的任何方法執行。關於expression屬性如何配置請點擊:expression配置 http://www.linuxidc.com/Linux/2016-06/132196.htm

  切面使用<aop:config>標簽下的<aop:aspect>標簽配置,其中“ ref”用來引用切面支持類的方法。
  前置通知使用<aop:aspect>標簽下的<aop:before>標簽來定義, pointcut-ref屬性用於引用切入點Bean, 而method用來引用切面通知實現類中的方法,該方法就是通知實現,即在目標類方法執行之前調用的方法。
  最終通知使用<aop:aspect>標簽下的<aop:after >標簽來定義,切入點除了使用pointcut-ref屬性來引用已經存在的切入點,也可以使用pointcut屬性來定義,如pointcut="execution(* cn.javass..*.*(..))", method屬性同樣是指定通知實現,即在目標類方法執行之後調用的方法。

(5)測試運行

package com.log;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aopBean.xml");
        IHelloWorldService hello = context.getBean("helloWorldService", IHelloWorldService.class);
        hello.sayHello();
        
        HelloWorldAspect advice = context.getBean("aspect", HelloWorldAspect.class);
        advice.beforeAdvice();
    }
}

(6)輸出結果

Spring中如何配置Hibernate事務 http://www.linuxidc.com/Linux/2013-12/93681.htm

Struts2整合Spring方法及原理 http://www.linuxidc.com/Linux/2013-12/93692.htm

基於 Spring 設計並實現 RESTful Web Services http://www.linuxidc.com/Linux/2013-10/91974.htm

Spring-3.2.4 + Quartz-2.2.0集成實例 http://www.linuxidc.com/Linux/2013-10/91524.htm

使用 Spring 進行單元測試 http://www.linuxidc.com/Linux/2013-09/89913.htm

運用Spring注解實現Netty服務器端UDP應用程序 http://www.linuxidc.com/Linux/2013-09/89780.htm

Spring 3.x 企業應用開發實戰 PDF完整高清掃描版+源代碼 http://www.linuxidc.com/Linux/2013-10/91357.htm

Spring 的詳細介紹:請點這裡
Spring 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved