1. 程式人生 > >深入理解Spring AOP之二代理對象生成

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

gets code 網上 none work class als post 產生

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

spring代理對象

上一篇博客中講到了Spring的一些基本概念和初步講了實現方法,當中提到了動態代理技術,包含JDK動態代理技術和Cglib動態代理

動態代理這部分我有過一篇博客介紹:動態代理,想深入了解的朋友能夠看一看,再回想一下,Spring中怎樣區分採用JDK動態代理和CGlib動態代理:

  1. 假設目標對象的實現類實現了接口。Spring AOP 將會採用 JDK 動態代理來生成 AOP 代理類;
  2. 假設目標對象的實現類沒有實現接口,Spring AOP 將會採用 CGLIB 來生成 AOP 代理類

將下載編譯好的Spring-aop包中的源代碼打開,例如以下圖所看到的
技術分享

技術分享

對應的源代碼能夠在Github上面。然後用工具編譯成project文件。再導入eclipse裏面來閱讀,網上有對應的方法。

Spring AOP 使用類 org.springframework.aop.framework.ProxyFactory進行織入。找到ProxyFactory相應的相關內容,然後整理例如以下類圖
技術分享

技術分享

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動態中的一種。

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