1. 程式人生 > >Spring AOP簡介及簡單例項

Spring AOP簡介及簡單例項

一、SpringAOP 簡介

1.AOP思想:

AOP即面向切面程式設計,可以說是OOP的補充和完善。它利用一種稱為"橫切"的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為"Aspect",即切面。
           所謂"切面",簡單說就是那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性。

2.AOP概念:

1)AOP把軟體系統分為兩個部分:核心關注點和橫切關注點

業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。
橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處基本相似,比如設定頁面編碼、許可權認證、日誌、事務。

AOP的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。

3.AOP使用

AOP程式設計其實是很簡單的事情,縱觀AOP程式設計,程式設計師只需要參與三個部分:

  • 1)定義普通業務元件
  • 2)定義切入點,一個切入點可能橫切多個業務元件
  • 3)定義增強處理,增強處理就是在AOP框架為普通業務元件織入的處理動作

所以進行AOP程式設計的關鍵就是定義切入點(在哪裡要新增方法)定義增強處理(要新增的方法),一旦定義了合適的切入點和增強處理,AOP框架將自動生成AOP代理,即:代理物件的方法=增強處理+被代理物件的方法

4.AOP概念:

橫切關注點:

對那些方法進行攔截,攔截後怎麼處理,類似這些的關注點
切面(次要業務):是對橫向關注點的抽象<aop:aspect>
連線點(所有可能進行切面操作的方法即類中的所有方法):被攔截到的點,因為Spring只支援方法型別的連線點不能操作屬性和構造方法,所以在Spring中連線點指的就是被攔截到的方法,實際上連線點還可以是欄位或者構造器
切入點(具體攔截到的方法):對連線點進行攔截的定義<aop:pointer>
通知:所謂通知指的就是指攔截到連線點之後要執行的程式碼,通知分為前置、後置、異常、最終、環繞通知五類
目標物件:代理的目標物件
織入(weave):(在原有的方法織入一個新的方法形成一個大方法)將切面應用到目標物件並導致代理物件建立的過程
    將切面的通知方法織入到切點方法的過程

5.Spring 對AOP的支援:

Spring中AOP代理由Spring的IOC容器負責生成、管理,其依賴關係也由IOC容器負責管理。因此,AOP代理可以直接使用容器中的其它bean例項作為目標,這種關係可由IOC容器的依賴注入提供。

   <aop:config>
            <aop:aspect id="time" ref="timeHandler"><>
                <aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
                <aop:before method="printTime" pointcut-ref="addAllMethod" />
                <aop:after method="printTime" pointcut-ref="addAllMethod" />
            </aop:aspect>
   </aop:config>

二、SringAOP簡單例子--方法執行前列印當前時間

1.pom.xml

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.8.RELEASE</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.7.2</version>
    </dependency>

2.業務邏輯

核心關注點(主要業務--列印Hello World!)

//介面
package org.lanqiao.aop;

public interface Hello {
      void print();
}

//實現類
package org.lanqiao.aop;

public class HelloImpl implements Hello {
    public void print() {
        System.out.println("Hello World!");
    }
}

橫切關注點(次要業務--列印當前時間) 

package org.lanqiao.aop;

public interface TimeAOP {
    void printTime();
}



package org.lanqiao.aop;


import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeAOPImpl implements TimeAOP {
    @Override
    public void printTime() {
        long currentTime = System.currentTimeMillis();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH時mm分ss秒");
        Date date = new Date(currentTime);
        System.out.println(formatter.format(date));
    }
}

3.Spring配置檔案aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="hello" class="org.lanqiao.aop.HelloImpl"/>
    <bean id="timeHander" class="org.lanqiao.aop.TimeAOPImpl"/>

    <aop:config><!--橫切關注點,對哪些方法進行攔截,攔截後怎麼處理-->
        <aop:aspect id="timeAspect" ref="timeHander"><!--定義切面 若有多個切面可通過執行順序 order="1"等控制順序或者上下文順序   -->
            <aop:pointcut id="helloPointcut" expression="execution(* org.lanqiao.aop.Hello.*(..))"/><!--定義切入點-->
            <aop:before method="printTime" pointcut-ref="helloPointcut"/><!--將通知織入到切入點-->
            <!--<aop:around method="printTime" pointcut-ref="helloPointcut"/>-->
        </aop:aspect>
    </aop:config>

</beans>

常見切入點表示式的例子:

  • 任意公共方法的執行:

    execution(public * *(..))
    
  • 任何一個以“set”開始的方法的執行:

    execution(* set*(..))
    
  • AccountService 介面的任意方法的執行:

    execution(* com.xyz.service.AccountService.*(..))
    
  • 定義在service包裡的任意方法的執行:

    execution(* com.xyz.service.*.*(..))
    
  • 定義在service包或者子包裡的任意類的任意方法的執行:

    execution(* com.xyz.service..*.*(..))

4.測試 

package org.lanqiao;


import org.junit.Test;
import org.lanqiao.aop.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloTest
{
    @Test
    public void testPrint()
    {
        ApplicationContext ctx =
                new ClassPathXmlApplicationContext("aop.xml");
        Hello hello = (Hello)ctx.getBean("hello");
        hello.print();
    }
}

5.輸出結果

 

相互學習,共同指教!