深入分析Spring源碼(三)----代理模式(cglib動態代理)

cglib是針對類來實現代理的,原理是對指定的業務類生成一個子類,並覆蓋其中業務方法實現代理。因爲採用的是繼承,所以不能對final修飾的類進行代理。 

public class Star{
    public void findLove(){
        System.out.println("===findLove===");
    }
}
  public class Meipo implements MethodInterceptor{
        private Object target;//業務類對象,供代理方法中進行真正的業務方法調用
    
        //相當於jdk動態代理中的綁定    
        public Object getInstance(Object target) throws Exception{
            this.target = target;  //給業務對象賦值
            Enhancer enhancer = new Enhancer();//創建加強器,用來創建動態代理類
            //爲加強器指定要代理的業務類,把父類設置爲誰?
            //這一步就是告訴cglib,生成的子類需要繼承哪個類
            enhancer.setSuperClass(this.target.getClass());
         //設置回調,對於代理類上所有方法的調用都會回調intercept方法。 同理jdk動態代理生成代理對象傳入this,回調對應的invoke方法
            enhancer.setCallback(this);
         //1.生成源代碼 2.編譯成class文件 3.加載到JVM中,創建動態代理類對象並返回  
           return  enhancer.create();
        }

        @Override
        public Object intercept(Object obj,Method method,Object[]args,MethodProxy proxy){
            System.out.println("===before====dosomething===");
            //這個obj的引用是由CGlib給我們new出來的
            //cglib new出來以後的對象,是被代理對象的子類(繼承了我們自己寫的那個類)
            //根據OOP,在new子類之前,實際上默認先調用了我們的super()方法的,
            //new子類的同時,必須先new出來父類,這就相當於是間接的持有了我們父類的引用
            //子類重寫了父類的所有的方法
            //我們改變子類對象的某些屬性,是可以間接的操作父類的屬性的
            proxy.invokeSuper(obj,args);
            System.out.println("====after===dosomething==");
            return null;
        }
  }

JDK的動態代理是通過接口進行強制轉換的,生成以後的代理對象,可以強制轉換爲接口

CGlib的動態代理是通過生成一個被代理對象的子類,然後重寫父類的方法,生成的對象,可以強制轉換爲被代理對象(也就是自己寫的類),子類引用賦值給父類

public class TestCGlibProxy{

    public static void main(String[]args){
        try{
            Star star = new Star();
            MeiPo p = new Meipo();
            Star s = (Star)p.getInstance(star);
            s.findLove();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

動態代理可以做一件什麼事情?

                     可以在每一個方法方法調用之前加一些代碼,在方法調用之後再加一些代碼

                    例:AOP:事務代理(聲明式事務,哪些方法需要加事務,哪個方法不需要加事務)、日誌監聽

service方法

開啓一個事務(open)

事務的執行(是由我們自己的代碼完成的)

監聽是否有異常,可能需要根據異常的類型來決定這個事務是要回滾還是繼續提交 (commit/rollback)

事務關閉(close)

 

 

  動態代理和靜態代理的比較

    靜態代理是通過在代碼中顯式定義一個業務實現類一個代理,在代理類中對同名的業務方法進行包裝,用戶通過代理類調用被包裝過的業務方法;

    JDK動態代理是通過接口中的方法名,在動態生成的代理類中調用業務實現類的同名方法;

    CGlib動態代理是通過繼承業務類,生成的動態代理類是業務類的子類,通過重寫業務方法進行代理;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章