前一節所說的靜態代理和動態代理模式都是要求目標對象是實現一個接口的目標對象,但是有時候目標對象只是一個單獨的對象,並沒有實現任何的接口,這個時候就可以使用以目標對象子類的方式類實現代理,這種方法就叫做:Cglib代理
1.Cglib說明
Cglib代理,也叫作子類代理,它是在內存中構建一個子類對象從而實現對目標對象功能的擴展。
Cglib是一個強大的高性能的代碼生成包,它可以在運行期擴展java類與實現java接口。它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,爲他們提供方法的interception(攔截)
Cglib包的底層是通過使用一個小而塊的字節碼處理框架ASM來轉換字節碼並生成新的類。不鼓勵直接使用ASM,因爲它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉。
2.Cglib實現
Clinet:客戶端調用
RealSubject、RealSubject2:無繼承,真實角色
CglibSubject:繼承MethodInterceptor,動態代理生成類
Client.java
public class Client {
public static void main(String[] args)
{
CglibSubject cglibSubject = new CglibSubject();
RealSubject realSubject = (RealSubject)cglibSubject.getInstance(new RealSubject());
realSubject.request();
RealSubject2 realSubject2 = (RealSubject2)cglibSubject.getInstance(new RealSubject2());
realSubject2.request2();
}
}
CglibSubject.java
public class CglibSubject implements MethodInterceptor {
private Object sub;
/**
* 創建代理對象
*
* @param sub
* @return
*/
public Object getInstance(Object sub) {
this.sub = sub;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.sub.getClass());
// 回調方法
enhancer.setCallback(this);
// 創建代理對象
return enhancer.create();
}
@Override
// 回調方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
proxy.invokeSuper(obj, args);
log(sub.getClass().getName());
return null;
}
private void log(String className)
{
System.out.println("代理AOP切入--打印log--"+className);
}
}
RealSubject.java 和 RealSubject2.java
public class RealSubject{
public void request() {
System.out.println("From Real Subject1!");
}
}
public class RealSubject2{
public void request2() {
System.out.println("From Real Subject2!");
}
}
3.Cglib對比
類別 | 靜態代理個數 | 動態代理個數 | Cglib動態代理 |
---|---|---|---|
抽象角色 | n | n | 0 |
真實角色 | n | n | n |
動態代理生成類 | n | 1 | 1 |