可信赖的龙岗网站建设,网页设计师联盟网站,石碣东莞网站建设,做一个商务平台网站的费用Cglib和jdk动态代理的区别
动态代理解决了方法之间的紧耦合#xff0c;
IOC解决了类与类之间的紧耦合#xff01;
Cglib和jdk动态代理的区别#xff1f;
1、Jdk动态代理#xff1a;利用拦截器#xff08;必须实现InvocationHandler#xff09;加上反射机制生成一个代…Cglib和jdk动态代理的区别
动态代理解决了方法之间的紧耦合
IOC解决了类与类之间的紧耦合
Cglib和jdk动态代理的区别
1、Jdk动态代理利用拦截器必须实现InvocationHandler加上反射机制生成一个代理接口的匿名类在调用具体方法前调用InvokeHandler来处理
2、 Cglib动态代理利用ASM框架对代理对象类生成的class文件加载进来通过修改其字节码生成子类来处理
什么时候用cglib什么时候用jdk动态代理
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口可以强制使用cglib
3、如果目标对象没有实现接口必须采用cglib库Spring会自动在JDK动态代理和cglib之间转换
JDK动态代理和cglib字节码生成的区别
1、JDK动态代理只能对实现了接口的类生成代理而不能针对类
2、Cglib是针对类实现代理主要是对指定的类生成一个子类覆盖其中的方法并覆盖其中方法的增强但是因为采用的是继承所以该类或方法最好不要生成final对于final类或方法是无法继承的
Cglib比JDK快
1、cglib底层是ASM字节码生成框架但是字节码技术生成代理类在JDL1.6之前比使用java反射的效率要高
2、在jdk6之后逐步对JDK动态代理进行了优化在调用次数比较少时效率高于cglib代理效率
3、只有在大量调用的时候cglib的效率高但是在1.8的时候JDK的效率已高于cglib
4、Cglib不能对声明final的方法进行代理因为cglib是动态生成代理对象final关键字修饰的类不可变只能被引用不能被修改
Spring如何选择是用JDK还是cglib
1、当bean实现接口时会用JDK代理模式
2、当bean没有实现接口用cglib实现
3、可以强制使用cglib在spring配置中加入aop:aspectj-autoproxy proxyt-target-class”true”/
一. Cglib原理
动态生成一个要代理的子类子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截技术拦截所有的父类方法的调用顺势织入横切逻辑它比Java反射的jdk动态代理要快
Cglib是一个强大的、高性能的代码生成包它被广泛应用在许多AOP框架中为他们提供方法的拦截
最底层的是字节码Bytecode,字节码是java为了保证依次运行可以跨平台使用的一种虚拟指令格式
在字节码文件之上的是ASM只是一种直接操作字节码的框架应用ASM需要对Java字节码、class结构比较熟悉
位于ASM上面的是Cglibgroovy、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的第三方库提供的动态代理
/*** 动态代理* 特点字节码随用随创建随用随加载* 作用不修改源码的基础上对方法增强* 分类* 基于接口的动态代理* 基于子类的动态代理* 基于子类的动态代理* 涉及的类Enhancer* 提供者第三方cglib库* 如何创建代理对象* 使用Enhancer类中的create方法* 创建代理对象的要求* 被代理类不能是最终类* newProxyInstance方法的参数在使用代理时需要转换成指定的对象* ClassLoader:类加载器* 他是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法* Callback用于提供增强的代码* 他是让我们写如何代理。我们一般写一个该接口的实现类通常情况加都是匿名内部类但不是必须的。* 此接口的实现类是谁用谁写。* 我们一般写的都是该接口的子接口实现类MethodInterceptor*/
com.dynamic.cglib.Producer cglibProducer (com.dynamic.cglib.Producer) Enhancer.create(com.dynamic.cglib.Producer.class,new MethodInterceptor() {/*** 执行被代理对象的任何方法都会经过该方法* param obj* param method* param args* 以上三个参数和基于接口的动态代理中invoke方法的参数是一样的* param proxy当前执行方法的代理对象* return* throws Throwable*/Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {Object returnValuenull;Float money(Float)args[0];if(saleProduct.equals(method.getName())){returnValue method.invoke(producer,money*0.8f);}return returnValue;}}
);
cglibProducer.saleProduct(100.0f);JDK本身提供的动态代理实现
/*** 动态代理* 特点字节码随用随创建随用随加载* 作用不修改源码的基础上对方法增强* 分类* 基于接口的动态代理* 基于子类的动态代理* 基于接口的动态代理* 涉及的类proxy* 提供者Jdk官方* 如何创建代理对象* 使用Proxy类中的newProxyInstance方法* 创建代理对象的要求* 被代理类最少实现一个接口如果没有则不能使用* newProxyInstance方法的参数在使用代理时需要转换成指定的对象* ClassLoader:类加载器* 他是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法* Class[]字节码数组* 它是用于让代理对象和被代理对象有相同方法。固定写法* InvocationHandler用于提供增强的代码* 他是让我们写如何代理。我们一般写一个该接口的实现类通常情况加都是匿名内部类但不是必须的。* 此接口的实现类是谁用谁写。*/IProducer proxyProducer (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),producer.getClass().getInterfaces(),new InvocationHandler() {/*** 作用执行被代理对象的任何接口方法都会经过该方法* param proxy 代理对象的引用* param method 当前执行的方法* param args 当前执行方法所需的参数* return 和被代理对象有相同返回值* throws Throwable*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 提供增强的代码
// 1、获取方法执行的参数Object returnValuenull;Float money(Float)args[0];if(saleProduct.equals(method.getName())){returnValue method.invoke(producer,money*0.8f);}return returnValue;}});JDK和Cglib的区别
CglibJDK是否提供子类代理是否是否提供接口代理是可强制是区别必须依赖于CGLib的类库但是它需要类来实现任何接口代理的是指定的类生成一个子类覆盖其中的方法实现InvocationHandler 使用Proxy.newProxyInstance产生代理对象 被代理的对象必须要实现接口