CGLIB(Code Generation Library)是一個開源項目!java
是一個強大的,高性能,高質量的Code生成類庫,它能夠在運行期擴展Java類與實現Java接口。spring
CGLIB是一個強大的高性能的代碼生成包。它普遍的被許多AOP的框架使用,例如Spring AOP和dynaop,爲他們提供方法的interception(攔截)。最流行的OR Mapping工具hibernate也使用CGLIB來代理單端single-ended(多對一和一對一)關聯(對集合的延遲抓取,是採用其餘機制實現的)。EasyMock和jMock是經過使用模仿(mock)對象來測試java代碼的包。它們都經過使用CGLIB來爲那些沒有接口的類建立模仿(mock)對象。app
先來個service 注意沒有接口框架
public class CglibService {
public CglibService() {
System.out.println("CglibDao 構造方法");
}
/** * 該方法不能被子類覆蓋,Cglib是沒法代理final修飾的方法的 * @param name * @return */
final public String sayOthers(String name){
System.out.println("CglibDao final sayOthers:"+name);
return null;
}
public void sayHello(){
System.out.println("CglibDao:sayHello");
}
}
複製代碼
新建一個Interceptor實現org.springframework.cglib.proxy.MethodInterceptoride
public class MyMethodInterceptor implements MethodInterceptor {
/** * * @param o 代理對象 * @param method 被代理的對象方法 * @param objects 方法入參 * @param methodProxy 代理方法 * @return * @throws Throwable */
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("======插入前置通知======");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("======插入後置通知======");
return object;
}
}
複製代碼
新建測試類工具
/** * cglib 動態代理測試 */
public class cglibAgentTest {
@Test
public void testCglibAgent(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibService.class);
// 設置enhancer的回調對象
enhancer.setCallback(new MyMethodInterceptor());
// 建立代理對象
CglibService proxy= (CglibService)enhancer.create();
// 經過代理對象調用目標方法
proxy.sayHello();
proxy.sayOthers("小明");
}
}
複製代碼
打印的值性能
CglibDao 構造方法
======插入前置通知======
CglibDao:sayHello
======插入後置通知======
CglibDao final sayOthers:小明
複製代碼
能夠看出來 會先執行他的構造方法 當調用sayHello時候會先調用他們的代理方法 若是當方法爲final修飾時 沒法實現代理測試
Cglib與InvocationHandler實現的動態代理不一樣是 cglib不用寫接口spa
Spring中的aop也能夠經過配置採用Cglib方式hibernate
除了CGLIB包,腳本語言例如Groovy和BeanShell,也是使用ASM來生成java的字節碼。固然不鼓勵直接使用ASM,
由於它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉,因此推薦用Cglib