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: 

public Object createProxyObject(Object obj) {
    this.targetObject = obj;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(obj.getClass());
    enhancer.setCallback(this);
    Object proxyObj = enhancer.create();
    return proxyObj;// 返回代理对象,返回的对象其实就是一个封装了“实现类”的代理类,是实现类的实例。
}

  

JDK: 

public Object newProxy(Object targetObject) {// 将目标对象传入进行代理
    this.targetObject = targetObject;
    return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
            targetObject.getClass().getInterfaces(), this);// 返回代理对象
}  

在代码中可以看到,在生成代理类时,传递的是实现类所实现的接口 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"/>)。

参考

Spring AOP 实现原理与 CGLIB 应用

Spring AOP 实现原理

动态代理:JDK动态代理和CGLIB代理的区别

静态代理,动态代理,jdk代理,cglib代理的区别

时间: 2024-08-11 07:49:29

JDK和CGLIB生成动态代理类的区别的相关文章

用cglib生成的代理类取不到注解的问题

> 百度找了一下没找到,谷歌搜一下就出来了(会点英语就是好) 直接在注解上面加@Inherited @Inherited @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyAnnotation { } 原来CGLIB 返回的代理类是基于原来类的子类的,加上这个标志就可以令子类继承这个注解(唉,基础啊) 链接http://stackoverflow.com/questions/1706

基于jdk和cglib的动态代理

动态代理是Spring Aop的基础,分为基于JDK的动态代理和基于CGLIB的动态代理. 声明一个被代理的类: package com.maheng.proxy.jdk; public interface IUser { public void save(String name); } package com.maheng.proxy.jdk; public class User implements IUser{ @Override public void save(String name)

cgLib生成动态代理

package com.stono.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Enhancer

探索Mybatis之JDK动态代理:探究Proxy.newProxyInstance()生成的代理类解析

Mybatis的Mapper接口UserMapper 1 package com.safin.Mapper; 2 3 import com.safin.Pojo.User; 4 5 import java.util.List; 6 7 public interface UserMapper { 8 int insertUser(User user); 9 User getUser(Long id); 10 List<User> findUser(String userName); 11 } 我

JDK动态代理和Cglib的动态代理

最简单的是静态代理方法,即代理模式,这里就不多啰嗦了.. 重点说一下JDK的动态代理和Cglib的动态代理吧 先说JDK的,需要被代理的类需要有接口,否则无法实现 package proxy.dynamic; public interface IBook { void add(); } 实现接口的类如下 package proxy.dynamic; public class Book implements IBook { @Override public void add() { System.

模拟JDK动态代理类的实现

问题: 要理解动态代理及其优点,我们先从这样一个问题入手,比如现在我们有UserDao这样一个接口,里面有addUser()方法,同时有一个UserDaoImpl类实现了该接口,具体实现了addUser()方法,现在我要实现在该方法前后记录日志的功能,有什么解决办法呢? 在源代码上直接修改.第一反应肯定是直接在源码上添加该功能,但是如果我的需求变成在所有的DaoImpl包里的类的所有的方法都添加记录日志的功能,那再去每一个都添加,工作量大,代码的重用率也不高,而且有的时候你可能没有源代码,所以该

查看JDK自动生成的代理类源码

直接运行下面的代码,在D盘就可以看到生成的源码类$GameProxy.class import sun.misc.ProxyGenerator; import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 查看JDK自动生

Java中的静态代理、通用动态代理类以及原理剖析

代理模式和静态代理 在开发中,代理模式是常用的模式之一,一般来说我们使用的代理模式基本上都是静态代理,实现模式大致如下 : 我们以网络代理为例,简单演示一下静态代理的实现 : // 网络接口 interface Network { public void surfTheInternet(); public void gotoFacebook(); } // 普通网络 class CommonNetwork implements Network { @Override public void su

cglib的动态代理

前言 jdk中的动态代理通过反射类Proxy和InvocationHandler回调接口实现,要求委托类必须实现一个接口,只能对该类接口中定义的方法实现代理,这在实际编程中有一定的局限性. cglib实现 使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码,下面通过一个例子看看使用CGLib如何实现动态代理.1.定义业务逻辑 public class UserServiceImpl { publ