Spring中的两种代理JDK和CGLIB的区别浅谈
一、原理区别:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用invokehandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用jdk的动态代理实现aop
2、如果目标对象实现了接口,可以强制使用cglib实现aop
3、如果目标对象没有实现了接口,必须采用cglib库,spring会自动在jdk动态代理和cglib之间转换
如何强制使用cglib实现aop?
(1)添加cglib库,spring_home/cglib/.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
jdk动态代理和cglib字节码生成的区别?
(1)jdk动态代理只能对实现了接口的类生成代理,而不能针对类
(2)cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
二、代码实现
package com.fy.spring.proxy; public interface usermanager { public void adduser(string id, string password); public void deluser(string id); }
package com.fy.spring.proxy; public class usermanagerimpl implements usermanager { public void adduser(string id, string password) { system.out.println(".: 掉用了usermanagerimpl.adduser()方法! "); } public void deluser(string id) { system.out.println(".: 掉用了usermanagerimpl.deluser()方法! "); } }
jdk动态代理类
package com.fy.spring.proxy; import java.lang.reflect.invocationhandler; import java.lang.reflect.method; import java.lang.reflect.proxy; /** * * jdk动态代理类 * * */ public class jdkproxy implements invocationhandler { private object targetobject;//需要代理的目标对象 public object newproxy(object targetobject) {//将目标对象传入进行代理 this.targetobject = targetobject; return proxy.newproxyinstance(targetobject.getclass().getclassloader(), targetobject.getclass().getinterfaces(), this);//返回代理对象 } public object invoke(object proxy, method method, object[] args)//invoke方法 throws throwable { checkpopedom();//一般我们进行逻辑处理的函数比如这个地方是模拟检查权限 object ret = null; // 设置方法的返回值 ret = method.invoke(targetobject, args); //调用invoke方法,ret存储该方法的返回值 return ret; } private void checkpopedom() {//模拟检查权限的例子 system.out.println(".:检查权限 checkpopedom()!"); } }
cglibproxy动态代理类
package com.fy.spring.proxy; import java.lang.reflect.method; import net.sf.cglib.proxy.enhancer; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodproxy; /** * cglibproxy动态代理类的实例 * * */ public class cglibproxy implements methodinterceptor { private object targetobject;// cglib需要代理的目标对象 public object createproxyobject(object obj) { this.targetobject = obj; enhancer enhancer = new enhancer(); enhancer.setsuperclass(obj.getclass()); enhancer.setcallback(this); object proxyobj = enhancer.create(); return proxyobj;// 返回代理对象 } public object intercept(object proxy, method method, object[] args, methodproxy methodproxy) throws throwable { object obj = null; if ("adduser".equals(method.getname())) {// 过滤方法 checkpopedom();// 检查权限 } obj = method.invoke(targetobject, args); return obj; } private void checkpopedom() { system.out.println(".:检查权限 checkpopedom()!"); } }
测试类:
public class client { public static void main(string[] args) { usermanager usermanager = (usermanager) new cglibproxy() .createproxyobject(new usermanagerimpl()); system.out.println("-----------cglibproxy-------------"); usermanager.adduser("tom", "root"); system.out.println("-----------jdkproxy-------------"); jdkproxy jdkprpxy = new jdkproxy(); usermanager usermanagerjdk = (usermanager) jdkprpxy .newproxy(new usermanagerimpl()); usermanagerjdk.adduser("tom", "root"); } }
运行结果:
-----------cglibproxy-------------
检查权限 checkpopedom()!
掉用了usermanagerimpl.adduser()方法!
-----------jdkproxy-------------
检查权限 checkpopedom()!
掉用了usermanagerimpl.adduser()方法!
jdk代理是不需要以来第三方的库,只要要jdk环境就可以进行代理,它有几个要求
- 实现invocationhandler
- 使用proxy.newproxyinstance产生代理对象
- 被代理的对象必须要实现接口
cglib 必须依赖于cglib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用jdk的代理
在hibernate中的拦截器其实现考虑到不需要其他接口的条件hibernate中的相关代理采用的是cglib来执行。
希望本文所述对你有所帮助,spring中的两种代理jdk和cglib的区别浅谈内容就给大家介绍到这里了。希望大家继续关注我们的网站!想要学习java可以继续关注本站。
上一篇: asp.net服务器端指令include的使用及优势介绍
下一篇: mysql事件的开启和调用
推荐阅读
-
Spring中的两种代理JDK和CGLIB的区别浅谈
-
Spring AOP中的JDK和CGLib动态代理哪个效率更高?
-
Spring AOP中的JDK和CGLib动态代理哪个效率更高?
-
详解Spring的两种代理方式:JDK动态代理和CGLIB动态代理
-
详解Spring的两种代理方式:JDK动态代理和CGLIB动态代理
-
Spring AOP 代理实现的两种方式: JDK动态代理 和 Cglib框架动态代理
-
【Spring AOP源码】基于JDK动态代理和Cglib创建代理对象的原理分析
-
Java中动态代理的两种方式JDK动态代理和cglib动态代理以及区别
-
解析动态代理jdk的Proxy与spring的CGlib(包括区别介绍)
-
01 动态代理是如何实现的?JDK Proxy 和 CGLib 有什么区别?