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的区别的更多相关文章

  1. JDK和CGLIB动态代理原理区别

    JDK和CGLIB动态代理原理区别 https://blog.csdn.net/yhl_jxy/article/details/80635012 2018年06月09日 18:34:17 阅读数:65 ...

  2. spring源码学习【准备】之jdk动态代理和cglib动态代理的区别和性能

    一:区别:---->JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了.--->JDK的动态代理机制只能代理实现了接口的类,而不能 ...

  3. jdk动态代理和cglib动态代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  4. java反射 java动态代理和cglib动态代理的区别

    java反射      https://blog.csdn.net/f2764052703/article/details/89311013 java 动态代理   https://blog.csdn ...

  5. JDK和CGLIB生成动态代理类的区别

     关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...

  6. 【4】JDK和CGLIB生成动态代理类的区别

    当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代理:事先写好代理对象类,在 ...

  7. JDK和CGLIB生成动态代理类的区别(转)

     关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...

  8. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

  9. CGLib缺少jar出现 java.lang.ClassNotFoundException: org.objectweb.asm.Type

    CGLib实现动态代理区别于JDK动态代理,不需要目标类实现任何接口,是通过生成代理类子类的方式,而且据说速度要快于JDK动态代理.所以我想要试验一下CGlib的动态代理,网上找了些例子,自己动手写了 ...

随机推荐

  1. PBX220 测评一

    //纯粹个人看法,可能包含非常不恰当的主观看法,敬请见谅. 本次测试的是易用科技Speedytel 新出的产品 PBX-220.      测试环境为:华硕EeePC(IE7).Eyebeam. 先来 ...

  2. 《UML大战需求分析》阅读笔记4

    流程分析利器之二,状态机图. 状态机图也可以叫状态图,也是用来分析流程的,之前的活动图的主体是事件的行为,而状态机图主要描述的是事件的状态. 开始:实心圆点: 结束:点加环:(与活动图一样) 状态:圆 ...

  3. 堆排序Heap sort

    堆排序有点小复杂,分成三块 第一块,什么是堆,什么是最大堆 第二块,怎么将堆调整为最大堆,这部分是重点 第三块,堆排序介绍 第一块,什么是堆,什么是最大堆 什么是堆 这里的堆(二叉堆),指得不是堆栈的 ...

  4. 安卓奇葩问题之SQLite条件查找不到数据

    今天真是日了狗了. 先说需求:要做一个累死支付宝首页的可自定义的栏目.栏目是动态从后台获取的,所以就会有一个本地数据和后台数据的同步问题.为了方便对本地数据的增删改查,首先想到SQLite. 然后就写 ...

  5. 阿里云安装JDK1.7

    本人阿里云选择的是CentOS 7.0系统,本系列文件将全部基于此环境. 1.下载JDK,版本为jdk-7u79-linux-x64.tar.gz   2.使用FileZilla上传至/softwar ...

  6. 算法入门笔记------------Day2

    1.开灯问题 有n盏灯,编号为1-n,第一个人把所有灯打开,第二个按下所有编号为2的倍数的开关(这些灯都被关掉),第三个人按下所有编号为3的倍数的开关,依次类推,一共有k个人,问最后有哪些灯开着?输入 ...

  7. Windows Phone 8.1 新特性 - 控件之FlipView

    本篇为大家介绍 Windows Phone 8.1 中新增的 FlipView 控件,它的中文名字叫做:翻转视图. 虽然听起来有点拗口,但是它的用途大家一定不会陌生.在 Windows Phone 8 ...

  8. javascript练习-扑克牌

    下面用枚举类型来实现一副扑克牌的类: //定义一个玩牌的类 function Card(suit,rank){ function inherit(p){ if(p==null) throw TypeE ...

  9. 使用CSS中的meta实现web定时刷新或跳转的方法

    这篇文章主要介绍了使用CSS中的meta实现web定时刷新或跳转的方法,比使用JavaScript脚本实现起来更加简单一些,需要的朋友可以参考下 meta源信息功能之页面定时跳转与刷新 几乎所有的网页 ...

  10. 使用ajax预加载图片

    使用Ajax 上面所给出的方法似乎不够酷,那现在来看一个使用Ajax实现图片预加载的方法.该方法利用DOM,不仅仅预加载图片,还会预加载CSS.JavaScript等相关的东西.使用Ajax,比直接使 ...