AOP技術討論

#1 2015-10-14 AOP討論java

強烈推薦文章正則表達式

本文則是根據上述文章進行的羣內討論的提綱編程

#2 從AOP攔截的時機來看待AOPjvm

  • 編譯期
  • 字節碼加載前
  • 字節碼加載後

如圖:ide

AOP實現機制分類

  • 1 aspectj : 在編譯期靜態植入工具

  • 2 JDK Proxy: 目標類加載後,爲其接口動態生成代理類this

  • 3 cglib : 目標類加載後,爲其動態生成子類,將切面邏輯加入子類中.net

  • 4 自定義類加載器:在目標類加載前,將切面邏輯加入目標類字節碼中代理

  • 5 字節碼轉換器:在目標類加載前,將切面邏輯加入目標類字節碼中(jdk1.5的Instrumentation);在目標類加載後,將切面邏輯加入目標類字節碼中(jdk1.6的Instrumentation觸發jvm從新類加載)日誌

    在類的字節碼載入jvm前會調用ClassFileTransformer的transform方法,從而實現修改原類方法的功能,實現aop

    日誌記錄工具anylog,就是使用自定義的ClassFileTransformer來動態修改字節碼(內部藉助於javassist來修改字節碼)

#3 角色梳理:AOP聯盟、Aspectj、SpringAOP

##3.1 AOP的概念

  • Pointcut:切入點,表示在哪裏進行攔截,簡單理解如正則表達式

  • Joinpoint:鏈接點,符合上述正則表達式的一個具體對象

  • Advice:加強,即攔截邏輯

    Advice的類型:

    • 1 前置加強(Before advice)
    • 2 後置返回加強(After returning advice)
    • 3 後置異常加強(After throwing advice)
    • 4 環繞加強(Around Advice)
    • 5 引入加強(對類進行加強)
  • Aspect:切面,包含切入點和加強

  • Target Object:要代理的目標對象

  • AOP Proxy:代理對象

  • Weaving:織入,能夠是編譯期、字節碼加載前、字節碼加載後

##3.2 Aspectj

以下簡單使用案例:

aspectj使用案例

這裏有個系列文章跟我學aspectj

  • 在編譯時期就織入
  • 不能使用傳統的JDK編譯
  • 等等

#4 SpringAOP的發展歷程

##4.1 JDK和CGLib動態代理的原始方式

JDK動態代理:

JDK動態代理

CGLib動態代理:

CGLib動態代理

##4.2 ProxyFactory對jdk和cglib的封裝

ProxyFactory簡單的對jdk和cglib的封裝,根據配置(強制採用cglib)或者自行決定(根據是否實現接口)採用jdk動態代理仍是cglib動態代理。

使用案例以下:

ProxyFactory使用案例

對jdk動態代理的封裝(cglib也相似再也不說明):

InvocationHandler h:固定是JdkDynamicAopProxy,其中對

InvocationHandler的接口方法Object invoke(Object proxy, Method method, Object[] args)實現以下:

JdkDynamicAopProxy對InvocationHandler的實現

  • 第一步:根據調用的類和方法獲取攔截器MethodInterceptor集合,內部會使用pointcut來進行過濾。後面詳細說說MethodInterceptor和Advice的區別。

    ProxyFactory有以下兩種方法:

    addAdvice(Advice advice)
    addAdvisor(Advisor advisor)

    Advisor:實際上是Advice和Pointcut的集合,因此在添加Advice是會給出一個默認的Pointcut

    Pointcut能夠是:

    • 正則表達式類型 JdkRegexpMethodPointcut

    • aspectj的pointcut表達式類型,如

      execution(* com.aspectj.demo.test.HelloWorld.main(..))
      @annotation(aop.demo.Tag)
  • 第二步:若是攔截器集合爲空(即沒有代理該方法),則經過反射直接執行目標對象target的方法

  • 第三步:若是攔截器集合不爲空,依次執行攔截器MethodInterceptor中的invoke方法。

MethodInterceptor和Advice的區別:

Advice:定義了攔截邏輯,如MethodBeforeAdvice,接口定義以下:

public interface MethodBeforeAdvice extends BeforeAdvice {
	void before(Method method, Object[] args, Object target) throws Throwable;
}

而MethodInterceptor則是決定Advice的調用時機,同時對外提供統一的調用方法invoke,如MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}
}

上述就是ProxyFactory對jdk和cglib的封裝,簡化了咱們的操做。可是還有以下問題:

  • 一個ProxyFactory只能代理一個目標對象target
  • 還要手動的配置每個Advisor bean對應的Advice和Pointcut。

##4.3 批量代理

上述ProxyFactory還只能針對某一個target進行代理

咱們如今的需求是:對一批對象進行批量代理。這時須要兩大部分:

  • 一批Advice和Pointcut組合,即會有多個Advisor,符合不一樣Pointcut的進行不一樣的Advice加強。這裏即切面,切面並無具體的類進行描述,能夠理解成一個Advisor的集合(一個Advisor包含了一個Advice和一個Pointcut),以下所示

    如xml配置形式配置切面:

    xml配置形式配置切面

    註解形式配置切面,同時要開啓aop:aspectj-autoproxy配置:

    註解形式配置切面

  • 切面僅僅是描述哪些類的哪些方法被哪些Advice加強,僅僅是描述而已,須要有一個類來承擔這樣的批量代理的工做,這就是基類AbstractAutoProxyCreator來完成這一項工做,對於每個符合條件的bean都仍然採用ProxyFactory來進行代理的建立:

    AbstractAutoProxyCreator批量代理

    因此Spring中的AOP所有是基於ProxyFactory這套建立流程的。而AbstractAutoProxyCreator子類則是分別取解析不一樣的切面配置

    如上述的aop:config配置是啓用了AspectJAwareAdvisorAutoProxyCreator來進行批量代理的

    如上述註解形式開啓的aop:aspectj-autoproxy是啓用了AnnotationAwareAspectJAutoProxyCreator來進行批量代理的

##4.4 Spring對aspectj的引入的體現

咱們知道aspectj是靜態織入,Spring是怎麼來引入aspectj呢?

aspectj是靜態織入,須要單獨的編譯器來進行編譯,可是功能強大。如使用案例:

aspectj使用案例

強大的pointcut表達式功能(具體的自行去搜),同時還具備了註解功能,以下:

等這些都是aspectj的實現

而什麼才叫Spring最原始的AOP呢?就是ProxyFactory這一層,僅僅對jdk和cglib進行了簡單的封裝。

Spring原始的ProxyFactory代理,手動編程或配置進行代理都比較麻煩,引入了aspectj的某些功能

  • 引入了aspectj的pointcut表達式功能
  • 引入了上述註解功能

可是引入以後呢,仍是所有轉化成Spring本來的Advisor,最終仍然使用本來的ProxyFactory來建立代理,而不是像aspectj那樣須要單獨的編譯器。

相關文章
相關標籤/搜索