静态代理与动态代理(JDK代理/cglib代理)的区别

电玩女神 2021-12-15 17:37 442阅读 0赞

前提知识:

  (暂未发布)java代理设计模式

  (暂未发布)java发射相关知识

   (暂未发布)java装饰设计模式

静态代理与动态代理的区别:

  静态代理:创建代理类java文件或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

  动态代理:在程序运行时运用反射机制动态创建代理对象而成.在程序运行前代理类的.class文件不存在。

静态代理图解与代码说明: 本质是对于 (暂未发布)java装饰设计模式的一种应用。

1278244-20190311111726981-1959513655.png

动态代理主要包括两种模式JDK代理模式与cglib代理模式(参考spring的org.springframework.cglib.proxy包)

JDK代理主要是通过java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)函数基于(暂未发布)ClassLoader类加载机制实现,类似(暂未发布)java装饰设计模式来创建代理类

jdk代码说明:

  1. 1 import java.lang.reflect.InvocationHandler;
  2. 2 import java.lang.reflect.Method;
  3. 3 import java.lang.reflect.Proxy;
  4. 4
  5. 5 import cn.it.TxManager;
  6. 6
  7. 7 /**创始一个使用jdk的proxy完成动态代理工具
  8. 8 * implements InvocationHandler 自己创建的一个回调的处理器
  9. 9 * */
  10. 10 public class JDKProxyFactory implements InvocationHandler {
  11. 11 /**用于接收真实主题角色(目标对象) 多态的调用 */
  12. 12 private Object target;
  13. 13
  14. 14 /**用于接收事务对象*/
  15. 15 private TxManager txManager;
  16. 16
  17. 17 /**使用构造方法传递目标对象与事务对象*/
  18. 18 public JDKProxyFactory(Object target,TxManager txManager) {
  19. 19 this.target = target;
  20. 20 this.txManager = txManager;
  21. 21 }
  22. 22 /**创建代理对象*/
  23. 23 public Object createProxy() {
  24. 24 /** 使用java.lang.reflect.Proxy完成代理对象创建
  25. 25 * Proxy的static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ClassLoader 类加载器
  26. 26 * 所有Class都可以拿到ClassLoader(只要拿到它就可以了) 用于加载 class类文件
  27. 27 interfaces 得到目标对象的实现接口的Class[]
  28. 28 抽象主题角色 ,要从真实主题角色中拿到
  29. 29 java.lang.reflect.InvocationHandler 代理执行程序接口
  30. 30 主要是让咱们来完成相应的处理(添加上咱们想要在代理方法加添加的代码)
  31. 31 由于JDKProxyFactory本类implements实现InvocationHandler接口
  32. 32 InvocationHandler h 参数就是this对象
  33. 33 */
  34. 34 return Proxy.newProxyInstance(
  35. 35 this.getClass().getClassLoader(),
  36. 36 target.getClass().getInterfaces(), //真实主题角色的接口
  37. 37 this
  38. 38 );
  39. 39 }
  40. 40
  41. 41 /**
  42. 42 * 通过反射执行回调方法 在代理实例上处理方法调用并返回结果。
  43. 43 * Object proxy : 代理对象(几乎不用)
  44. 44 * java.lang.reflect.Method method : 实际执行的方法对象
  45. 45 * Object[] args : 实际调用方法中的参数
  46. 46 * 返回的是方法执行之后的返回值
  47. 47 */
  48. 48 @Override
  49. 49 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  50. 50
  51. 51 Object result = null;
  52. 52 try {
  53. 53 txManager.begin();//开始事务 调用事务对象的方法
  54. 54 /**
  55. 55 java.lang.reflect.Method method 的 Object invoke(Object obj, Object... args)
  56. 56 相当于result=target.invoke(args)*/
  57. 57
  58. 58 /** 加强 target.getName() 能获得执行的对象的类名 能够针对某些类来进行增强
  59. 59 if(target.getName().endwith("Dao")){
  60. 60 //增强的代码
  61. 61 }
  62. 62 */
  63. 63
  64. 64 /**对执行的方法进行判断 针对某些方法对象增强
  65. 65 save可以通过配置文件读取 dog4j解析
  66. 66 如 startwith endwith equals 来进行判断
  67. 67 */
  68. 68 if(method.endwith("save")){
  69. 69 //增强save方法执行前的代码
  70. 70 result = method.invoke(target, args);
  71. 71 //增强save方法执行后的代码
  72. 72 }else{
  73. 73 result = method.invoke(target, args);
  74. 74 }
  75. 75
  76. 76 txManager.commit();//提交事务
  77. 77 } catch (Exception e) {
  78. 78 txManager.rollback();//回滚事务
  79. 79 e.printStackTrace();
  80. 80 }
  81. 81 return result;
  82. 82 }
  83. 83 }
  84. 84
  85. 85 @Test
  86. 86 public void testProxy() throws Exception {
  87. 87 User user = new User("小红");
  88. 88 IUserService userService = new UserServiceImpl();
  89. 89 TxManager txManager = new TxManager();
  90. 90
  91. 91 JDKProxyFactory handler = new JDKProxyFactory(userService,txManager);
  92. 92 IUserService proxy = (IUserService)handler.createProxy();
  93. 93 // JDK底层使用的是装饰设计模式的代理
  94. 94 //UserServiceImpl proxy = (UserServiceImpl)handler.createProxy();会报错 CGlib不会报错
  95. 95
  96. 96 //proxy.update();
  97. 97 proxy.save(user);
  98. 98 }

cglib代理模式主要是通过org.springframework.cglib.proxy包利用spring的jar包中内置的asm字节码操作框架子包,利用(暂未发布)java继承增强的原理生成代理类

  1. Cglib代理模式代码案例说明
  2. import java.lang.reflect.Method;
  3. import org.springframework.cglib.proxy.Enhancer;
  4. import org.springframework.cglib.proxy.MethodInterceptor;
  5. import org.springframework.cglib.proxy.MethodProxy;
  6. /***cglib创建的 动态代理工具 */
  7. public class CglibProxyFactory implements MethodInterceptor {
  8. private Object target;
  9. private TxManager txManager;
  10. public CglibProxyFactory(Object target,TxManager txManager) {
  11. this.target = target;
  12. this.txManager = txManager;
  13. }
  14. // 创建代理对象
  15. public Object createProxy() {
  16. // 1.创建Enhancer
  17. Enhancer enhance = new Enhancer();
  18. // 2.参数:传递目标对象的Class 这样enhance对象就是目标对象的子类 底层使用子类继承的方式来增强父类方法
  19. enhance.setSuperclass(target.getClass());
  20. // 3.设置回调操作 (相当于InvocationHandler)
  21. //传入Callback callback CglibProxyFactory implements MethodInterceptor implements Callback
  22. //所以 this也就是callback对象
  23. enhance.setCallback(this);
  24. return enhance.create();
  25. }
  26. /**
  27. * 回调方法 参考 InvocationHandler中的invoke方法内的写法
  28. * Object proxy : 代理对象(几乎不用)
  29. * Method method : 执行的方法
  30. * Object[] args : 方法中的参数
  31. * MethodProxy mehtodProxy : 代理方法(用不到) 子类复写的方法
  32. * 返回的是方法执行之后的返回值
  33. */
  34. @Override
  35. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methdoProxy) throws Throwable {
  36. System.out.println("日志操作....");
  37. return method.invoke(target, args); // 与jdk的proxy中操作类似
  38. // return methdoProxy.invokeSuper(proxy, args); 不推荐
  39. }
  40. }
  41. @Test
  42. public void testProxy() throws Exception {
  43. User user = new User("小红");
  44. //真实主题角色
  45. UserServiceImpl userService = new UserServiceImpl();
  46. TxManager txManager = new TxManager();
  47. //代理主题主题没创建出来
  48. CglibProxyFactory handler = new CglibProxyFactory(userService, txManager);
  49. UserService obj = (UserService)handler.createProxy();
  50. UserServiceImpl obj = (UserServiceImpl)handler.createProxy();
  51. // UserServiceImpl$$EnhancerByCGLIB$$2536a285
  52. System.out.println(obj.getClass());
  53. obj.save(user);
  54. }

更多详情:请参考我的GitHub

转载于:https://www.cnblogs.com/qq1452753919/p/10507227.html

发表评论

表情:
评论列表 (有 0 条评论,442人围观)

还没有评论,来说两句吧...

相关阅读