And the difference between Cglib jdk dynamic proxy

Dynamic agent tight coupling between the solution method,
IOC to solve the tight coupling between class and class!
 
Cglib and jdk dynamic proxy difference?
1, Jdk dynamic agent: using interceptors (must implement of InvocationHandler) plus reflection generates a proxy class interfaces anonymous call InvokeHandler before calling a specific method to process
2, Cglib dynamic proxy: using ASM frame, a proxy object class generated by the class file loaded in, processed by subclassing modifying bytecode
When using jdk dynamic proxy use when cglib?
1, the target object interfaces generated by default JDK dynamic proxies
2, if the target object using the interface, you can force the use of cglib
3, if the target object does not implement the interface must be used cglib library, Spring will automatically switch between JDK dynamic proxies and cglib
JDK dynamic proxy and bytecode generation cglib difference?
1, JDK dynamic proxy can only generate a proxy class that implements the interface, not for class
2, Cglib is a proxy for the class implements, mainly to generate a subclass of the specified class, which covers the method and coverage enhancement which method, but because the use of inheritance, class or method is best not to generate final, for the final class or method can not be inherited
Cglib faster than JDK?
1, cglib bottom frame is generated ASM bytecode, but technology to generate proxy class bytecode, efficiency than prior JDL1.6 higher reflection java
2, after jdk6 gradually to JDK dynamic proxies are optimized, more efficient in the number of calls came from above cglib agent efficiency
3, invoked only when a large number of high-efficiency cglib, but in JDK 1.8 when efficiency is higher than cglib
4, Cglib proxy method can not be declared final, because cglib is dynamically generated proxy object, the keyword final modification of an immutable class can only be referenced can not be modified
How to choose Spring is using JDK or cglib?
1, when the bean implements the interface, will use JDK proxy mode
2, when the bean does not implement interface, with cglib
3、可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
一. Cglib原理
动态生成一个要代理的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用,顺势织入横切逻辑,它比Java反射的jdk动态代理要快
Cglib是一个强大的、高性能的代码生成包,它被广泛应用在许多AOP框架中,为他们提供方法的拦截
 
最底层的是字节码Bytecode,字节码是java为了保证依次运行,可以跨平台使用的一种虚拟指令格式
在字节码文件之上的是ASM,只是一种直接操作字节码的框架,应用ASM需要对Java字节码、class结构比较熟悉
位于ASM上面的是Cglib,groovy、beanshell,后来那个种并不是Java体系中的内容是脚本语言,他们通过ASM框架生成字节码变相执行Java代码,在JVM中程序执行不一定非要写java代码,只要能生成java字节码,jvm并不关系字节码的来源
位于cglib、groovy、beanshell之上的就是hibernate和spring AOP
最上面的是applications,既具体应用,一般是一个web项目或者本地跑一个程序、
使用cglib代码对类做代理?
使用cglib定义不同的拦截策略?
构造函数不拦截方法
用MethodInterceptor和Enhancer实现一个动态代理
Jdk中的动态代理
JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是JDK中所有要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中有一定的局限性,而且使用反射的效率也不高
Cglib实现
使用cglib是实现动态代理,不受代理类必须实现接口的限制,因为cglib底层是用ASM框架,使用字节码技术生成代理类,你使用Java反射的效率要高,cglib不能对声明final的方法进行代理,因为cglib原理是动态生成被代理类的子类
 
Cglib的第三方库提供的动态代理
 1 /**
 2  * 动态代理:
 3  *  特点:字节码随用随创建,随用随加载
 4  *  作用:不修改源码的基础上对方法增强
 5  *  分类:
 6  *      基于接口的动态代理
 7  *      基于子类的动态代理
 8  *  基于子类的动态代理:
 9  *      涉及的类:Enhancer
10  *      提供者:第三方cglib库
11  *  如何创建代理对象:
12  *      使用Enhancer类中的create方法
13  *  创建代理对象的要求:
14  *      被代理类不能是最终类
15  *  newProxyInstance方法的参数:在使用代理时需要转换成指定的对象
16  *      ClassLoader:类加载器
17  *          他是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法
18  *      Callback:用于提供增强的代码
19  *          他是让我们写如何代理。我们一般写一个该接口的实现类,通常情况加都是匿名内部类,但不是必须的。
20  *          此接口的实现类,是谁用谁写。
21  *          我们一般写的都是该接口的子接口实现类,MethodInterceptor
22  */
23 com.dynamic.cglib.Producer cglibProducer= (com.dynamic.cglib.Producer) Enhancer.create(
24         com.dynamic.cglib.Producer.class,
25         new MethodInterceptor() {
26             /**
27              *  执行被代理对象的任何方法都会经过该方法
28              * @param obj
29              * @param method
30              * @param args
31              *      以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
32              * @param proxy:当前执行方法的代理对象
33              * @return
34              * @throws Throwable
35              */
36             @Override
37             public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
38                 Object returnValue=null;
39                 Float money=(Float)args[0];
40                 if("saleProduct".equals(method.getName())){
41                    returnValue= method.invoke(producer,money*0.8f);
42                 }
43                 return returnValue;
44             }
45         }
46 );
47 cglibProducer.saleProduct(100.0f);

 

JDK本身提供的动态代理实现
 1 /**
 2          * 动态代理:
 3          *  特点:字节码随用随创建,随用随加载
 4          *  作用:不修改源码的基础上对方法增强
 5          *  分类:
 6          *      基于接口的动态代理
 7          *      基于子类的动态代理
 8          *  基于接口的动态代理:
 9          *      涉及的类:proxy
10          *      提供者:Jdk官方
11          *  如何创建代理对象:
12          *      使用Proxy类中的newProxyInstance方法
13          *  创建代理对象的要求:
14          *      被代理类最少实现一个接口,如果没有则不能使用
15          *  newProxyInstance方法的参数:在使用代理时需要转换成指定的对象
16          *      ClassLoader:类加载器
17          *          他是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法
18          *      Class[]:字节码数组
19          *          它是用于让代理对象和被代理对象有相同方法。固定写法
20          *      InvocationHandler:用于提供增强的代码
21          *          他是让我们写如何代理。我们一般写一个该接口的实现类,通常情况加都是匿名内部类,但不是必须的。
22          *          此接口的实现类,是谁用谁写。
23          */
24        IProducer proxyProducer=  (IProducer) Proxy.newProxyInstance(
25                 producer.getClass().getClassLoader(),
26                 producer.getClass().getInterfaces(),
27 
28                new InvocationHandler() {
29                    /**
30                     * 作用:执行被代理对象的任何接口方法都会经过该方法
31                     * @param proxy  代理对象的引用
32                     * @param method 当前执行的方法
33                     * @param args   当前执行方法所需的参数
34                     * @return       和被代理对象有相同返回值
35                     * @throws Throwable
36                     */
37                     @Override
38                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
39 //                        提供增强的代码
40 //                        1、获取方法执行的参数
41                         Object returnValue=null;
42                         Float money=(Float)args[0];
43                         if("saleProduct".equals(method.getName())){
44                            returnValue= method.invoke(producer,money*0.8f);
45                         }
46                         return returnValue;
47                     }
48                 }
49         );

 

 
JDK和Cglib的区别:
 
Cglib
JDK
是否提供子类代理
是否提供接口代理
是(可强制)
区别
必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法
实现InvocationHandler 
使用Proxy.newProxyInstance产生代理对象
被代理的对象必须要实现接口

Guess you like

Origin www.cnblogs.com/sandaman2019/p/12636727.html