Spring之AOP實現

cici_iii發表於2020-12-29


前言

AOP(Aspect Oriented Programming)稱為面向切面程式設計,在程式開發中主要用來解決一些系統層面上的問題,比如日誌,事務,許可權等待。


環境搭建

1、pom.xml 配置AOP依賴

        <!-- AOP 依賴-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>

2、Spring配置檔案的名稱空間中加入aop標頭檔案

<beans xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/aop                                                                      
                            https://www.springframework.org/schema/aop/spring-aop.xsd">

前置業務類編寫

1、Admin的service

package com.ex.service;

public interface IAdminService {
    public void saveAdmin(String name);
}
package com.ex.service.impl;

@Service
public class adminServiceImpl implements IAdminService {

    @Override
    public void saveAdmin(String name) {
        System.out.println("save admin method");
    }
}

2、user的service

package com.ex.service;

public interface IUserService {
    public void selectUser(int id);
}
package com.ex.service.impl;

@Service
public class userServiceImpl implements IUserService {

    @Override
    public void selectUser(int id) {
        System.out.println("user select method");
    }
}

一、註解實現AOP

1.編寫註解實現的增強類

@Component
@Aspect
public class LogAdvice {
    // springaop自動的5種aop這裡全部列出
    // *返回型別,包名,*類名,*方法名,(..)任何引數
    @Before("execution(* com.ex.service.impl.*.*(..))")
    public void before(){
        System.out.println("---------方法執行前before()---------");
    }
    @After("execution(* com.ex.service.impl.*.*(..))")
    public void after(){
        System.out.println("---------方法執行後after()---------");
    }
    @AfterReturning("execution(* com.ex.service.impl.*.*(..))")
    public void afterReturning(){
        System.out.println("---------方法返回後afterReturning()---------");
    }
    @Around("execution(* com.ex.service.impl.*.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("-------環繞前-------");
        System.out.println("簽名(拿到方法名):"+jp.getSignature());
        //執行目標方法proceed
        Object proceed = jp.proceed();
        System.out.println("-------環繞後------");
        System.out.println(proceed);
    }
    @AfterThrowing("execution(* com.xinzhi.service.impl.*.*(..))")
    public void afterThrow() {
        System.out.println("--------------有異常發生-----------------" + new Date());
    }
}

2.在Spring配置檔案中,註冊bean,並增加支援註解的配置

    <!-- 掃包:如果使用了註解,需要在開始之前去掃包-->
    <context:component-scan base-package="com.ex"/>
    <!-- aop 註解實現 配置 -->
    <aop:aspectj-autoproxy/>

3.測試

    @Test
    public void testAop(){
        userService.selectUser(1);
        System.out.println("--------------------------------");
        adminService.saveAdmin("aa");
    }

結果

-------環繞前-------
簽名(拿到方法名):void com.ex.service.IUserService.selectUser(int)
---------方法執行前before()---------
user select method
-------環繞後------
null
---------方法執行後after()---------
---------方法返回後afterReturning()---------
--------------------------------
-------環繞前-------
簽名(拿到方法名):void com.ex.service.IAdminService.saveAdmin(String)
---------方法執行前before()---------
save admin method
-------環繞後------
null
---------方法執行後after()---------
---------方法返回後afterReturning()---------

二、配置檔案實現AOP

1.編寫自定義增強類

public class MyAOP {
    public void before(){
        System.out.println("---------執行方法前列印日誌--------------自定義");
    }
    public void after(){
        System.out.println("---------執行方法後列印日誌--------------自定義");
    }
}

2.Spring配置檔案中,註冊bean,配置增強

    <!--註冊bean--> 
    <bean id="myAop" class="com.xinzhi.aop.MyAop"/>
    
    <!--aop的配置-->
    <aop:config>
        <!-- ref 自定義切面類 -->
        <aop:aspect ref="myAOP">
            <!-- 切入點配置 -->
            <aop:pointcut id="pointcut1" expression="execution(* com.ex.service.impl.adminServiceImpl.*(..))"/>
            <aop:pointcut id="pointcut2" expression="execution(* com.ex.service.impl.userServiceImpl.*(..))"/>
            <!-- 織入 -->
            <aop:before pointcut-ref="pointcut1" method="before"/>
            <aop:after pointcut-ref="pointcut2" method="after"/>
        </aop:aspect>
    </aop:config>

2.測試

    @Test
    public void testAop2(){
        userService.selectUser(1);
        System.out.println("--------------------------------");
        adminService.saveAdmin("aa");
    }

結果

user select method
---------執行方法後列印日誌--------------自定義
--------------------------------
---------執行方法前列印日誌--------------自定義
save admin method

總結

AOP就是對指定的一批的方法在其執行過程中進行一個統一的處理,將大量重複性的工作抽離了出來,省事!

相關文章