美文网首页
【Spring源码】22.AOP之代理对象的创建

【Spring源码】22.AOP之代理对象的创建

作者: 天还下着毛毛雨 | 来源:发表于2023-02-11 20:18 被阅读0次

前言

上一章我们讲了 , 在AbstractAutoProxyCreator类实现至BeanPostProcessor接口的postProcessAfterInitialization方法中,在遍历每一个正在实例化的bean时,会先解析容器类所有的beanNames对应的class,来创建并收集advisor对象。 并且会把当前beanClass 与 advisor对象集合进行匹配,如果匹配到了advisor对象,那么就说明 这个bean的某些方法时需要增强的,那么就会通过jdk动态代理或者cglib 来创建代理对象,实现aop。

接下来看看spring aop创建代理对象的具体过程。

image

进入createProxy方法,可以看到会把 beanClass,beanName,以及命中的Advisor集合,以及原生bean 包装成SingletonTargetSource对象传进去

image

1. proxyFactory对象的创建

createProxy方法会先常见一个ProxyFactory代理工厂对象,并且从AbstractAutoProxyCreator对象,复制一些属性进去

image image

1.1. 判断接口与更改proxyTargetClass属性值

这里最重要的属性是proxyTargetClass,将参与 决定使用jdk动态代理,还是cglib代理。

就是@EnableAspectJAutoProxy注解里的 proxyTargetClass 属性

@Component
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class AopConfig {
}

如果是默认的false(默认),那么接下来会有一个判断的过程,有可能会被spring改成true

image

evaluateProxyInterfaces方法会去判断 该beanClass 是否有实现接口

先是取出 beanClass 实现的所有接口

image

然后遍历,遍历的过程中会判断 接口的合法性

image
  1. isConfigurationCallbackInterface判断接口得不是 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 这几个接口,这是spring提供的接口
image
  1. isInternalLanguageInterface 判断 !( 接口名称.equals("groovy.lang.GroovyObject") ||接口名称.getName().endsWith(".cglib.proxy.Factory") || 接口名称.endsWith(".bytebuddy.MockAccess"));)
image

这两个判断都 符合的话,hasReasonableProxyInterface变量会变成true, 并退出遍历

hasReasonableProxyInterface 为true的话, proxyTargetClass配置就还是false,不变

否则为false, 则会被 更改成 true

image

1.2 proxyFactory其他属性赋值

判断完 ProxyTargetClass 属性后,对TargetSource 目标对象,advisor对象集合等属性进行赋值

image

2. 创建aop代理对象-AopProxy对象

proxyFactory对象 创建成功后,开始创建AopProxy对象

image

这个AopProxy对象啊,是spring的aop代理对象,它两个实现类

  1. 通过jdk动态代理实现的aop代理对象
  2. 通过cglib代理实现的aop代理对象

通过它可以创建jdk动态代理/cglib 代理对象

看createAopProxy(classLoader)方法

image

调用aop代理工厂对象 创建aop代理对象 : createAopProxy

这里注意,会传入 proxyFactory对象, proxyFactory对象是持有原生bean和该类匹配的所有切面对象的

image

这里就有判断 具体是使用jdk动态代理还是cglib了

image

if ( 如果ProxyTargetClass配置的为true,

或者该类没有除 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 以外的接口-->ProxyTargetClass会被改成true,

或者 (如果 没有任何接口 或者 只实现了SpringProxy ){

        if(该类 是否是接口,或者是 Proxy类型(该class就是jdk动态代理创建的))

                那么还是会使用jdk动态代理

       Else{

              使用cglib

        }

}else{

使用jdk动态代理

}

如何还要考虑是否代理,是否只实现SpringProxy接口 那样太复杂了 ,下面这个归纳一下就可以满足常用的情况了

proxyTargetClass=false(默认) 
    被代理类是否实现除 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 以外的接口:
        是 jdk动态代理
        否 proxyTargetClass会被改成true
proxyTargetClass=true 
    被代理类是否是接口||是否是代理类(一般无法满足)
            是  : jdk动态代理
            否  : cglib动态代理

不管是返回JdkDynamicAopProxy 还是 ObjenesisCglibAopProxy,都会传入 proxyFactory对象,在构造方法赋值给JdkDynamicAopProxy的 AdvisedSupport advised属性。

也就是 JdkDynamicAopProxy {

    AdvisedSupport advised =  proxyFactory{

            advisors :所有的切面,

            targetSource:被代理目标对象

            proxyTargetClass :代理的方式

    }

}

3. AopProxy对象创建jdk代理对象

如果是jdk动态代理,上面返回的是JdkDynamicAopProxy对象

来看下 是怎么生成代理对象的

代码回到这

image

进入JdkDynamicAopProxy类的 getProxy方法

image

这里就是 按照jdk动态代理 的 模式 创建代理对象了,传入类加载器,实现的所有正常接口,InvocationHandler对象,创建代理对象

这里值得注意的是传入的 InvocationHandler对象就是 JdkDynamicAopProxy对象

那么JdkDynamicAopProxy 肯定实现了InvocationHandler接口,那么肯定会实现invoke方法,具体的增强逻辑 就在invoke方法里了。

image

并且他的AdvisedSupport advised 属性是 proxyFactory{

            advisors :所有的切面,

            targetSource:被代理目标对象

            proxyTargetClass :代理的方式

}

当方法执行的时候就会执行 InvokeHandle的invoke方法,取出AdvisedSupport advised属性里的advisors进行方法级别的匹配,并调用advice,进行增强。

image

相关文章

网友评论

      本文标题:【Spring源码】22.AOP之代理对象的创建

      本文链接:https://www.haomeiwen.com/subject/derrkdtx.html