使用cglib实现动态代理
在上篇博客java动态代理中我对java的动态代理进行了讲解,但是我也说过,java的动态代理有一种缺点,那就是业务类必须要有接口,但是在实际情况中我们要横切的业务类并不一定有接口,这个时候java的动态代理自然就不能使用了,为了解决这一问题,于是就出现了cglib,cglib可以说是很给力了,因为他的业务类有无接口皆可.
废话不多说,上代码
- 通过目标对象生成代理对象,通过cglib的api生成代理对象
/**
* 此类是一个工厂类
* 专门用来生成cglib的动态代理对象
* @author Administrator
*/
public class CGLIBProxy {
/**
* @param targetObject 目标对象
* @return proxyObject 代理对象
* proxyObject和targetObject是父子关系
* targetObject所对应的目标类是父类,目标类不能是final修饰的
* proxyObject所对应的类是子类(由cglib创建的代理类)
*/
public static Object getProxyObject(Object targetObject){
Object proxyObject=null;
//enhancer:增强,加强
Enhancer enhancer=new Enhancer();
//cglib动态代理有无接口皆可
enhancer.setInterfaces(targetObject.getClass().getInterfaces());
//设置代理类的父类
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback(new TransactionInterceptor(targetObject));
/*
* 用cglib来创建代理类,其底层cglib引用第三方功能jar asm.jar
* asm是一个java字节码生成框架,他是以二进制形式修改已有的类,
* 来生成动态代理类的字节码,asm可以直接产生二进制的class字节码文件
* 也可以生成字节码在内存,\
* asm在创建class字节码,使用的是底层jvm的指令级别,所以创建字节码的时候
* 偏慢(相对于jdk生成字节码),但创建完的字节码,运行时cglib偏快(相对于jdk)
*/
proxyObject=enhancer.create();//用cglib来创建代理类
return proxyObject;
}
}
- 下面这个类是不是很熟悉,没错他就是耦合新旧业务而成的新的业务类,在运行的时候会通过回调生成代理对象.
public class TransactionInterceptor implements MethodInterceptor{
private Object targetObject;
public TransactionInterceptor(Object targetObject) {
this.targetObject = targetObject;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object returnValue=null;
TransactionManager tm=new TransactionManager();
try{
tm.begin();
returnValue=method.invoke(targetObject, args);//用目标对象调用目标方法,returnValue是目标方法的返回值
//returnValue=methodProxy.invoke(targetObject, args);
tm.commit();
}catch(Exception e){
e.printStackTrace();
tm.rollback();
}
return returnValue;
}
}
**
补充
**:本方法(intercept)的返回值不一定就是目标方法的返回值可以对目标方法的返回值做过其他的处理后,再通过本方法返回
讲完了jdk的动态代理和cglib的动态代理,我们来对这两种动态代理方式做一下总结
****jdk和cglib的区别:
jdk动态代理:
1.业务类必须有接口
2.必须实现InvocationHandler接口,在接口的子实现中耦合原有业务和新业务
3.代理类和业务类是兄弟关系,因为隶属于同一个接口
4.用jdk创建代理,创建代理快,执行代理类慢
cglib动态代理:
1.业务类有无接口皆可
2.必须实现MethodInterceptor接口,在接口的子实现中耦合原有业务和新业务
3.代理类和业务类是父子,业务类是父,代理类是子
4.用asm和cglib创建代理类,创建慢,执行快
5.业务类不用final修饰
用jdk和cglib动态代理,在没有特别java代码处理的前提下,是给业务类的所有方法横切/织入新功能,spring aop自己创建了一套表达式语言,通过这些表达式,可以轻松控制业务类中的某些方法添加横切,或不添加横切,spring aop底层用的就是动态代理有业务接口用jdk动态代理,没有业务接口用cglib动态代理