JDK動態代理適用於已實現一組接口的類的情況,但如果類沒有實現接口,如何創建動態代理呢?那就使用CGLib代理,CGLib代理不再限制實現接口這一條件,它使用目標類,創建它的子類的方式,來實現代理,示例代碼如下:
public class LearnService {
public void read() {
System.out.println("read()...");
}
}
public class CGLibProxy implements MethodInterceptor{
Enhancer enhancer = new Enhancer();
/**
* 創建代理對象
* @param target
* @return
*/
public Object getProxy(Class<?> clazz){
//設置需要創建子類的類
enhancer.setSuperclass(clazz);
//回調方法
enhancer.setCallback(this);
//通過字節碼技術動態創建子類實例
return enhancer.create();
}
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("cglib-start...");
Object result = proxy.invokeSuper(object, args);
System.out.println("cglib-end...");
return result;
}
}
public class CGLibProxyDemo {
public static void main(String[] args) {
CGLibProxy proxy = new CGLibProxy();
LearnService ls = (LearnService)proxy.getProxy(LearnService.class);
ls.read();
System.out.println(ls.getClass().getName());
}
}
運行結果:
cglib-start...
read()...
cglib-end...
com.java.proxy.cglib.LearnService$$EnhancerByCGLIB$$710efc3a
CGLib與JDK動態代理的比較:
1、JDK採用反射+接口方式,CGLib採用反射創建子類
2、JDK不能創建沒有實現接口類的代理,CGLib不能創建final修飾的類的代理,不能代理final修飾的方法
3、JDK動態代理不用依賴額外的庫,更輕量,CGLib需要依賴CGLib等類庫
4、CGLib代理要求類必須有無參構造