AOP全稱是Aspect-Oriented Programming,對應到編程術語中就是面向切面的編程。簡單來講就是執行一段代碼以前以及以後分別插入另外一段代碼,從而實現對這段代碼全方位監視。java
鏈接點,抽象統一了method,constructor,field。好比最經常使用的Method,對應到類就是`ReflectiveMethodInvocation`,能夠攔截方法調用,並添加自定義的advice。這個概念是aop內部封裝的過程當中用到,使用者不須要直接接觸。spring
切入點,其實就是一個過濾器,其子類衍生出靜態的切入點,動態切入點,基於表達式的切入點等。本質就是經過對類,方法,輸入參數的解析,判斷哪些是須要進行攔截的,哪些是能夠被過濾的。編程
通知,或者加強,這兩種翻譯均可以強行解釋,是爲了實現攔截Jointpoint後具體的邏輯,好比常見的MethodInterceptor,對方法進行攔截。這個接口是使用者最關心的,直接關係到業務邏輯。緩存
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency>
spring支持兩種動態代理方案,1種是基於jdk的動態代理,第2種是基於cglib的動態代理。詳細參考`DefaultAopProxyFactory`,spring基於3個條件來選擇哪種動態代理方案,只要符合其中一個條件spring就會採用基於cglib的方案。1.是否須要優化(基於cglib的動態代理方案執行性能比JDK的高);2.是否聲明瞭代理對象是類(JDK不支持對類的動態代理,而cglib支持);3.沒有代理接口聲明;全部配置能夠經過`org.springframework.aop.framework.ProxyFactory`配置。用戶註冊的adivce先被緩存在列表中(Interceptor是Advice接口的子接口),若是沒有顯示聲明則會被封裝成`DefaultPointcutAdvisor`,這裏就涉及到Pointcut這個術語,默認的Pointcut容許攔截全部類和方法。ide
核心類是`JDKDynamicAopProxy`,首先根據配置選擇型的將spring本身的3個接口加入到代理接口,而後本身實現了JDK中的`InvocationHandler`接口。當JDK的動態代理回調`InvocationHandler`的時候,先判斷是不是spring本身增長的幾個接口,若是是則經過反射調用直接返回,若是不是則經過執行`JoinPoint`的子類`ReflectiveMethodInvocation`,回調第一個advice,以後的advice經過使用者本身觸發調用,這樣造成了一個調用鏈。須要注意的是,spring爲了提升效率,額外攔截了hashcode和equals方法直接處理,也不會進入advice的攔截處理流程。假如咱們有兩個advice,那麼實際的執行順序爲性能
advice1.before -> advice2.before -> poxy.process-> advice2.after -> advice1.after
詳細demo參考優化
public class AopTest { public static void main(String[] args){ System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); test(); } public static void test(){ // 基於對類的代理 ProxyFactory proxyFactory = new ProxyFactory(); // target 表示被真正執行代理的實例 proxyFactory.setTarget(new AopTester()); proxyFactory.setInterfaces(AopInterface.class); // advice 能夠對調用進行攔截從而實現aop proxyFactory.addAdvice(new MyInterceptor1()); proxyFactory.addAdvice(new MyInterceptor1()); AopInterface aopTester = (AopInterface) proxyFactory.getProxy(); System.out.println(aopTester.run("test")); } /** * 被代理的接口 */ public static interface AopInterface{ public String run(String s); } /** * 被代理的類 */ public static class AopTester implements AopInterface{ @Override public String run(String s){ return s+" ing ..."; } } /** * 攔截器1,也是advice,提供通知 */ public static class MyInterceptor1 implements MethodInterceptor{ @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("1 before"); Object obj = invocation.proceed(); System.out.println(obj); System.out.println("1 after"); return "1 "+obj; } } /** * 攔截器2,也是advice,提供通知 */ public static class MyInterceptor2 implements MethodInterceptor{ @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("2 before"); Object obj = invocation.proceed(); System.out.println(obj); System.out.println("2 after"); return "2 "+obj; } } }
spring的aop以動態代理爲技術基礎,結合JDK和cglib的proxy方案,抽象出Pointcut和Advice兩個核心接口,讓使用者很是方便的控制須要攔截的內容以及攔截後的邏輯。spa
版本 4.3.10.RELEASE翻譯