0


【spring】jdk动态代理和cglib动态代理的区别

目录

一、说明

  • 1.spring aop中的动态代理主要有两种方式,jdk动态代理和cglib动态代理
  • 2.从实现接口、继承父类的角度讨论区别
  • 3.从限制角度讨论区别
  • 4.从性能上讨论区别

二、区别

  • 1.jdk动态代理只提供接口类的代理,如果目标类不是接口,只能用cglib代理
  • 2.jdk动态代理会在运行时为目标类生成一个动态代理类$proxy*.class。cglib的底层是通过ASM在运行时动态生成目标类的子类,还会有其它类
    1. jdk动态代理的代理类实现了目标类实现的接口,并且会实现接口所有方法来代码增强。cglib动态代理会重写父类所有的方法来代码增强
  • 4.jdk动态代理调用时先去调用处理类进行增强,再通过反射的方式调用目标类的方法。cglib动态代理调用时先通过代理类进行增强,再直接调用父类对应的方法进行调用目标方法
  • 5.jdk动态代理如果目标类未实现接口则无法代理,cglib是通过继承的方式来动态代理,若目标类被final关键字修饰,则无法使用cglib做动态代理
  • 6.性能上:在老版的jdk,jdk代理生成的类速度快,通过反射调用慢,cglib是jdk代理速度的10倍左右,jdk在版本每次升级都会有很大的性能提升,cglib停滞不前,jdk7 8的动态代理性能在1万次实验中比cglib要快20%左右

三、代码示例

3.1 静态代理
  1. package com.proxy.staticproxy;
  2. public interface SellTicket {
  3. void sell();
  4. }
  1. package com.proxy.staticproxy;
  2. public class TrainStation implements SellTicket{
  3. @Override
  4. public void sell() {
  5. System.out.println("火车站售票");
  6. }
  7. }
  1. package com.proxy.staticproxy;
  2. public class ProxyPoint implements SellTicket{
  3. //声明火车类对象
  4. private TrainStation trainStation = new TrainStation();
  5. @Override
  6. public void sell() {
  7. System.out.println("代售点收取服务费");
  8. trainStation.sell();
  9. }
  10. public static void main(String[] args) {
  11. ProxyPoint proxyPoint = new ProxyPoint();
  12. proxyPoint.sell();
  13. }
  14. }
3.2 jdk动态代理
  1. package com.proxy.jdkproxy;
  2. import com.proxy.staticproxy.SellTicket;
  3. import com.proxy.staticproxy.TrainStation;
  4. import java.lang.reflect.InvocationHandler;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.Proxy;
  7. public class ProxyFactory {
  8. private TrainStation trainStation = new TrainStation();
  9. public SellTicket getProxyPoint() {
  10. /**
  11. * ClassLoader loader: 类加载器,用于加载代理类。可以通过目标对象获取类加载器
  12. * Class<?>[] interfaces: 代理类实现的接口的字节码对象
  13. * InvocationHandler h: 代理对象的调用处理程序
  14. */
  15. SellTicket sellTicket = (SellTicket)Proxy.newProxyInstance(trainStation.getClass().getClassLoader(), trainStation.getClass().getInterfaces(),
  16. new InvocationHandler() {
  17. /**
  18. * @param proxy 代理对象 proxyObject是同一个对象,在invoke方法中基本不用
  19. * @param method 对接口中的方法进行封装的method对象
  20. * @param args 调用方法的实际参数
  21. * @return 方法返回值
  22. * @throws Throwable
  23. */
  24. @Override
  25. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  26. // 代码增强
  27. System.out.println("代理点收取服务费");
  28. Object object = method.invoke(trainStation, args);
  29. return object;
  30. }
  31. });
  32. return sellTicket;
  33. }
  34. public static void main(String[] args) {
  35. ProxyFactory proxyPoint = new ProxyFactory();
  36. SellTicket sellTicket = proxyPoint.getProxyPoint();
  37. sellTicket.sell();
  38. }
  39. }
3.3 cglib动态代理
  1. <!-- 引入cglib依赖包-->
  2. <dependency>
  3. <groupId>cglib</groupId>
  4. <artifactId>cglib</artifactId>
  5. <version>2.2.2</version>
  6. </dependency>
  1. package com.cglib;
  2. import net.sf.cglib.proxy.Enhancer;
  3. import net.sf.cglib.proxy.MethodInterceptor;
  4. import net.sf.cglib.proxy.MethodProxy;
  5. import java.lang.reflect.Method;
  6. public class ProxyFactory implements MethodInterceptor {
  7. private TrainStation trainStation = new TrainStation();
  8. public TrainStation getTrainStation(){
  9. //创建Enhancer对象,类似于JDK代理中的Proxy类
  10. Enhancer enhancer = new Enhancer();
  11. //设置父类的字节码对象
  12. enhancer.setSuperclass(TrainStation.class);
  13. //设置回调函数
  14. enhancer.setCallback(this);
  15. //创建代理对象
  16. TrainStation trainStation = (TrainStation)enhancer.create();
  17. return trainStation;
  18. }
  19. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  20. // 代码增强
  21. System.out.println("代售点收取服务费用");
  22. Object obj = method.invoke(trainStation, objects);
  23. return obj;
  24. }
  25. public static void main(String[] args) throws Exception {
  26. ProxyFactory proxyFactory = new ProxyFactory();
  27. TrainStation trainStation = proxyFactory.getTrainStation();
  28. trainStation.sell();
  29. }
  30. }

本文转载自: https://blog.csdn.net/qq_32088869/article/details/129655075
版权归原作者 王佑辉 所有, 如有侵权,请联系我们删除。

“【spring】jdk动态代理和cglib动态代理的区别”的评论:

还没有评论