深入理解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相應的相關內容,然后整理例如以下類圖



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

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

  • 免責聲明!

    本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



     
    粵ICP備18138465號   © 2018-2025 CODEPRJ.COM