⑴ cglib动态代理和jdk动态代理的区别与应用
jdk动态代理:需要有顶层接口才能使用,但是在只有顶层接口的时候也可以使用,常见是mybatis的mapper文件是代理.
cglib动态代理:可以直接代理类,使用字节码技术,不能对 final类进行继承。使用了动态生成字节码技术。
⑵ spring cglib代理耗时太久
由于整个Spring加载和实例化bean的过程原因导致。
Spring的bean的scope设置成prototype,就是每次都要创建一个实例,可以看一下Spring的源码,创建一个Spring实例是很复杂的一个过程,CGlib代理只是其中的一步,底层也是通过反射完成的,耗时的关键不在CGlib代理,而是在整个Spring加载和实例化bean的过程。
CGlib是属于动态管理,动态代理是在不改变原有代码的情况下上进行对象功能增强,使用代理对象代替原来的对象完成功能,进而达到拓展功能的目的。
⑶ java动态代理和cglib动态代理的区别
1、Jdk动态代理实例:JDK动态代理只能代理实现了接口的类,其他普通类不能实现。代理类会在newProxyInstance方法中生成
2、cglib动态代理:cglib是针对类实现代理的,为代理的类生成一个子类,覆盖方法实现增强,因为采用的是继承所以不能代理final修饰的类。需要cglib和asm两个jar包
⑷ jdk动态代理和cglib的区别
关于动态代理和静态代理
当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。
按照代理对象的创建时期不同,可以分为两种:
静态代理:事先写好代理对象类,在程序发布前就已经存在了;
动态代理:应用程序发布后,通过动态创建代理对象。
静态代理其实就是一个典型的代理模式实现,在代理类中包装一个被代理对象,然后影响被代理对象的行为,比较简单,代码就不放了。
其中动态代理又可分为:JDK动态代理和CGLIB代理。
1.JDK动态代理
此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。
代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。
JDK动态代理只能针对实现了接口的类生成代理。
2.CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,
主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。
JDK动态代理和CGLIB代理生成的区别
JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。
PS:final 所修饰的数据具有“终态”的特征,表示“最终的”意思:
final 修饰的类不能被继承。
final 修饰的方法不能被子类重写。
final 修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。
final 修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有 一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用。
final 修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。
参考代码
CGLIB:
12345678JDK:
12345在代码中可以看到,在生成代理类时,传递的是实现类所实现的接口 targetObject.getClass().getInterfaces(),所以JDK只能对于接口进行做代理。如果换成类的话,则会抛java.lang.ClassCastException异常。
在Spring的源码中,可以看到很多生成代理类的代码。
动态代理的应用
AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。
实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。
默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。
如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。
⑸ CGLIB什么意思
cglib是一个开源项目,它是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO字节码的动态生成。
cglib项目主页如下:
http://cglib.sourceforge.net/
⑹ CGLIB是什么
写了一半。网页一黑。。东西就都没了。。。强烈建议OSC的博客有个自动保存功能!!!! CGLIB是一个反射的包,和JDK的反射不同,cglib反射的对象可以不用实现接口。cglib是就ASM的,引用一个图,很清晰。 spring的AOP的实现一种是使用原生的jdk的反射,一种就是使用cglib引用一下: CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 不多说了,直接上helloword的例子。 使用的时候报了如下错误: Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type 忘引入asm的包了,引入,报如下错误: java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method visit.(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V helloworkpublic class HelloWord { public void sayHello(){ System.out.println(helloWorld);}}写一个代理类实现MethodIntercepter接口的intercept的方法,其中用proxy调用invokesuper的方法 public class CglibProxy implements MethodInterceptor{@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println(before); proxy.invokeSuper(obj, args); System.out.println(afert); return null;}}接下来就是调用方法了,启用enhancer调用setsuperclass为要代理的类,setcallback为调用的代理类,然后用enhancer调用create重新生成一个要代理的类就ok了。 public class TestCglib { public static void main(String[] args) { //HelloWord helloWord=new HelloWord(); //helloWord.sayHello(); Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(HelloWord.class); enhancer.setCallback(new CglibProxy()); HelloWord helloWord=(HelloWord) enhancer.create(); helloWord.sayHello();}}输出结果如下:beforehelloWorldafert引用一个博客,里面的例子也很好。特别是增加了methodfilter,是的cglib的功能更强大了 总结一下,cglib封装了asm可以对类进行动态代理。
⑺ Spring事务管理是动态代理还是静态代理 CGLB支持动态代理吗因为我听老师说CGLB是静态代理
JDK动态代理是运行时生成代理对象,其特点是有一个原对象实例,有一个代理对象实例,代理对象内部持有原对象的引用。
而CGLIB代理是运行时先编译一个新的类,直接在字节码的层级上把代码添加进原方法中,运行时只有一个动态生成的新类的实例,不存在源对象实例。
Spring同时支持这两种代理方式,但是因为JDK动态代理只能进行接口的代理,如果你要代理的对象没有实现接口,那就不能采取JDK动态代理,而会采用CGLIB代理。
一般情况下优先采用JDK动态代理,虽然其效率似乎比不上CGLIB代理,但是其对象用完之后可以正常释放。但是CGLIB代理每代理一个对象,都会产生一个新类。而类一旦载入JVM,按照大部分JVM的机制,这些新类占用的内存不会释放。J2EE程序一般运行时间都很长,内存上会有一些压力。
⑻ Spring的两种代理JDK和CGLIB的区别
原理区别:x0dx0ajava动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。x0dx0a1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP x0dx0a2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP x0dx0a3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
⑼ 静态代理,JDK动态代理和CGLib动态代理之前的区别
1、静态代理:静态代理中的代理类,需要我们自己写
JDK动态代理类实现了InvocationHandler接口。在重写的invoke方法中可以看出,JDK动态代理的基础是反射(method.invoke(对象,参数)),还好反射看的比较多,到现在还记得。在这里需要提到的是Proxy.newProxyInstance(),这个方法。字面上的意思是 新建一个代理类的实例,这一点就和静态代理不同了。里面的参数有三个 类加载器、所有的接口,得到InvocationHandler接口的子类实例。这就是JDK动态代理,该代理有以下几种特点:
1、Interface:对于JDK Proxy,业务类是需要一个Interface的,这是一个缺陷;
2、Proxy:Proxy类是动态产生的,这个类在调用Proxy.newProxyInstance()方法之后,产生一个Proxy类的实力。实际上,这个Proxy类也是存在的,不仅仅是类的实例,这个Proxy类可以保存在硬盘上;
3、Method:对于业务委托类的每个方法,现在Proxy类里面都不用静态显示出来
4、InvocationHandler:这个类在业务委托类执行时,会先调用invoke方法。invoke方法在执行想要的代理操作,可以实现对业务方法的再包装。
以上就是JDK动态代理
3、CGLib动态代理:上面的JDK Proxy只能代理实现了接口的类,而不能实现接口的类就不能实现JDK代理。这时候就需要CGLib动态代理类
这里需要注意的是实现MethodIntercetor接口,必须导入cglib-nodep-2.1_3.jar这个包。CGLib是针对类来实现代理的,他的原理是对指定的目标生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
⑽ Spring中默认使用jdk代理还是cglib代理
jdk代理(基于接口):如果目标实现了接口,那么默认使用jdk代理。
cglib代理(基于类):如果目标没有实现接口,那么默认使用cglib代理。
spring中的配置proxy-target-class 属性:
proxy-target-class:true 设置基于类的代理,cglib代理。
proxy-target-class:false 设置基于接口的代理,jdk代理,但如果目标没有实现接口,使用cglib代理。
如果当前类方法上有 @Cacheable @Transactional 注解或者 被aop加强的话 生成的是代理对象,具体哪种代理看上面的区分,如果没有上述条件的话那么创建的对象是 原始对象。