深刻理解Spring AOP之二代理对象生成

深刻理解Spring AOP之二代理对象生成

spring代理对象

上一篇博客中讲到了Spring的一些基本概念和初步讲了实现方法,当中提到了动态代理技术,包含JDK动态代理技术和Cglib动态代理

动态代理这部分我有过一篇博客介绍: 动态代理,想深刻了解的朋友可以看一看,再回想一下,Spring中怎样区分採用JDK动态代理和CGlib动态代理:

  1. 假设目标对象的实现类实现了接口。Spring AOP 将会採用 JDK 动态代理来生成 AOP 代理类;
  2. 假设目标对象的实现类没有实现接口,Spring AOP 将会採用 CGLIB 来生成 AOP 代理类

将下载编译好的Spring-aop包中的源代码打开,例如如下图所看到的


aop.png

对应的源代码可以在 Github上面。而后用工具编译成project文件。再导入eclipse里面来阅读, 网上有对应的方法

Spring AOP 使用类 org.springframework.aop.framework.ProxyFactory进行织入。找到ProxyFactory相应的相关内容,而后整理例如如下类图java



porxy3.png

Spring代理类怎样生成

调用方法步骤可以例如如下所看到的:

  • 新建一个target,target使咱们需要操做的目标
  • 定义一个代理工厂,可以是ProxyFactory或者ProxyFactorybean两种方法,Bean顾名思义,採用的Spring中的IOC机制,而ProxyFactory方法则可以直接获得

  • 增长通知

  • 获得代理实例,经过getproxy()方法

    先看ProxyFactory是怎样获得代理类的

  • 找到proxyFactory中的getProxy()方法;

    public Object getProxy() {
            return createAopProxy().getProxy();
        }
    
    protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            return getAopProxyFactory().createAopProxy(this);
        }

    实现它得到一个用来产生代理的实例, createAopProxy() 方法返回 AopProxy, 而后再调用 getProxy() 方法产生详细的代理对象,这里如下再细讲。因为在ProxyFactoryBean中也用到了同样的父类。

  • 获得了一个AopProxy以后,再利用AopProxy的方法,依据条件得到一个用来产生代理的实例。要么是JDK动态代理生成,要么是Cglib代理生成。

    ProxyFactoryBean是怎样得到代理类的

    找到ProxyFactoryBean方法,ProxyFactoryBean是在Spring IoC环境中,建立AOP应用的最底层方法,从中。可以看到一条实现AOP的基本线索。借助如上类图,看看AOP代理类是怎样产生的(回想下动态代理中的代理类生成方法)

  • 先看看ProxyFactoryBean中的getObject方法

    为何要先看getObject方法呢:假设容器中的某个对象持有某个FactoryBean的引用,它取得的不是FactoryBean自己,而是FactoryBean的getObject()方法所返回的对象。

    因此。假设容器中某个对象依赖于ProxyFactoryBean,那么它将会使用到ProxyFactoryBean的getObject()方法所返回的代理对象 git

    @Override
        public Object getObject() throws BeansException {
            initializeAdvisorChain(); //初始化通知器
            if (isSingleton()) {
                return getSingletonInstance();//依据定义生成单例的Proxy
            }
            else {
                if (this.targetName == null) {
                    logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); } return newPrototypeInstance(); //这里依据定义生成prototype的Proxy } } 

  • 继续跟踪getSingletonInstance()方法。这个地方可以看出点东西

    private synchronized Object getSingletonInstance() {
            if (this.singletonInstance == null) {
                this.targetSource = freshTargetSource();//返回被 代 理的 目标对象
                if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                    //从targetSource中获取目标对象的Class
    
                    Class<?> targetClass = getTargetClass();
                    if (targetClass == null) {
                        throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } //这里设置代理对象的接口 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } // 初始化共享的单例 super.setFrozen(this.freezeProxy); //这里会使用ProxyFactory来生成需要的Proxy this.singletonInstance = getProxy(createAopProxy()); } return this.singletonInstance; } 

    这里看看setFrozen()和createAopProxy()方法,调用的是proxyFactoryBean上一层接口ProxyCreatorSupport中的方法(看类图),

    protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            return getAopProxyFactory().createAopProxy(this); //这里借助了AopProxyFactory
        }

    如下这很是重要。getAopProxyFactory()方法,

    public AopProxyFactory getAopProxyFactory() {
            return this.aopProxyFactory;
        }

    尽管返回的是aopProxyFactory但是咱们假设追踪到构造函数中,咱们发现其有用的是new DefaultAopProxyFactory();

    private AopProxyFactory aopProxyFactory;
        public ProxyCreatorSupport() {
            this.aopProxyFactory = new DefaultAopProxyFactory();
        }

    继续追踪到DefaultAopProxyFactory中,找到createAopProxy()方法,最终真相大白,例如如下

    github

    @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 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."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }

    可以看到当中的代理对象可以由JDK或者Cglib来生成的,JdkDynamicAopProxy类和Cglib2AopProxy都实现的是AopProxy的接口。上面的这些逻辑就是要推断採用两种动态代理中的那一种。详细的规则可以參考最上面的介绍。到了这里。可能对JDK动态代理有点心动,毕竟动态代理中接触过了,例如如下是JdkDynamicAopProxy中实现代理的方法-getproxy()方法

    @Override
        public Object getProxy(ClassLoader classLoader) {
            if (logger.isDebugEnabled()) {
                logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
            }
            //依据advised 中 的 配 置信息,将proxy需要代 理的接口放入proxiedInterfaces 中
            Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
            findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
            //如下这种方法眼熟吧,哈哈 没错就是JDK中的动态代理经典方法
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }

    用Proxy包装target以后,经过ProxyFactoryBean获得对其方法的调用就被Proxy拦截了, ProxyFactoryBean的getObject()方法获得的其实是一个Proxy了,target对象已经被封装了。对 ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对象的代理对象

    总结

    上面讲了怎么多,简单回想下代理对象是怎样生成的

    一、上面讲到了两种生成代理对象的方法,一种是经过ProxyFactory,一种是经过ProxyFactoryBean。

    第一种获取比較简单。但是需要手工的进行写代码,而另一种是经过Spring的IOC机制来控制Bean的生成。 spring

    二、无论是ProxyFactory或者ProxyFactoryBean都是要经过createAopProxy().getProxy()来获取对应的代理对象,而经过Proxyfactory比較直接,上面重点介绍的是经过ProxyFactoryBean得到proxy。
    三、首先,找到ProxyFactoryBean的getObject方法。为何?(主要是跟Bean容器中getObject能返回代理对象)
    四、其次调用getSingletonInstance()。在getSingletonInstance方法中引入了super中的方法,super是指ProxyCreatorSupport。这里ProxyCreatorSupport是ProxyFactoryBean和ProxyFactory的父类,已经作了很是多工做,仅仅需在ProxyFactoryBean的getObject()方法中经过父类的createAopProxy()取得对应的AopProxy。
    五、跟踪createAopProxy方法。追踪到了ProxyCreatorSupport中,而后,借助了AopProxyFactory,此时获得的aopProxyFactory,在构造函数中已经定义为new DefaultAopProxyFactory()
    六、进入DefaultAopProxyFactory中。找到createAopProxy方法。在这里推断是调用JDK动态或者CGlib动态中的一种。
  • 相关文章
    相关标签/搜索