1. 程式人生 > >AOP底層原理解析

AOP底層原理解析

1 什麼是AOP:

  1. AOP AspectOrientedPrograming面向切面程式設計
  2. AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼(效能監視、事務管理、安全檢查、快取)
  3. Spring AOP使用純Java實現,不需要專門的編譯過程和類載入器,在執行期通過代理方式向目標類織入增強程式碼
  4. AspecJ是一個基於Java語言的AOP框架,Spring2.0開始,Spring AOP引入對Aspect的支援,
  5. AspectJ擴充套件了Java語言,提供了一個專門的編譯器,在編譯時提供橫向程式碼的織入

2 AOP底層原理;

  1. 就是代理機制:
  2. *動態代理:(JDK中使用)
    • * JDK
      的動態代理,對實現了介面的類生成代理.

3 SpringAOP代理:

  1. JDK動態代理:對實現了介面的類生成代理
  2. CGLib代理機制:對類生成代理

4 AOP的術語:

  1. Joinpoint(連線點):所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點.
  2. Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進行攔截的定義.
  3. Advice(通知/增強):所謂通知是指攔截到Joinpoint之後所要做的事情就是通知.通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
  4. Introduction
    (引介):引介是一種特殊的通知在不修改類程式碼的前提下,Introduction可以在執行期為類動態地新增一些方法或Field.
  5. Target(目標物件):代理的目標物件
  6. Weaving(織入):是指把增強應用到目標物件來建立新的代理物件的過程.
  7. Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類
  8. Aspect(切面):是切入點和通知(引介)的結合
  1. spring採用動態代理織入,而AspectJ採用編譯期織入和類裝在期織入
  1. 對於不使用介面的業務類,無法使用JDK動態代理
  2. CGlib採用非常底層位元組碼技術,可以為一個類建立子類,解決無介面代理問題

5 AOP的底層實現
:

   5.1 JDK動態代理

  1. JDK1.3引入動態代理技術
  2. 編寫動態代理程式
  3. java.lang.reflect.Proxy
  4. java.lang.reflect.InvocationHandler
  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. /**
  5. * @Title: JDK的動態代理的機制
  6. * @ClassName:JDKProxy.java
  7. * @Description:
  8. *
  9. * @Copyright 2016-2017 Powered By 研發中心
  10. * @author: 王延飛
  11. * @date:2016年9月19日 下午10:28:08
  12. * @version V1.0
  13. */
  14. publicclassJDKProxyimplementsInvocationHandler[]{
  15. privateUserDao userDao;
  16. publicJDKProxy(UserDao userDao){
  17. super();
  18. this.userDao = userDao;
  19. }
  20. publicUserDao createProxy(){
  21. UserDao proxy =(UserDao)Proxy.newProxyInstance(userDao.getClass()
  22. .getClassLoader(), userDao.getClass().getInterfaces(),this);
  23. return proxy;
  24. }
  25. // 呼叫目標物件的任何一個方法 都相當於呼叫invoke();
  26. publicObject invoke(Object proxy,Method method,Object[] args)
  27. throwsThrowable{
  28. if("add".equals(method.getName())){
  29. // 記錄日誌:
  30. System.out.println("日誌記錄=================");
  31. Object result = method.invoke(userDao, args);
  32. return result;
  33. }
  34. return method.invoke(userDao, args);
  35. }
  36. }

    5.2 CGLIB動態代理

  1. 對於不使用介面的業務類,無法使用JDK動態代理
  2. CGlib採用非常底層位元組碼技術,可以為一個類建立子類,解決無介面代理問題
  1. import java.lang.reflect.Method;
  2. import org.springframework.cglib.proxy.Enhancer;
  3. import org.springframework.cglib.proxy.MethodInterceptor;
  4. import org.springframework.cglib.proxy.MethodProxy;
  5. /**
  6. * 使用CGLib生成代理物件
  7. *
  8. */
  9. publicclassCGLibProxyimplementsMethodInterceptor{
  10. privateProductDao productDao;
  11. publicCGLibProxy(ProductDao productDao){
  12. super();
  13. this.productDao = productDao;
  14. }
  15. publicProductDao createProxy(){
  16. // 使用CGLIB生成代理:
  17. // 1.建立核心類:
  18. Enhancer enhancer =newEnhancer();
  19. // 2.為其設定父類:
  20. enhancer.setSuperclass(productDao.getClass());
  21. // 3.設定回撥:(相當於JDK動態代理中的回撥)
  22. enhancer.setCallback(this);
  23. // 4.建立代理:
  24. return(ProductDao) enhancer.create();
  25. }
  26. /** * @param proxy CGlib根據指定父類生成的代理物件 * @param method 攔截的方法 * @param args 攔截方法的引數陣列 * @param methodProxy 方法的代理物件,用於執行父類的方法 * @return */
  27. publicObject intercept(Object proxy,Method method,Object[] args,
  28. MethodProxy methodProxy)throwsThrowable{
  29. if("add".equals(method.getName())){
  30. System.out.println("日誌記錄==============");
  31. // 放行程式碼:這裡相當於JDK中的(method.invoke)
  32. Object obj = methodProxy.invokeSuper(proxy, args);
  33. return obj;
  34. }
  35. return methodProxy.invokeSuper(proxy, args);
  36. }
  37. }

    5.3 代理總結

  1. Spring在執行期,生成動態代理物件,不需要特殊的編譯器
  2. Spring AOP的底層就是通過JDK動態代理或CGLib動態代理技術為目標Bean執行橫向織入
    • 1.若目標物件實現了若干介面,spring使用JDKjava.lang.reflect.Proxy類代理。
    • 2.若目標物件沒有實現任何介面,spring使用CGLIB庫生成目標物件的子類。
  3. 程式中應優先對介面建立代理,便於程式解耦維護
  4. 標記為final的方法,不能被代理,因為無法進行覆蓋
    • JDK動態代理,是針對介面生成子類,介面中方法不能使用final修飾
    • CGLib是針對目標類生產子類,因此類或方法不能使final
  5. Spring只支援方法連線點,不提供屬性連線