字节码增强和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小时内删除。
发表评论