CGLIB动态代理
cglib是什么?
CGLIB(Code Generation Library)是一个开源项目!
是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。
CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。最流行的OR Mapping工具hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实现的)。EasyMock和jMock是通过使用模仿(mock)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿(mock)对象。
CGLIIB实现动态代理
先来个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.MethodInterceptor
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不用写接口
Spring中的aop也可以通过配置采用Cglib方式
除了CGLIB包,脚本语言例如Groovy和BeanShell,也是使用ASM来生成java的字节码。当然不鼓励直接使用ASM,
因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉,所以推荐用Cglib