Spring深度解析-12、AOP代理对象创建原理-ProxyFactoryBean
阅读原文时间:2021年04月24日阅读:1

设计原理


大家都知道spring的AOP是通过代理模式实现的,那么AOP中所谓的代理模式在spring源码中是如何实现的呢,实现代理模式实质上就是需要通过一些手段得到目标对象的代理对象,那么在spring中如何得到这些个代理对象呢?
Spring常用的获取代理对象的方式有三种:
1、AspectJProxyFactory:集成spring与Aspect实现AOP
2、ProxyFactory:编程式使用AOP
3、ProxyFactoryBean:声明式使用AOP

这三个类都继承自
ProxyConfig:提供配置属性
AdvisedSupport:封装了通知与通知器
ProxyCreatorSupport:代理对象创建的辅助类

ProxyFactoryBean的配置

对于AOP代理对象的创建实现,我们从ProxyFactoryBean开始深入窥探,在深入理解ProxyFactoryBean创建代理对象之前,有必要先学会ProxyFactoryBean的配置与使用,
需要配置什么东西呢?
1、ProxyFactoryBean
2、Advisor [ 其实就是 Advice+PointCut]
3、target [目标对象]

下面来看一个配置使用的案例:
目标接口

public interface Subject {
    void request();
}

目标增强对象

public class Target implements Subject {
    @Override
    public void request() {
        System.out.println("target request ..");
    }
}

Advice通知:

前置增强
public class TargetBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("target before");
    }
}

bean.xml

<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces"><value>com.raycloud.dmj.data.utils.Subject</value></property>
        <property name="target">
            <bean class="com.raycloud.dmj.data.utils.Target"/>
        </property>
        <property name="interceptorNames">
            <list>
                <value>advisor</value>
            </list>
        </property>
    </bean>

<!--DefaultPointcutAdvisor 使用的切点为True单件,即匹配任何方法都为true,也就是为所有方法增强 -->
    <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" >
            <bean class="com.raycloud.dmj.data.utils.TargetBeforeAdvice" />
        </property>
    </bean>

main方法

 public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        ((Subject)context.getBean("proxyFactoryBean")).request();
    }

输出结果:
target before
target request …
实现了对目标对象的方法前置增强处理。

ProxyFactoryBean创建AopProxy源码解析

上面通过一个简单的实验案例,了解了通过ProxyFactoryBean创建代理对象需要的东西,其实就是目标接口,目标对象,以及通知器【通知+切面】,就是通过这些东西实现了方法的增强,如上是一个前置增强处理的案例。
下面来从源码的角度去看下ProxyFactoryBean到底是如何实现代理对象的生成的呢?
首先看下ProxyFactoryBean的类继承体系:

public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {

ProxyFactoryBean实现了BeanClassLoaderAware,BeanFactoryAware,因此可以在ProxyFactory中直接获取类加载器与Bean工程;
其次ProxyFactoryBean实现了FactoryBean接口,回想前面getBean的源码,可知,对一个FactoryBean做getBean操作本质是获取了FactoryBean的getObject方法返回的对象,因此自ProxyFactory如何创建代理对象的学习中,要从ProxyFactoryBean的getObject开始:
getObject:

public Object getObject() throws BeansException {
//初始化通知器链
        this.initializeAdvisorChain();
//判断是否是单例,单例与多例有不同的实现方式
        if (this.isSingleton()) {

            return this.getSingletonInstance();
        } else {
            if (this.targetName == null) {
                this.logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
            }

            return this.newPrototypeInstance();
        }
    }

如上源码分析可知,在ProxyFactoryBean的getObject中,第一步是进行通知器链的初始化,然后根据单例与否,进行不同的操作,返回代理对象。
OK,那么通知器链的初始化时做了什么呢?
下面来看下
initializeAdvisorChain:

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
//如何已经初始化过了,那就不用在初始化了
        if (this.advisorChainInitialized) {
            return;
        }
    //如果不为空,那就初始化这个通知器链;为空,说明没有配置啊
        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // Globals can't be last unless we specified a targetSource using the property...
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // Materialize interceptor chain from bean names.
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }
                //可以通过 XXX*的方法区配置一系列ID开头为XXX的通知器
                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }

                else {
                    // If we get here, we need to add a named interceptor.
                    // We must check if it's a singleton or prototype.
                    Object advice;
                    //如果是单例,就从容器中取
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // Add the real Advisor/Advice to the chain.
                        //这里通过回调得到的BeanFactory去getBean就很方便了
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // It's a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                        //不是单例就每次都new
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    //添加到通知器链
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }

初始化通知器Advisor的主要实现在namedBeanToAdvisor的this.advisorAdapterRegistry.wrap(next);
过程:
1、判断是否是Advisor,如果是通知器,ok,直接返回即可
2、如果不是通知器,又不是通知,那么就报错
3、如果是methodinterceptor的实现类,那么包装成DefaultPointcutAdvisor返回,这个是方法的拦截器
4、如果是前置、后置或者异常增强,同样包装成DefaultPointcutAdvisor。
methodinterceptor 与具体 前置、后置或者异常增强的区别在于methodinterceptor 可以自由的在方法执行前后和抛出异常时做出一系列增强。
此外DefaultPointcutAdvisor的PointCut切点是一个True单例,即默认匹配所有的方法提供Advice增强

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;
        //如果是MethodInterceptor的实现类,直接创建DefaultPointcutAdvisor
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        //如果没有实现MethodInterceptor,就需要判断是不是 前置增强,后置增强或者异常增强,如果是这三种之一,就需要包装成DefaultPointcutAdvisor.DefaultPointcutAdvisor默认增强目标对象的所有方法
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

如上是初始化通知器链的过程,其实就是根据name去getBean的过程,ProxyFactoryBean因为实现了BeanFactoryAware,因此可以在其内部直接使用到Bean工厂,从而很方便的使用getBean方法从容器中取对象。
至于单例与否,单例对象会维护到singletonInstance属性上,如果这个属性有值就直接返回,否则就创建;而多例就是每次都创建对象罢了。
创建代理对象的代码都是一样的。

this.getProxy(this.createAopProxy());

createAopProxy().

protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            this.activate();
        }
        //这里的AopProxyFactory是维护在ProxyCreatorSupport中的,
        且显式指定为DefaultAopProxyFactory
        return this.getAopProxyFactory().createAopProxy(this);
    }

这里的AopProxyFactory是维护在ProxyCreatorSupport中的,且显式指定为DefaultAopProxyFactory。
DefaultAopProxyFactory 中的createAopProxy

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 {
            //如果目标类是一个接口,那就使用JDK代理,否则用CGLIB代理
                return (AopProxy)(targetClass.isInterface() ? new JdkDynamicAopProxy(config) : DefaultAopProxyFactory.CglibProxyFactory.createCglibProxy(config));
            }
        }
    }

如果目标类是一个接口,那就使用JDK代理,否则用CGLIB代理。

//获取代理以后,就通过代理的getProxy去获取代理对象
 protected Object getProxy(AopProxy aopProxy) {
        return aopProxy.getProxy(this.proxyClassLoader);
    }

获取代理以后,就通过代理的getProxy去获取代理对象