SpringBoot 整合AOP(面向切面编程)其中@Around失效问题

发布时间 2023-03-28 09:43:51作者: 迷糊桃

1.AOP实现知识点​

核心思想:动态代理。

​支持技术:反射。

2.官方文档名词解释​

Aspect(切面):关注点的模块化(新增业务的模块化)。为完成新业务而编写的类对象。(带@Aspect注解的类)。

Join point(连接点):新业务的实现,通知到了我们该干点什么。

Advice(通知):告诉新业务是在连接点的什么状态去执行 ,具体请看5. 通知的分类。

Pointcut(切点):我们新增业务执行的地方。(例中的Run())。

Introduction(引入):改变类的情况下,给该类添加属性和方法。

Target object(目标对象):要扩展业务的对象。

AOP proxy(代理):像目标对象通知后创建的对象(动态代理中的代理对象)。

3.通知分类

@Before :在切点方法(Run())执行前。

@After:在切点方法(Run())执行后。

@AfterReturning:切点方法(Run())返回后执行

@AfterThrowing:切点方法(Run())抛异常执行

@Around:环绕增强 ,切入点方法(Run())之前之后都执行。

该增强和其他增强不同,需要将切入点方法传入该方法后执行。注意看代码实现和相关注释。(踩了大坑)。

4.注解方法实现AOP整合

1.引入相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.目标对象(实现举例)

 //接口类
    public interface CarService {

        /**
         * 汽车跑
         */
        public void run();

    }

  //实现类
    @Service
    public class CarServiceImpl implements CarService {

        @Override
        public void run() {
            System.out.println("汽车跑动了!!!!!!!!!!");
        }

    }

3.切面 (这个要注意下@Aound)

//该注解表示这是个切面
@Aspect
//将该对象交给Spring 的Ico容器管理
@Component
public class CarAop {

    /**
     * 连接点 将CarService接口的所有实现类中的方法作为接入点,绑定到carRun()上。
     * execution 中字符发解释
     * 1.第一个 * 任意返回值
     * 2.中间的是包名
     * 3.第二个*表示server包下的所有对象
     * 4.括号表示接收参数
     * 5.括号中的..表示任意参数
     * 
     * execution 绑定这一个
     * 还有 :execution  within  this  target  args  @target  @args   @within  @annotation
     */
    @Pointcut("execution( * com.qian.exercise_java.aop.service.*(..))")
    public void carRun(){

    }

    /**
     * carRun() 就是上面的接入点。
     * @Before  表示在CarService接口的所有实现类中的方法,执行前将执行runBefore()方法
     */
    @Before("carRun()")
    public void runBefore(){
        System.out.println("runBefore()执行前执行了!!!!!");
    }

    /**
     * 之后执行
     */
    @After("carRun()")
    public void runAfter(){
        System.out.println("runAfter()执行前执行了!!!!!");
    }


    /**
     * 一部分run()之前执行,一部分run()之后执行
     * 这个需要特别注意
     */
    @Around("carRun()")
    public void runAround(ProceedingJoinPoint pj) throws Throwable {
        System.out.println("run()执行---前---执行了runAround()!!!!!!");

        //如果添加了环绕增强,一定要加下面这句,不然远方法都将不执行。
        //执行被增强方法
        pj.proceed();
        System.out.println("run()执行---后---执行了runAround()!!!!!!");
    }

    /**
     * run()***方法返回后***执行
     */
    @AfterReturning("carRun()")
    public void runAfterReturning(){
        System.out.println("runAfterReturning()执行了!!!!!!");
    }

}

4.测试结果

@RunWith(SpringRunner.class)
@SpringBootTest
public class CarAopTest {

    @Autowired
    private CarService carService;

    @Test
    public void carAopTest(){
        carService.run();
    }
}

5.测试输出结果

run()执行---前---执行了runAround()!!!!!!
runBefore()执行前执行了!!!!!
汽车跑动了!!!!!!!!!!
runAfterReturning()执行了!!!!!!
runAfter()执行前执行了!!!!!
run()执行---后---执行了runAround()!!!!!!