对于AOP的理解(二)

2020-08-21  本文已影响0人  倚仗听江

上一篇文章主要讲了一下,SpringAOP进行动态代理这件事到底发生在什么时候,我们已经知道了再Spring容器初始化完成的时候代理就已经完成了。如果没看过的朋友,有兴趣的话可以看一下我的这篇文章:https://www.jianshu.com/p/5da1690a52ed
上次说到,当Spring调用addSingleton方法时代理就已经完成了

image.png
那么我们就可以通过调用栈往前推,看看到底是在哪里完成了代理这件事。
image.png
这里其实也有个小技巧吧,我们可以使用二分查找的思想,在调用栈的一半的位置看看代理是否完成了,直到找到进行代理的地方。
按照这样的方法,我们可以慢慢的将范围缩小,可以看到
image.png
直到这个位置时,代理依旧没有完成,我们进到这个方法,继续调试。
继续往下走,进入到createBean方法后
image.png
可以发现,此时依旧没有进行代理,继续往下走。
终于。。。
image.png
在这个地方,代理被执行了。。。
那就说明,这个方法我们得进入看。
终于走到了这里
image.png
这是对Spring后置处理器的一个循环,找到我们AOP的后置处理器
image.png
看这行代码是不是特别的亲切,没错,这里就要创建代理了!
继续往下走
image.png
终于走到最后了,createAopProxy方法,看到这个名字就知道,它是在创建代理。也正如你所知道的SpringAOP的代理有两种方式:JDK动态代理和CGLIB动态代理。
那么这两种动态代理各自在什么情况下会被使用呢?
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

通过这个方法我们可以发现:如果一个类有顶层接口,则默认使用jdk的动态代理来代理,如果直接是一个类,则使用cglib动态代理。
我们来做一下测试:
此时我的UserService是一个类


image.png

使用的是cglib动态代理

再创建一个OrderService接口,用OrderServiceImpl来实现


image.png

使用的是jdk动态代理
但一定要这样吗?也不是,其实是可以控制的。@EnableAspectJAutoProxy(proxyTargetClass = true),没错,在这个注解中加上proxyTargetClass = true),那么就会都使用cglib动态代理。


image.png
注:这个属性默认是false,当它为false时,就是上面说的那种默认情况。
那为什么这个属性能起到这样的作用呢?不知道同学们看到proxyTargetClass 有没有感到眼熟?没错,就在刚才那个完成代理的方法中!
image.png

而这个config.isProxyTargetClass()是什么呢?


image.png
好了,终于破案了,这就是为什么这个属性能起到这个作用的原因。
上一篇 下一篇

猜你喜欢

热点阅读