28.AOP源码之创建代理工厂和AopProxy


highlight: arduino-light

废话不多说,上一篇文章我们找到了所有合适的advisors。

spring是怎么用这些advisor?

答:将要代理的对象和advisors都添加到代理工厂。

在创建代理的时候又做了哪些事情?

答:根据配置判断代理方式,并根据代理方式创建对应的AopProxy。

标题对每一步都做了总结,直接开始看源码吧!

3.AbstractAutoProxyCreator#createProxy

1.判断isProxyTargetClass,默认是false。

2.如果isProxyTargetClass是false。

如果BD的preserveTargetClass属性是true,那么设置ProxyTargetClass为true

3.如果BD的preserveTargetClass属性是false继续判断是否存在hasReasonableProxyInterface,如果没有,那么设置ProxyTargetClass为true

```java protected Object createProxy(Class> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { //设置一个属性originalTargetClass //值是被代理类的源class if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } //创建代理工厂   ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //判断判断代理方式 // isProxyTargetClass默认是false 代表不使用cglib //如果配置成了true不会进入下面的判断 if (!proxyFactory.isProxyTargetClass()) { //shouldProxyTargetClass方法的返回值: //return Boolean.TRUE.equals(bd.getAttribute(PRESERVETARGETCLASS_ATTRIBUTE)); //即判断BD的preserveTargetClass属性是true   //那么会设置ProxyTargetClass为true if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); }else { // //如果 shouldProxyTargetClass返回的是 false //即判断BD的preserveTargetClass属性是false //进入这里 //判断是否有ReasonableProxyInterface //否则还是设置isProxyTargetClass是true /** * 获取的接口列表 * 1.不是 InitializingBean、DisposableBean、Aware 接口扩展接口 * 不是 Jdk中AutoCloseable 和 Closeable 接口 * 2.不是内部语言接口 * 即不是 groovy.lang.GroovyObject * 或者.cglib.proxy.Factory 结尾 * 或者.bytebuddy.MockAccess 结尾 * 3.不是空接口 * * 上面3个条件满足 那么就认为有ReasonableProxyInterface * 如果有,那么设置ProxyTargetClass为false * 如果没有,那么设置ProxyTargetClass为true */ evaluateProxyInterfaces(beanClass, proxyFactory); } }

//合并specificInterceptors 和 commonInterceptors到 advisors
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//代理工厂添加advisor
proxyFactory.addAdvisors(advisors);
//是将被代理的bean封装到SingletonTargetSource 
//就是当前被代理的bean的实例
proxyFactory.setTargetSource(targetSource);
//扩展点::: 自定义代理工厂
//将默认的代理工厂返回给了我们 我们可以对其修改或者替换?
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
    proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());

} ```

我们先从整体上看下这个createProxy()方法都做了什么,此时我们发现它就是创建了一个proxyFactory对象,接着给这个proxyFactory设置了一堆属性,最后通过proxyFactory对象的getProxy()方法就获取到了一个动态代理对象。

3.0创建代理工厂proxyFactory

java ProxyFactory proxyFactory = new ProxyFactory();

其实我们通过名字来看的话,猜测ProxyFactory就是一个代理工厂,也就是专门用来创建动态代理的工厂,现在看来这个ProxyFactory是非常非常重要的的,那现在就非常有必要来研究一下ProxyFactory了。

ProxyFactory的无参构造方法没啥特殊的。可以直接跳过。

那现在ProxyFactory已经构建好了,我们接着看下都给这个代理工厂设置了哪些属性

3.1为proxyFactory拷贝通用属性

java proxyFactory.copyFrom(this);

首先我们来看下这个proxyFactory.copyFrom(this)是干嘛的,那么就要先看下这个入参this到底是哪个类的实例。

此时我们发现proxyFactory.copyFrom(this)是在AbstractAutoProxyCreator中进行调用的,那这个this是不是AbstractAutoProxyCreator类的实例呢?

其实是这样的,虽然这行代码是在AbstractAutoProxyCreator类中调用的,但是我们也知道抽象类是不能直接使用new来实例化的,所以这个this一定是AbstractAutoProxyCreator类的某个子类,那么到底是哪个子类呢?

不知道大家还记不记得,之前在讲AOP自动代理时机时。

当时我们就讲过AnnotationAwareAspectJAutoProxyCreator这个类。

其实这个this就是AnnotationAwareAspectJAutoProxyCreator类的实例。

只不过一些核心逻辑都是在其父类AbstractAutoProxyCreator中,所以我们很容易忽略掉它的子类。

此时我们搞清楚了入参后,接下来我们就点开copyFrom()方法看下吧,此时会看到如下代码:

java public void copyFrom(ProxyConfig other) { Assert.notNull(other, "Other ProxyConfig object must not be null"); this.proxyTargetClass = other.proxyTargetClass; this.optimize = other.optimize; this.exposeProxy = other.exposeProxy; this.frozen = other.frozen; this.opaque = other.opaque; }

可以看到,其实它就是将入参对象AnnotationAwareAspectJAutoProxyCreator的一些属性设置给了proxyFactory自己。比如这个proxyTargetClass属性和optimize属性。

AnnotationAwareAspectJAutoProxyCreator的这些属性来自哪里呢?

来自BeanConfig上的注解@EnableAspectJAutoProxy属性。

java @EnableAspectJAutoProxy(proxyTargetClass = false,exposeProxy = false)

```java public class ProxyConfig implements Serializable {

private static final long serialVersionUID = -8409359707199703185L;

private boolean proxyTargetClass = false;

private boolean optimize = false;

boolean opaque = false;

boolean exposeProxy = false;

private boolean frozen = false;

} ```

此时我们发现proxyTargetClass属性和optimize属性都是在一个叫做ProxyConfig的类中,而不是ProxyFactory中。

那这个ProxyConfig和ProxyFactory之间到底是什么关系呢?

此时我们发现,其实ProxyFactory是ProxyConfig的子类。

所以ProxyFactory是可以从父类ProxyConfig继承过来属性的,比如proxyTargetClass属性和optimize属性。

那通过copyFrom()方法设置的proxyTargetClass属性和optimize属性到底是干嘛的呢?这个我们现在还不知道,不过看源码就是这样,前边设置的一些属性可能是为了给后边使用的,所以这里我们就先跳过,接着往下看还会设置哪些属性吧。

3.2ProxyFactory设置属性ProxyTargetClass

java // isProxyTargetClass默认是false 代表不使用cglib //如果配置成了true不会进入下面的判断 if (!proxyFactory.isProxyTargetClass()) { //如果BD的preserveTargetClass属性是true 那么会设置ProxyTargetClass为true if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); }else { //如果 shouldProxyTargetClass返回的是 false //会判断是否有ReasonableProxyInterface 否则还是设置isProxyTargetClass是true /** * 获取的接口列表 * 1.不是 InitializingBean、DisposableBean、Aware 接口扩展接口 * 不是Jdk 中 AutoCloseable 和 Closeable 接口 * 2.不是内部语言接口 * 不是groovy.lang.GroovyObject * 或者.cglib.proxy.Factory 结尾 * 或者.bytebuddy.MockAccess 结尾 * 3.不是空接口 * * 上面3个条件满足 那么就认为有ReasonableProxyInterface */ evaluateProxyInterfaces(beanClass, proxyFactory); } }

可以看到,这里就是先看下proxyTargetClass属性是否为true,这个属性的名字翻译过来是“代理目标类”,我们从名字中就可以判断出来它就是基于类代理的意思,因为我们知道动态代理有两种,分别是jdk代理和cglib代理,而jdk代理是基于接口的,而cglib代理是基于类的,所以这个proxyTargetClass属性,就代表你是不是要基于目标类进行代理,也可以翻译为是否使用cglib代理,都是一个意思。

好,我们接着往下看,如果当前不是基于类代理的,也就是基于接口代理的,那么就会进入这个if分支,在这个if分支中又会来执行shouldProxyTargetClass(beanClass, beanName)方法

java public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) { if (beanName != null && beanFactory.containsBeanDefinition(beanName)) { BeanDefinition bd = beanFactory.getBeanDefinition(beanName); return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE)); } return false; }

其实这里就是从BeanDefinition中取出一个PRESERVETARGETCLASS_ATTRIBUTE属性。

看一下这个属性是否配置为了true。

而这个PRESERVETARGETCLASS_ATTRIBUTE的定义如下:

java public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");

可以看到,其实这个PRESERVETARGETCLASS_ATTRIBUTE真正代表的参数名字是preserveTargetClass,说白了这个shouldProxyTargetClass()方法就是来看一下BeanDefinition中的preserveTargetClass属性是否被配置为了true。

如果preserveTargetClass配置为了true,那么就将proxyTargetClass设置为true。

说白了就是除了proxyTargetClass属性可以控制是基于类代理还是基于接口代理,Spring在BeanDefinition中还定义了一个preserveTargetClass属性,它也可以控制基于类代理和基于接口代理,相当于给自己留了一个“后门”。

个人感觉proxyTargetClass是类级别的。preserveTargetClass是BD级别。

然后我们接着往下看,如果proxyTargetClass和preserveTargetClass都为false,那么说明此时是基于接口代理的,那么此时就会执行evaluateProxyInterfaces()方法,代码如下:

java protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) { Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); boolean hasReasonableProxyInterface = false; for (Class<?> ifc : targetInterfaces) { /*** * 获取的接口列表 * 1.不是 InitializingBean、DisposableBean、Aware 接口扩展接口 * 不是Jdk 中 AutoCloseable 和 Closeable 接口 * 2.不是内部语言接口 * 不是groovy.lang.GroovyObject * 或者.cglib.proxy.Factory 结尾 * 或者.bytebuddy.MockAccess 结尾 * 3.不是空接口 * * 上面3个条件满足 那么就认为有ReasonableProxyInterface ***/ if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0) { hasReasonableProxyInterface = true; break; } } //如果有 ReasonableProxyInterface 那必须得是false了 if (hasReasonableProxyInterface) { for (Class<?> ifc : targetInterfaces) { proxyFactory.addInterface(ifc); } }else { proxyFactory.setProxyTargetClass(true); } }

我们可以看到,这里首先获取了目标类中的所有接口,然后依次处理这些接口,处理的时候调用了isConfigurationCallbackInterface()方法和isInternalLanguageInterface()方法,这两个方法很简单,代码如下:

其实就是看下这些接口是不是回调接口或者是内部语言的接口,也就是确保这些接口是用户自己定义的有效接口

如果存在有效接口的话,并且接口中存在方法的话,那么就将hasReasonableProxyInterface设置为true,接着就会将有效接口添加到proxyFactory的interfaces属性中

说白了这里就是将代理要实现的接口先保存起来,后边基于接口生成代理的时候就会使用到!

而如果不存在有效接口的话,那么此时就只能基于类进行代理了,就会将proxyTargetClass属性设置为true

```md //shouldProxyTargetClass方法 //判断BD的preserveTargetClass属性是true那么设置ProxyTargetClass为true

//如果 shouldProxyTargetClass返回的是 false进入这里 //判断是否有ReasonableProxyInterface 1.不是 InitializingBean、DisposableBean、Aware接口扩展接口 不是Jdk中AutoCloseable 和 Closeable 接口 2.不是内部语言接口即不是 groovy.lang.GroovyObject 或者.cglib.proxy.Factory 结尾 或者.bytebuddy.MockAccess 结尾 3.不是空接口 上面3个条件满足 那么就认为有ReasonableProxyInterface 如果有,那么设置ProxyTargetClass为false 如果没有,那么设置ProxyTargetClass为true ```

3.3合并并包装Advisor:buildAdvisors

到了这里,我们发现前边我们千辛万苦得到的拦截器还没有用到,不过没事儿,我们继续往下看,此时就会看到一个buildAdvisors()方法,一看这个方法的名字,就必然和拦截器脱不了干系,这个buildAdvisors()方法的代码如下:

java protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) { //commonInterceptors为空数组 下面的判断跳过 Advisor[] commonInterceptors = resolveInterceptorNames(); List<Object> allInterceptors = new ArrayList<>(); if (specificInterceptors != null) { //添加所有自定义的specificInterceptors allInterceptors.addAll(Arrays.asList(specificInterceptors)); //下面的判断跳过 if (commonInterceptors.length > 0) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); }else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } Advisor[] advisors = new Advisor[allInterceptors.size()]; //遍历所有的advisor for (int i = 0; i < allInterceptors.size(); i++) { //根据不同的类型做包装 //说是包装其实是根据不同的Advisor封装为不同的Advisor对象 advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors; }

这里先去解析通用拦截器,如果存在通用拦截器的话,就将通用拦截器和之前获取的增强拦截器合并到一起。

最后对合并后的拦截器进行统一再封装,即统一封装为Advisor类型,此时就会调用下边这个wrap()方法

java @Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; //这里主要是给事务的TransactionInterceptor用的吧 if (advice instanceof MethodInterceptor) { return new DefaultPointcutAdvisor(advice); } /*** 适配器模式 registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); ***/ for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }

可以看到,在使用wrap()方法进行统一封装的时候,会先看一下当前要封装的对象是不是Advisor类型,如果本身人家就是Advisor类型的话,那这里就不用再多此一举了,此时直接返回原来的对象就可以了。

需要注意的是这个wrap()方法只能包装Advisor类型和Advice类型,如果要包装的对象不是这两种类型,那么就直接抛异常进行提示,而如果是这两种类型之一的话,那么就统一包装成DefaultPointcutAdvisor对象,最后将统一包装好的advisors返回。

3.4添加advisors到ProxyFactory

接着就将所有包装好的advisors通过addAdvisors()方法添加到proxyFactory中,

java proxyFactory.addAdvisors(advisors);

这个时候就将之前我们千辛万苦获取到的拦截器,给设置到了ProxyFactory中。

这样后边创建代理时,就可以从ProxyFactory中获取到拦截器了!

3.5设置bean实例到代理工厂

java //设置被代理类的实例到代理工厂 proxyFactory.setTargetSource(targetSource);

这个targetSource是什么东西?是被代理的bean的包装类

//targetSource是被代理的bean的包装类 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

targetSource原来就是我们被代理的bean被包装了。

java new SingletonTargetSource(bean)

我们再进一步看下这个customizeProxyFactory()方法的定义。

其实就是一个空实现,说白了就是ProxyFactory为我们留的一个扩展点,我们可以使用子类来重写这个方法,这样就可以定制自己的ProxyFactory了

然后我们再往下看,发现最后还会设置一个preFiltered标识。

执行AbstractAdvisorAutoProxyCreator类的advisorsPreFiltered()方法。

java @Override protected boolean advisorsPreFiltered() { return true; }

可以发现这里永远返回true,说白了就是将ProxyFactory中的preFiltered标识设置为true

那这个preFiltered标识有什么用呢?

其实从名字来看,这个preFiltered标识是预过滤的意思,但是目前为止,我们还真不清楚它的作用,我们猜测这个preFiltered标识应该在后边某个地方会用到,所以这个preFiltered标识有个大概印象就可以了,我们继续往下分析。

好了,到这里为止ProxyFactory的核心属性就都设置完成了,也就是创建代理的准备工作都完成了

属性设置完成之后,接着就会来执行这行代码proxyFactory.getProxy(getProxyClassLoader())

总结:判断isProxyTargetClass,合并和包装advisors

4.ProxyFactory#getProxy

看最后一句代码

java return proxyFactory.getProxy(getProxyClassLoader());

proxyFactory就是我们的ProxyFactory。

看下ProxyFactory#getProxy(java.lang.ClassLoader)方法

java public Object getProxy(@Nullable ClassLoader classLoader) { //createAopProxy()返回的是AopProxy //根据不同的类型判断使用jdk代理或者是cglib代理 //AopProxy 是jdk或者cglib return createAopProxy().getProxy(classLoader); }

这里要分2步看:createAopProxy() 和 getProxy(classLoader)

createAopProxy

```java protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } /* getAopProxyFactory()返回的是一个DefaultAopProxyFactory 继续看DefaultAopProxyFactory#createAopProxy 注意这个参数:this是我们在第3步创建的代理工厂ProxyFactory ProxyFactory extends ProxyCreatorSupport ProxyCreatorSupport extends AdvisedSupport AdvisedSupport extends ProxyConfig implements Advised ProxyFactory 封装了各种参数比如被代理类的实例以及advisors advisor中又封装了方法和方法的切面表达式 */   return getAopProxyFactory().createAopProxy(this); }

//ProxyFactory继承自ProxyCreatorSupport public ProxyCreatorSupport() {    this.aopProxyFactory = new DefaultAopProxyFactory(); } ```

DefaultAopProxyFactory#createAopProxy
判断代理方式,创建不同的AopProxy

java /*** proxyTargetClass属性是否为true,这个属性的名字翻译过来是“代理目标类”。 我们从名字中就可以判断出来它就是基于类代理的意思,因为我们知道动态代理有两种。 分别是jdk代理和cglib代理,而jdk代理是基于接口的,而cglib代理是基于类的。 所以这个proxyTargetClass属性,就代表你是不是要基于目标类进行代理。 也可以翻译为是否使用cglib代理,都是一个意思。 如果是接口类或者Proxy的类,使用JDK动态代理对象 CGLIB是用继承的方式实现的,不支持这两种方式的类做代理 原因 1.CGLIB是用继承的方式实现的,不支持接口 原因 2.Proxy一定是用jdk代理创建的代理对象 如果是jdk代理创建的代理对象仍然使用jdk代理对其增强 注意这个参数:config 其实就是我们的ProxyFactory ProxyFactory extends ProxyCreatorSupport ProxyCreatorSupport extends AdvisedSupport AdvisedSupport extends ProxyConfig implements Advised ***/ @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { /*** 主要判断3个条件 1.config.isOptimize()表示是否开启了优化策略,这个默认为false,一般不常用 2.config.isProxyTargetClass()和属性proxyTargetClass的值一样 3.hasNoUserSuppliedProxyInterfaces(config)目标类没有实现接口 这3种情况有1种是true都代表有可能要使用cglib代理 一旦被代理的类是接口或者或者Proxy的类还是会使用jdk的动态代理 ***/ if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { /*** 判断被代理的目标类是否是null 是null抛出异常 ***/ Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException(); } //如果是接口或者或者Proxy的类还是会使用jdk的动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //这里的config传入的是AdvisedSupport return new JdkDynamicAopProxy(config); } //否则使用的是clib return new ObjenesisCglibAopProxy(config); }else { //config.isOptimize() //|| config.isProxyTargetClass() //|| hasNoUserSuppliedProxyInterfaces(config):目标类没有支持代理的接口 //这行代码的三个条件如果都是false,那么就使用jdk代理 //isProxyTargetClass()是false 使用的一定是jdk代理 return new JdkDynamicAopProxy(config); } }

1.如果isProxyTargetClass是true或者目标类没有合适的被代理的接口会继续判断

如果是接口或者是Proxy类型 那么还是使用JDK代理。

否则使用cglib代理

2.如果isProxyTargetClass是false 那么使用的一定是JDK代理

3.最后根据不同的代理方式创建不同的代理

DefaultAopProxyFactory#createAopProxy

JdkDynamicAopProxy构造方法,这里的config是我们创建的代理工厂ProxyFactory。

ProxyFactory 封装了各种参数比如被代理类的实例以及advisorsadvisor中又封装了方法和方法的切面表达式

注意最后把ProxyFactory赋值给了advised属性。

java public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException ("No advisors and no TargetSource specified"); } //**注意最后把ProxyFactory赋值给了advised属性。** this.advised = config; }

ObjenesisCglibAopProxy构造方法,这里的config是我们创建的代理工厂ProxyFactory。

ProxyFactory 封装了各种参数比如被代理类的实例以及advisorsadvisor中又封装了方法和方法的切面表达式

java public ObjenesisCglibAopProxy(AdvisedSupport config) { super(config); }

java public CglibAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException ("No advisors and no TargetSource specified"); } //**注意最后把ProxyFactory赋值给了advised属性。** this.advised = config; this.advisedDispatcher = new AdvisedDispatcher(this.advised); }

注意最后把ProxyFactory赋值给了advised属性。

总结:根据代理方式返回对应的AopProxy

CglibAopProxy和JdkDynamicAopProxy都封装了ProxyFactory。

ProxyFactory封装了各种参数 advisors proxyTargetClass 等属性。

如果isProxyTargetClass()是false一定使用的是jdk代理。

如果isProxyTargetClass()是true,但是如果是目标类是接口或者是Proxy类型,那么仍然会使用jdk代理。

否则采用cglib。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值