深刻理解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動態中的一種。
  • 相關文章
    相關標籤/搜索