JDK 代理和 CGLib 有什么区别?
JDK 代理和 CGLib 有什么区别?动态代理是一种机制,程序通过该机制在运行时动态生成代理对象并调用代理方法。动态代理主要有两种实现机制,一种是基于反射动态代理的JDK,另一种是基于ASM动态代理机制的CGLib实现。现在让我们谈谈两种实现之间的区别以及如何实现它们
JDK 代理和 CGLib 之间的区别
[*]JDK动态代理采用反射机制实现,而CGLib基于ASM机制实现,性能不同
[*]JDK动态代理是Java语言的内置功能,它不断更新和升级,没有任何维护问题。CGLib是基于第三方工具实现的,两种实现方式往往不同。
[*]JDK动态代理必须通过接口实现,调用起来相对简单,而CGLib不需要接口,调用起来相对复杂。
JDKProxy 动态代理实现
JDK 动态代理通过反射类代理和 InvocationHandler 接口实现。由于JDK中的所有动态代理类都必须实现一个接口,也就是说,动态代理类必须实现在动态代理接口中定义的方法,这会导致反射效率低。
[*]代码实现
public class JdkTokProxyT implements InvocationHandler {
private T target;
public JdkTikTokProxy(T target) {
this.target = target;
}
public static T T getProxy(T t) {
Object o = Proxy.newProxyInstance(t.getClass().getClassLoader()
, t.getClass().getInterfaces()
, new JdkTikTokProxy(t));
return (T) o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// reflection executes
System.out.println("Methods that actually execute the proxied object");
Object invoke = method.invoke(target, args);
System.out.println("Return value:" + invoke);
return null; }}Copy the code从上面的代码中可以看出,JDK 动态代理使用 Proxy 类中的 newProxyInstance 方法创建一个动态代理对象。
newProxyInstance 方法主要采用
参数描述类加载器加载器当前用于装入代理对象的字节码的类装入器。使用与代理对象相同的类装入器。固定写入类?[] 接口当前由可执行对象实现的所有接口的字节码数组,用于使可执行对象和可执行对象具有相同的方法。固定写入InvocationHandler h目前,当代理对象执行目标方法时,我们可以使用 H 定义拦截增强方法,即我们编写如何代理。我们通常为此接口编写一个实现类,通常是匿名内部类,但这不是必需的。invoke 方法的主要功能是通过执行支撑对象的任何接口方法传递,或者更确切地说,一个侦听方法,即调用 main 方法参数
参数描述代理对代理对象的引用方法当前执行的方法参数当前执行方法所需的参数返回具有与代理对象相同的返回值invoke() 方法是 JDK 代理的调用接口,它使用 Invocation Invo Invocation。
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}这是因为在动态代理中有一个重要作用,即代理,它用于集中管理prostedobject。显然,InvoHandler 就是这个代理,invoke() 方法是触发代理的执行方法。我们通过实现调用接口来获得动态代理功能。
实施附加
如果使用由 CGLib 实现的动态代理,则不需要代理类来实现接口,这提高了性能,因为 CGLib 使用下面的 ASM 框架,该框架通过字节码技术生成代理类。
动态生成一个支持子类,该子类覆盖支持类的所有非最终方法。方法拦截拦截子类中对父方法的所有调用,将横切逻辑编织到子类中,这比Java的反射JDK动态代理更快.
Cglib 是一个功能强大、高性能的代码生成包,在许多 AOP 框架中广泛用于提供方法拦截
[*]代码实现如下public class CglibProxy {
public static T T createProxy(T t) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(t.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Cglib is on.");
Object invoke = proxy.invokeSuper(obj, args);
returninvoke; }}); Object o = enhancer.create();return(T) o; }}Copy the code从上面的代码中可以看出,CGLib 是基于子类实现的动态代理,并使用增强器类中的 create 方法创建代理对象。因此,代理类不能由关键字 final 修改。如果由 final 修改,则在使用增强器设置父类时将报告错误,并且无法构建动态代理。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]