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

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?");
    }
}

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

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

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值