Aop失效了?获取代理对象的两种方式!

发布时间:2024年01月17日

AOP为何失效?

请看以下代码

service

@Service
public class HelloBbService {

    public void hello1() {
        System.out.println("how are you ?");
        // 通过this调用
        this.hello2();
    }

    public void hello2() {
        System.out.println("what's your name?");
    }
}

aop设置

@Aspect
@Component
@Slf4j
public class AopConfig {

    @Around("execution(* cn.bb.mydemo.service.HelloBbService.hello2()) ")
    public void printLog(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("方法执行开始");
        joinPoint.proceed();
        log.info("方法执行结束");
    }
}

控制层

@RestController
public class HelloBbController {
    @Autowired
    private HelloBbService helloBbService;

    @GetMapping(path = "hellobb")
    public void hellobb() {
        helloBbService.hello1();
    }
}

通过调用 输出如下

how are you ?
what's your name?

问题原因

通过断点发现,通过this拿到的对象只是普通对象,而只有代理对象,才能够被Spring增强,使得Aop生效。
在这里插入图片描述

问题解决

1. 使用@Autowired 自我注入

不是要代理对象嘛,通过@Autowired注入的方式拿到的就是代理对象,代码修改如下。

@Service
public class HelloBbService {

    @Autowired
    private HelloBbService helloBbService;

    public void hello1() {
        System.out.println("how are you ?");
        // 通过this调用
        helloBbService.hello2();
    }

    public void hello2() {
        System.out.println("what's your name?");
    }
}

在这里插入图片描述
方法调用输出如下。
在这里插入图片描述
可以看到,aop生效了。

这里要复习下。
jdk动态代理,只能针对实现类生成代理。
cglib动态代理,能针对普通类生成代理。
这里我并没有用接口实现,所以会使用cglib代理。

但是这种方式我并不推荐,为什么?因为当注入的类多时,会存在循环依赖的问题。

2.使用AopContext.currentProxy()

这才是这篇文章的重点,有同学说AopContext是什么?

它提供了一种在运行时获取当前代理对象的机制。通过AopContext,可以在实例化类时直接获取当前代理对象,而无需传递代理对象的引用。

本质上,它通过ThreadLocal 来将 Proxy 和线程绑定起来,这样就可以随时拿出当前线程绑定的 Proxy。

但注意,它默认是被禁用的,需要开启后才能使用。

可以通过该注解开启@EnableAspectJAutoProxy(exposeProxy = true)

代码修改如下。

@Service
@EnableAspectJAutoProxy(exposeProxy = true)// 为了方便 暂时加在了这里 建议大家加在启动类上
public class HelloBbService {

    public void hello1() {
        System.out.println("how are you ?");
        HelloBbService helloBbService = (HelloBbService) AopContext.currentProxy();
        helloBbService.hello2();
    }

    public void hello2() {
        System.out.println("what's your name?");
    }
}

再查看下对象,发现确实是代理对象了。
在这里插入图片描述
输出如下
在这里插入图片描述

从心理学的角度分析,越是头脑简单的人越是需要点缀和填充,而头脑复杂的人则对简洁有着特殊的心理需求。

文章来源:https://blog.csdn.net/weixin_44353507/article/details/135646135
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。