字节码增强和springAOP原理
反射和ASM区别
反射是读取持久堆上存储的类信息。⽽ ASM 是直接处理 .class 字节码的⼩⼯具(⼯具虽⼩,但是功能⾮常强⼤!)
反射只能读取类信息,⽽ ASM 除了读还能写。
反射读取类信息时需要进⾏类加载处理,⽽ ASM 则不需要将类加载到内存中。
反射相对于 ASM 来说使⽤⽅便,想直接操纵 ASM 的话需要有 JVM 指令基础。
Cglib框架动态代理
JDK动态代理 和 Cglib框架动态代理
Spring AOP 代理实现有两种: JDK动态代理
JDK中的动态代理:
⼀、⾸先说⼀下JDK中的动态代理
JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接⼝实现的,
但是,JDK中所要进⾏动态代理的类必须要实现⼀个接⼝,也就是说只能对该类所实现接⼝中定义的⽅法进⾏代理,这在实际编程中具有⼀定的局限性,⽽且使⽤反射的效率也并不是很⾼。
CGLib实现:
⼆、使⽤CGLib实现
使⽤CGLib实现动态代理,完全不受代理类必须实现接⼝的限制,⽽且CGLib底层采⽤ASM字节码⽣成框架,使⽤字节码技术⽣成代理类,⽐使⽤Java反射效率要⾼。唯⼀需要注意的是,CGLib不能对声明
为final的⽅法进⾏代理,因为CGLib原理是动态⽣成被代理类的⼦类。
JDK API 内置 ---- 通过 Proxy类,为⽬标对象创建代理 (必须⾯向接⼝代理 )
缺点: 使⽤Jdk动态代理,必须要求target⽬标对象,实现接⼝ ,如果没有接⼝,不能使⽤Jdk动态代理
Cglib 动态代理
CGLIB(Code Generation Library)是⼀个开源项⽬!是⼀个强⼤的,⾼性能,⾼质量的Code⽣成类库,它可以在运⾏期扩展Java类与实现Java接⼝。
⼀、什么是CGLIB?
CGLIB是⼀个功能强⼤,⾼性能的代码⽣成包。它为没有实现接⼝的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使⽤Java的动态代理创建代理,但当要代理的类没有实现接⼝或者为了更好的性能,CGLIB是⼀个好的选择。
⼆、CGLIB原理
CGLIB原理:动态⽣成⼀个要代理类的⼦类,⼦类重写要代理的类的所有不是final的⽅法。在⼦类中采
⽤⽅法拦截的技术拦截所有⽗类⽅法的调⽤,顺势织⼊横切逻辑。它⽐使⽤java反射的JDK动态代理要快。
CGLIB底层:使⽤字节码处理框架ASM,来转换字节码并⽣成新的类。不⿎励直接使⽤ASM,因为它要求你必须对JVM内部结构包括class⽂件的格式和指令集都很熟悉。
CGLIB缺点
CGLIB缺点:对于final⽅法,⽆法进⾏代理。Cglib 不但可以对接⼝进⾏代理,也可以对⽬标类对象,实现代理 (解决了 Jdk 只能对接⼝代理问题 )在spring3.2版本 core包中内置cglib 类  1.
public  class  JdkProxyFactory implements  InvocationHandler {  2.
// 被代理对象  3.
private  Object target;  4.
5.
// 在构造⽅法对象时,传⼊被代理对象  6.
public  JdkProxyFactory(Object target) {  7.
this .target = target;  8.
}  9.
10.
// 创建代理  11.
public  Object createProxy() {  12.
// 三个参数: 类加载器、 实现接⼝、 invocationhandler  13.
return  Class().getClassLoader(), Class().getInterfaces(), this );  14.
}  15.
16.
@Override  17.
public  Object invoke(Object proxy, Method method, Object[] args) throws  Throwable {  18.
System.out.println("记录⽇志");  19.spring aop应用场景
// 调⽤⽬标真实⽅法  20.
// target 被代理对象, args ⽅法参数 , method 被调⽤的⽅法  21.
return  method.invoke(target, args);  22.
}  23. }
Cglib 创建代理思想: 对⽬标类创建⼦类对象
设置 superClass 对哪个类创建⼦类 (类似 JDK代理 接⼝)
设置 callback 实现增强代码 (类似 JDK代理 InvocationHandler )
在cglib的callback函数中,要执⾏被代理对象的⽅法
method.invoke(target, args); 等价于 methodProxy.invokeSuper(proxy, args); 优先对接⼝代理 (使⽤JDK代理),如果⽬标没有接⼝,才会使⽤cglib代理 !

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。