Spring5參考指南:AOP代理

AOP代理

一般來講Spring AOP有兩種代理方式,一種默認的JDK代理,只能代理接口,一種是CGLIB代理,能夠代理具體的類對象。java

SpringAOP默認爲對AOP代理使用標準的JDK動態代理。若是業務對象不實現接口,則使用CGLIB。git

若是使用CGLIB,要注意對於CGLIB,不能advice final方法,由於它們不能在運行時生成的子類中被重寫。github

因爲Spring的AOP框架基於代理的特性,根據定義,目標對象內的方法調用不會被攔截。對於JDK代理,只能截獲對代理的公共接口方法調用。使用cglib,能夠截獲代理上的公共和受保護的方法調用(若是須要,甚至能夠截獲包可見的方法)。spring

若是須要攔截在目標類內的方法調用甚至構造函數,那麼考慮使用Spring驅動的native AspectJ weaving,而不是Spring的基於代理的AOP框架。框架

要強制使用CGLIB代理,請將aop:config元素的proxy target class屬性的值設置爲true,以下所示:函數

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>
複製代碼

要在使用@Aspectj auto proxy支持時強制cglib代理,請將aop:aspectj-autoproxy元素的proxy-target-class屬性設置爲true,以下所示:this

<aop:aspectj-autoproxy proxy-target-class="true"/>
複製代碼

AOP Proxies原理

SpringAOP是基於代理的,那什麼是代理呢?spa

首先咱們考慮一個最簡單的POJO對象:代理

public class SimplePojo implements Pojo {

    public void foo() {
        // this next method invocation is a direct call on the 'this' reference
        this.bar();
    }

    public void bar() {
        // some logic...
    }
}
複製代碼

若是直接調用該對象的方法,則運行原理以下所示:code

image

調用方法以下:

public class Main {

    public static void main(String[] args) {
        Pojo pojo = new SimplePojo();
        // this is a direct method call on the 'pojo' reference
        pojo.foo();
    }
}
複製代碼

若是是調用代理,則運行原理以下:

image

調用方法以下:

public class Main {

    public static void main(String[] args) {
        ProxyFactory factory = new ProxyFactory(new SimplePojo());
        factory.addInterface(Pojo.class);
        factory.addAdvice(new RetryAdvice());

        Pojo pojo = (Pojo) factory.getProxy();
        // this is a method call on the proxy!
        pojo.foo();
    }
}
複製代碼

本文的例子請參考aop-proxy

更多教程請參考 flydean的博客

相關文章
相關標籤/搜索