CGLib与JDKProxy的区别
Spring AOP 的实现主要有两种:CGLib与JDK自带的Proxy。
他们主要的区别是,需要JDKProxy修改的类必须实现接口(因此也只能代理public方法),在创建Proxy时可以使用class.getInterfaces()获得所有接口并进行代理。
而CGLib不受这个限制可以修改任何非private非final方法。
以上只是一些大家都知道的方面。在这两种方法的实现中,其实还是有其他一些重要的差别的,那就是调用代理类的方法内部同时调用了自己的另一个方法的话他们的最终结果将是不一样的,下面上代码!
//被代理对象接口
public interface DummyInterface {
void fun2();
void fun1();
}
//被代理对象实现
public class Dummy implements DummyInterface {
public Dummy(){
}
public void fun1(){
System.out.println("fun1 start");
fun2(); //调用内部方法fun2
System.out.println("fun1 end");
}
public void fun2() {
System.out.println("-fun2 start");
System.out.println("-fun2 end");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
//CGLib实现
public class CGlibEnhance implements MethodInterceptor{
public static void main(String[] args) {
CGlibEnhance ce = new CGlibEnhance();
Dummy dummy = (Dummy) ce.getProxy(Dummy.class);//获得代理对象
dummy.fun1();
System.out.println("----");
dummy.fun2();//直接调用fun2
}
public Object getProxy(Class<Dummy> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("pre-"+method.getName());
Object result = proxy.invokeSuper(obj,args);
System.out.println("post-"+method.getName());
return result;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//JDKProxy实现
public class JavaProxy implements InvocationHandler {
private Object target;//被代理对象
public JavaProxy(Object target) {
super();
this.target = target;
}
public static void main(String[] args) {
JavaProxy handler = new JavaProxy(new Dummy());
DummyInterface proxy = (DummyInterface) handler.getProxy();//获得代理对象
proxy.fun1();
System.out.println("----");
proxy.fun2();//直接调用fun2
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("pre-" + method.getName());
result = method.invoke(target, args);
System.out.println("post-" + method.getName());
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
}
}
以上两个方法都代理了Dummy对象并分别调用了fun1 fun2两个方法,fun1内部又调用了fun2。
两个结果却不一样
//cglib 输出
pre-fun1
fun1 start
pre-fun2 //★
-fun2 start
-fun2 end
post-fun2 //★
fun1 end
post-fun1
----
pre-fun2
-fun2 start
-fun2 end
post-fun2
//JDKProxy输出
pre-fun1
fun1 start
-fun2 start //★
-fun2 end //★
fun1 end
post-fun1
----
pre-fun2
-fun2 start
-fun2 end
post-fun2
可以看出在fun1调用fun2时(★处),JDKProxy并没有截获调用注入pre-fun2/post-fun2,但直接调用fun2时却截获到了方法调用。
其中原因是CGLib是使用继承的方式来改写原类,同时也可以看到在CGLib中我们并没有手动创建Dummy对象,因为CGLib create方法内部会自动创建。
而JDKProxy正如其名是Proxy,只是对原对象使用了代理模式,无法渗透到方法的内部调用。
这个从侧面说明了在spring AOP中如果被代理类进行类内部调用时会导致无法注入方法的情况。
CGLib与JDKProxy的区别的更多相关文章
- JDK和CGLIB动态代理原理区别
JDK和CGLIB动态代理原理区别 https://blog.csdn.net/yhl_jxy/article/details/80635012 2018年06月09日 18:34:17 阅读数:65 ...
- spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能
一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能 ...
- jdk动态代理和cglib动态代理的区别
一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...
- java反射 java动态代理和cglib动态代理的区别
java反射 https://blog.csdn.net/f2764052703/article/details/89311013 java 动态代理 https://blog.csdn ...
- JDK和CGLIB生成动态代理类的区别
关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...
- 【4】JDK和CGLIB生成动态代理类的区别
当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代理:事先写好代理对象类,在 ...
- JDK和CGLIB生成动态代理类的区别(转)
关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...
- java的静态代理和动态代理(jdk、cglib)
一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...
- CGLib缺少jar出现 java.lang.ClassNotFoundException: org.objectweb.asm.Type
CGLib实现动态代理区别于JDK动态代理,不需要目标类实现任何接口,是通过生成代理类子类的方式,而且据说速度要快于JDK动态代理.所以我想要试验一下CGlib的动态代理,网上找了些例子,自己动手写了 ...
随机推荐
- Ajax Step By Step5
第五.[表单序列化] Ajax 用的最多的地方莫过于表单操作,而传统的表单操作是通过 submit 提交将数据传 输到服务器端.如果使用 Ajax 异步处理的话,我们需要将每个表单元素逐个获取才方能提 ...
- css3选择器总结
1.p[class^/$/*=td]所有p标签的前面带有td/后面带有td/所有带有td的类的三种样式. 2.div:first-child/last-child/nth-child()在父元素下的第 ...
- IE9下WebUploader上传图片跨域问题
作为前端,这一次踩到后台xml配置的坑. IE9下上传图片通过flash插件,一直发送http://192.168.0.8:8888/crossdomain.xml请求,状态码为404,原因是上传图片 ...
- SVM系列之拉格朗日对偶
在学习SVM(Support Vector Machine) 支持向量机时,对于线性可分的分类样本求出的分类函数为: 其中,分类超平面可以表示为:
- 在DW 5.5+PhoneGap+Jquery Mobile下搭建移动开发环境
移动设备应用开发有多难,只要学会HTML5+Javascript就可以.用Dreamweaver5.5+PhoneGap+Jquery Mobile搭建移动开发环境,轻轻松松开发你自己的应用.让你用普 ...
- 计算机网路之动态NAT配置
配置路由端口的ip地址与打开(省略) 配置路由协议 router eigrp 100 network 211.1.1.0(网络号) 0.0.0.255(通配子掩) network 192.168.1. ...
- linux下解压被分割的zip文件
形如被分割的一系列文件:linux.z01, linux.z02, linux.z03, linux.zip 直接右键解压是不行的. 首先合并文件:cat linux.* > linux_all ...
- Android Studio--Gradle基础(转)
原文链接:http://stormzhang.com/devtools/2014/12/18/android-studio-tutorial4/ 其实很早之前也写了一篇Gradle的基础博客,但是时间 ...
- ODBC,OLEDB,ADO,ADO.net,JDBC 理解
一 .ODBC 开放式数据库互联(Open Database connectivity), 93年微软推出的实现应用程序 和关系数据库直接 通讯的借口标准.只能用于关系数据库 . 注意事项 : 必须先 ...
- (转)RHEL/CentOS 6.x使用EPEL6与remi的yum源安装MySQL 5.5.x
PS:如果既想获得 RHEL 的高质量.高性能.高可靠性,又需要方便易用(关键是免费)的软件包更新功能,那么 Fedora Project 推出的 EPEL(Extra Packages for En ...