首頁 > 軟體

一文詳解Spring AOP的設定與使用

2022-11-09 14:02:14

1.關於AOP

面向切面程式設計(俗稱AOP)提供了一種物件導向程式設計(俗稱OOP)的補充,物件導向程式設計最核心的單元是類(class),然而面向切面程式設計最核心的單元是切面(Aspects)。與物件導向的順序流程不同,AOP採用的是橫向切面的方式,注入與主業務流程無關的功能,例如事務管理和紀錄檔管理。

圖示:

Spring的一個關鍵元件是AOP框架。 雖然Spring IoC容器不依賴於AOP(意味著你不需要在IOC中依賴AOP),但AOP為Spring IoC提供了非常強大的中介軟體解決方案。

AOP 是一種程式設計正規化,最早由 AOP 聯盟的組織提出的,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。它是 OOP的延續。利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率

2.初步使用AOP環境設定

要使用Spring AOP,需要匯入如下的maven包:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9.1</version>
</dependency>

在對應的Spring組態檔中,需要匯入aop的約束:

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"

整體的設定如下:

<?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">

​​​​​​​</beans>

編寫介面類:UserService.java

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

介面實現類:UserServiceImpl.java

public class UserServiceImpl implements UserService {

    @Override
    public void add() {
        System.out.println("增加使用者");
    }

    @Override
    public void delete() {
        System.out.println("刪除使用者");
    }

    @Override
    public void update() {
        System.out.println("更新使用者");
    }

    @Override
    public void query() {
        System.out.println("查詢使用者");
    }
}

待插入的前置紀錄檔類:Log.java

/**
 * 插入的前置紀錄檔類
 */
public class Log implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被執行了!");
    }
}

待插入的後置紀錄檔類:AfterLog.java

/**
 * 插入的後置紀錄檔類
 */
public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("執行了" + method.getName() + "方法,返回結果為:" + returnValue);
    }
}

註冊類的bean標籤:

<!-- 註冊測試bean -->
<bean id="userService" class="top.imustctf.service.UserServiceImpl"/>
<bean id="log" class="top.imustctf.log.Log"/>
<bean id="afterLog" class="top.imustctf.log.AfterLog"/>

3.使用原生Spring API介面實現AOP

設定aop:

切入點是待切入的方法,使用正規表示式匹配

執行環繞增加是具體向切入點新增紀錄檔的設定

<!-- 設定AOP -->
<aop:config>
    <!-- 設定切入點 -->
    <aop:pointcut id="pointcut" expression="execution(* top.imustctf.service.UserServiceImpl.*(..))"/>
    <!-- 執行環繞增加 -->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

現在來測試一下吧:

可以看到,AOP動態代理切入成功了!

@Test
public void test() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
    // top.imustctf.service.UserServiceImpl的add被執行了!
    // 增加使用者
    // 執行了add方法,返回結果為:null
}

4.使用自定義類實現AOP

先Diy一個切面類:DiyPointCut.java

public class DiyPointCut {
    public void before() {
        System.out.println("方法執行前");
    }

    public void after() {
        System.out.println("方法執行後");
    }
}

註冊diy類並設定切面:

<bean id="diy" class="top.imustctf.diy.DiyPointCut"/>
<aop:config>
    <!-- 定義一個切面,ref中為要參照的類物件 -->
    <aop:aspect ref="diy">
        <!-- 設定切入點 -->
        <aop:pointcut id="point" expression="execution(* top.imustctf.service.UserServiceImpl.*(..))"/>
        <!-- 通知 -->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>

來開始測試:

@Test
public void test() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
    // 方法執行前
    // 增加使用者
    // 方法執行後
}

5.使用註解實現AOP

使用註解實現AOP,它更簡單,更強大!

在使用註解開發前,需要在Spring組態檔中開啟動態代理的支援:

<aop:aspectj-autoproxy/>

接下來,使用註解直接開發AOP類:

@Component
@Aspect  // 標註這個類是一個切面
public class AnnotationPointCut {
    @Before("execution(* top.imustctf.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("方法執行前啊!");
    }

    @After("execution(* top.imustctf.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("方法執行後啊!");
    }
}

現在來測試一下吧:

@Test
public void test() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = context.getBean("userService", UserService.class);
    userService.add();
    // 方法執行前啊!
    // 增加使用者
    // 方法執行後啊!
}

到此這篇關於一文詳解Spring AOP的設定與使用的文章就介紹到這了,更多相關Spring AOP內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com