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

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

spring代理对象

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

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

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

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

深入理解Spring AOP之二代理对象生成_第1张图片

相应的源码可以在 Github上面,然后用工具编译成project文件,再导入eclipse里面来阅读, 网上有相应的方法。 Spring AOP 使用类 org.springframework.aop.framework.ProxyFactory进行织入,找到ProxyFactory对应的相关内容,然后整理如下类图

深入理解Spring AOP之二代理对象生成_第2张图片

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()方法所返回的代理对象

    @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()方法,终于真相大白,如下


@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而言,其生产出来的对象是封装了目标对象的代理对象

总结

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

1、上面讲到了两种生成代理对象的方法,一种是通过ProxyFactory,一种是通过ProxyFactoryBean。第一种获取比较简单,但是需要手工的进行写代码,而第二种是通过Spring的IOC机制来控制Bean的生成。
2、无论是ProxyFactory或者ProxyFactoryBean都是要通过createAopProxy().getProxy()来获取相应的代理对象,而通过Proxyfactory比较直接,上面重点介绍的是通过ProxyFactoryBean获得proxy。
3、首先,找到ProxyFactoryBean的getObject方法,为什么?(主要是跟Bean容器中getObject能返回代理对象)
4、其次调用getSingletonInstance(),在getSingletonInstance方法中引入了super中的方法,super是指ProxyCreatorSupport,这里ProxyCreatorSupport是ProxyFactoryBean和ProxyFactory的父类,已经做了很多工作,只需在ProxyFactoryBean的getObject()方法中通过父类的createAopProxy()取得相应的AopProxy。
5、跟踪createAopProxy方法,追踪到了ProxyCreatorSupport中,然后,借助了AopProxyFactory,此时得到的aopProxyFactory,在构造函数中已经定义为new DefaultAopProxyFactory()
6、进入DefaultAopProxyFactory中,找到createAopProxy方法,在这里判断是调用JDK动态或者CGlib动态中的一种。

你可能感兴趣的:(java/java,web项目)