重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Cglib动态代理是怎么实现的?针对这个问题,今天小编总结这篇有关Cglib动态代理的文章,可供感兴趣的小伙伴们参考借鉴,希望对大家有所帮助。
创新互联服务项目包括南陵网站建设、南陵网站制作、南陵网页制作以及南陵网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,南陵网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到南陵省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
Spring Aop是使用动态代理技术动态的生成目标对象的代理对象完成对目标方法增强的,要彻底理解Spring Aop就需要先理解动态代理,动态代理分为两种jdk动态代理和cglib动态代理
Jdk动态代理:针对的是实现了接口的目标类,它使用jdk中的Proxy来创建代理对象。
关于动态代理和jdk动态代理,我在另一篇文章中有详细描述,下面我们 来看一下Cglib动态代理
Cglib动态代理:针对没有实现接口的目标类,它使用字节码增强的技术,通过动态创建目标类的子类对象在子类对象中增强目标类的方法实现,它需要引入asm.jar依赖。
Cglib动态代理是如何实现的呢?下面通过一个例子加以说明:
创建一个UserDao类:
public classUserDao {
public voidaddUser(){
System.out.println("添加用户");
}
public voiddeleteUser(){
System.out.println("删除用户");
}
}
创建代理类:
public classcglibProxyimplementsMethodInterceptor {
privateUserDaotarget;//被代理的目标类
public voidcglibProxy(UserDao target){
super(target);
this.target=target;
}
//创建代理对象
publicObjectcreateProxy(){
// 1.声明Enhancer类实例,用于生产代理类
Enhancer enhancer =newEnhancer();
// 2.设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
enhancer.setSuperclass(target.getClass());
// 3.//设置回调函数
enhancer.setCallback(this);
// 4.创建代理:
return(UserDao) enhancer.create();
}
/**
*回调函数
* @paramproxy目标对象
* @parammethod要增强的方法
* @paramargs要增强的方法参数
* @parammethodProxy方法的代理对象 * */
@Override
publicObject intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throwsThrowable {
//过滤不需要该业务的方法
if("addUser".equals(method.getName())) {
//调用目标对象的方法(执行UserDao对象即被代理对象的addUser方法)
Object result = methodProxy.invokeSuper(proxy, args);
//记录日志
Record.addRecord();
returnresult;
}else if("deleteUser".equals(method.getName())){
//.....
returnmethodProxy.invokeSuper(proxy, args);
}
//如果不需要增强直接执行原方法
returnmethodProxy.invokeSuper(proxy, args);
}
}
调用:
public classMyTest {
public static voidmain(String[] args) {
//创建目标对象
UserDao user=newUserDao();
//创建代理类对象
cglibProxy cglibProxy =newcglibProxy (user);
//生成目标类的代理对象
UserDao proxy = (UserDao)cglibProxy.createProxy();
//调用addUser方法
proxy.addUser();
}
}
打印的结果是:添加用户 记录日志,addUser方法被增强了
从上面的例子可以看到通过createProxy方法就可以创建代理对象,我们细致分析一下它创建对象的过程:
public voidcreateProxy(){
// 1.声明Enhancer类实例,用于生产代理类
Enhancer enhancer =newEnhancer();
// 2.设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
enhancer.setSuperclass(target.getClass());
// 3.//设置回调函数
enhancer.setCallback(this);
// 4.创建代理:
return(UserDao) enhancer.create();
}
第一行代码: Enhancer enhancer =newEnhancer();中的Enhancer是一个非常重要的类,它允许为非接口类型创建一个JAVA代理,Enhancer动态的创建给定类的子类并且拦截代理类的所有的方法,和JDK动态代理不一样的是不管是接口还是类它都能正常工作。
第二行代码:enhancer.setSuperclass(target.getClass());这行代码的意思是设置被代理类字节码,为什么要设置被代理类的字节码呢?CGLIB底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类。所以需要获取字节码,巧妇难为无米之炊哈。
第三行代码:enhancer.setCallback(this);设置回调函数,这里有一个参数this表示当前对象也就是cglibUser对象,因为cglibUser类实现了接口MethodInterceptor,也实现了接口的方法:intercept,这个方法就是回调方法。当我们去调用代理类对象的方法时就会转变为去执行这个方法。
第四行代码:return(UserDao) enhancer.create();这行代码就是去创建目标对象的代理对象,他是通过创建目标对象的子类对象来实现的。
再来详细的分析一下回调方法:intercept
@Override
publicObject intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throwsThrowable {
//如果方法名为addUser
if("addUser".equals(method.getName())) {
//调用目标对象的方法(执行UserDao对象即被代理对象的addUser方法)
Object result = methodProxy.invokeSuper(proxy, args);
//记录日志
Record.addRecord();
returnresult;
}else if("deleteUser".equals(method.getName())){
//.....
returnmethodProxy.invokeSuper(proxy, args);
}
//如果不需要增强直接执行原方法
returnmethodProxy.invokeSuper(proxy, args);
}
我们看看这个方法的参数:intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
第一个参数:Object proxy表示目标对象,也就是需要被代理的对象
第二个参数:Method method表示要被增强的方法
第三个参数:Object[] args 表示方法的参数
第四个参数:MethodProxy methodProxy每个被代理的方法都对应一个MethodProxy对象,它是由cglib生成的,methodProxy.invokeSuper方法最终调用目标类的原始方法,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升。
在这个方法里面我们可以判断当前执行的方法是否为需要被增强的方法,并做相应的增强处理。
比较一下jdk动态代理和cglib动态代理:
一:jdk动态代理使用jdk中的类Proxy来创建代理对象,它使用反射技术来实现,我们通过它来实现Spring Aop方法增强的时候不需要导入其它依赖。cglib需要引入相关依赖:asm.jar,它使用字节码增强技术来实现。
二:当目标类实现了接口的时候Spring Aop默认使用jdk动态代理方式来增强方法,没有实现接口的时候使用cglib动态代理方式增强方法
三: 在jdk1.8前,cglib生成的代理对象的执行效率高于jdk方式,1.8之后基本没有区别。
看完上述内容,你们对Cglib动态代理有进一步的了解吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读。