Spring AOP實現原理

用到了AOP的動態代理模式: java

1.畫圖:把切面畫出來 性能

2.舉個例子進行說明 this

3:實現原理: spa


切面的意義何在?
  設計

首先根據上例,假設咱們實現了一個通用的權限檢查模塊,那麼就能夠在這層切面上進
 行統一的集中式權限管理。權限檢查模塊能夠和業務邏輯代碼分離,而業務邏輯組件則無需關心權限方面的問題。系統大部分有權限檢查模塊,用的時候直接拿來用這個切面。也就是說,經過切面,咱們能夠將系統中各個不一樣層次上的問題隔離開來,實現統一集約式處理。各切面只需集中於本身領域內的邏輯實現。  代理


這一方面使得開發邏輯更加清晰,專業化分工更加易於進行;另外一方面,因爲切面的隔 日誌


離,下降了耦合性,咱們就能夠在不一樣的應用中將各個切面組合使用,從而使得代碼可重用 對象


性大大加強。  繼承


JDKProxy


若是是面向接口的動態代理的實現,即JDKProxy,其代理對象必須是某個接口的實現,使用java.lang.reflect.Proxy類根據一個被代理對象產生一個代理對象userDAOProxy,經過Proxy類的調用靜態方法newProxyInstance,根據要實現的接口來產生(這裏爲UserDao接口)也就是說接口裏面有哪些方法,我生成的代理裏面就有哪些方法);以及實現java.lang.reflect.InvocationHandler接口,實現invoke方法實現方法的截獲處理,也就是在方法的先後加上業務邏輯。 接口


當你想在多個方法先後加上業務邏輯的時候,可使用動態代理,更加靈活方便,代碼的可重用性大大的提高。


根據一個被代理對象經過Proxy靜態方法newProxyInstance產生代理對象:


newProxyInstance裏面的參數解釋:


第一個參數是說與被代理對象有同一個ClassLoader,


第二個參數說產生的代理對象實現的那個接口應該與被代理對象實現同一個接口(UserDao),也能夠這樣寫new Class[]{UserDao.class}。


第三個參數:當產生代理以後,調用代理裏面的方法後要用哪一個Handler進行處理。


LogIntercepter li = new LogIntercepter();


li.setTarget(userDAO);//引入一個被代理的對象userDAO


UserDao userDAOProxy = (UserDao) Proxy.newProxyInstance(userDAO.getClass().getClassLoader(),userDAO.getClass().getInterfaces(), li);


實現InvocationHandler接口 :


public Object invoke(Object proxy, Method m, Object[] args)


throws Throwable {


beforeMethod();//在方法前面添加業務邏輯,也就是日誌


m.invoke(target, args);//target Method方法所屬的對象,表示被代理對象動態調用invoke()


return null;


}


CGLibProxy


若是沒有實現接口,也沒有關係,能夠用CGLib(面向Class)實現AOP


CGLibProxyJDKProxy的代理機制基本相似,只是其動態代理的代理對象並不是某個接口的實現,而是針對目標類擴展的子類。話句話說JDKProxy返回動態代理類,是目標類所實現接口的另外一個實現版本,它實現了對目標類的代理(如同UserDAOProxyUserDAOImp的關係),而CGLibProxy返回的動態代理類,則是目標代理類的一個子類(代理類擴展了UserDaoImpl


EnhancerMethodInterceptorCGLib中負責完成代理對象建立和方法截獲處理。


Enhancer建立代理對象,實現MethodInterceptor接口,實現intercept方法來進行方法截取處理。


(CGLib (Code Generation Library) 字節碼類庫是一個強大的,高性能,高質量的Code生成類庫。它能夠在運行期擴展Java類與實現Java接口。Hibernate用它來實現PO字節碼的動態生成。CGLib 比 Java 的 java.lang.reflect.Proxy 類更強的在於它不只能夠接管接口類的方法,還能夠接管普通類的方法。)


 
JDK動態代理和CGLIB字節碼生成的區別
 * JDK動態代理只能對實現了接口的類生成代理,而不能針對類.
 * CGLIB針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法
   由於是繼承,因此該類或方法最好不要聲明成final


JDK代理是不須要以來第三方的庫,只要JDK環境就能夠進行代理,它有幾個要求


實現InvocationHandler
* 使用Proxy.newProxyInstance產生代理對象


* 被代理的對象必需要實現接口


CGLib 必須依賴於CGLib的類庫,可是它須要類來實現任何接口代理的是指定的類生成一個子類,覆蓋其中的方法,是一種繼承

AOP的應用:

作權限的檢查:設計完備的權限管理組件,完成以往須要大費周折才能完成的權限斷定功能。

可是目前尚未一個完善的實現,一方面是由於權限檢查過於複雜多變,不一樣的業務邏輯中的權限斷定邏輯可能多種多樣;另外一方面,就目前的AOP應用的粒度而言,「權限管理」做爲一個切面顯得過於龐大,須要進一步設計,設計複雜,實現難度大。


,作日誌,作審計,作性能,作事務的處理。項目裏面主要用在了聲明式的事務處理上。

 

 

一、JDK方式:PersonService爲接口,PersonServiceBean爲實現類,


  public class JDKProxyFactory implements InvocationHandler {
   private
Object targetObject;
  
   public Object createProxyIntance(Object
targetObject)
   {
    this.targetObject=targetObject;
    return
Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
     
this.targetObject.getClass().getInterfaces(), this);
   }


public Object invoke(Object proxy, Method method, Object[] args)
  throws
Throwable {
    PersonServiceBean
person=(PersonServiceBean)this.targetObject;
    Object result=null;
    
if(person.getUser()!=null)
     { 
      result =
method.invoke(targetObject, args);
      }
   return result;
}
}


 二、使用CGlib包實現:PersonServiceBean爲實現類,   而沒有PersonService接口,         


public class CGlibProxyFactory implements MethodInterceptor{
  private
Object targetObject;
 
  public Object createProxyInstance(Object
targetObject)
  {
   this.targetObject=targetObject;
   Enhancer
enhancer=new Enhancer();
  
enhancer.setSuperclass(this.targetObject.getClass());//設置目標類的子類,該子類會覆蓋全部父類中的非final方法
  
enhancer.setCallback(this);//設置回調
  return  enhancer.create();
  }


public Object intercept(Object proxy, Method method, Object[] args,   MethodProxy methodProxy) throws Throwable {   PersonServiceBean person=(PersonServiceBean)this.targetObject;     Object result=null;      if(person.getUser()!=null)      {        result = methodProxy.invoke(targetObject, args);       }  return null; } }

相關文章
相關標籤/搜索