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動態代理是通過繼承業務類,生成的動態代理類是業務類的子類,通過重寫業務方法進行代理;