天天看點

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

前言

本文主要舉幾個工作中典型AOP的實操案例,還有經常出現的問題(切不進去,ctrl+左鍵跳不到被切方法中)等等。

本文對于AOP的實作原理概不讨論,百度一搜有的是。

AOP的使用背景和好處

比如A子產品是公司的核心子產品,這塊代碼未經允許不得輕易篡改。

但是你又有新的需求,需要在公司的核心子產品的某個方法上進行增強(比如在執行核心方法的之前列印自定義日志,或者修改該核心方法的入參和傳回值等等)

這樣你就可以在不修改核心子產品源碼的情況下,對源代碼的方法進行增強,擴充原來方法的一些功能。

這樣既能保證源代碼不被破壞,又可以擴充源代碼現有的功能。

一、幾種使用姿勢

1、@AfterReturning和@Before

@AfterReturning是後置方法,在目标方法執行後執行,@Before是前置方法,在目标方法執行前執行

它們一般配合JoinPoint來使用(不能配合ProceedingJoinPoint,會報錯)。直接看例子:

被切的方法:

@Service
public class OriFuncImpl implements OriFunc{

    @Override
    public String ori(String str){
        System.out.println("執行了原方法");
        return str;
    }
}

           

使用@AfterReturning 和 @Before:

@Aspect
@Component
public class AopFunc {
    @Pointcut("execution(* com.daji.aop_test.OriFuncImpl.ori(..))")
    public void test() {
    }

    @Before("test()")
    public void before(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();    //擷取方法入參
        System.out.println("原方法的入參是:"+args[0]);
        System.out.println("原方法執行前會先執行我!!");
    }


    @AfterReturning("test()")
    public void after(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();    //擷取方法入參
        System.out.println("原方法執行後會執行我!!");
    }

}
           

2、@Around

@Around是環繞通知,既可以控制入參,還可以控制原方法的執行和傳回值

常常配合ProceedingJoinPoint來使用。直接看例子:

被切的方法:

@Service
public class OriFuncImpl implements OriFunc{

    @Override
    public String ori(String str){
        System.out.println("執行了原方法");
        return str;
    }
}

           

使用@Around:

@Aspect
@Component
public class AopFunc {
    @Pointcut("execution(* com.daji.aop_test.OriFuncImpl.ori(..))")
    public void modifyReturn() {
    }

    @Around("modifyReturn()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        Object result = joinPoint.proceed(args);
        return result;
    }

}

           

3、@Around可以篡改傳回值,篡改入參

需要ProceedingJoinPoint的配合

注意一定要将@Around修飾的方法用Object修飾其傳回值,并且傳回原方法執行的結果,如下圖所示:

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

篡改入參一樣的道理,隻需要篡改下圖中的 args數組,然後讓其傳入proceed中,即可完成篡改入參。如下圖所示:

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

是以,這個@Around比較萬能,尤其是配合ProceedingJoinPoint的使用。使AOP能做的事情更多了。

引申一下JoinPoint 和 ProceedingJoinPoint的關系:

  • ProceedingJoinPoint 隻能在@Around中使用
  • JoinPoint也可以擷取入參(getArgs()),它可以用于@Before 和 @AfterReturning
  • Proceedingjoinpoint 繼承了 JoinPoint 。是在JoinPoint的基礎上暴露出 proceed 這個方法。它們之間的關系如下圖:
Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

4、@Around如果不執行proceed(),那麼原方法将不會執行

二、使用AOP常見的問題和bug

1、切不進去

檢查是否有如下注解:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.2</version>
</dependency>
           

檢查完畢後檢查切面類,看看有沒有以下注解:

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

2、ctrl+滑鼠左鍵不能自動跳到被切方法:

正常情況如圖:

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

如果你存在上述問題,檢查你有沒有安裝下列插件:

Spring AOP之@Around,@AfterReturning使用、切不進去問題解決前言AOP的使用背景和好處一、幾種使用姿勢二、使用AOP常見的問題和bug

如果你是idea社群版,那麼預設是沒有的,你要麼自己下,要麼換成正式版。

繼續閱讀