Java动态代理相关简述

逃离我推掉我的手 2023-07-01 07:26 96阅读 0赞

一、概念:

Java动态代理的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(如Spring AOP、cglib等)。

代理模式:

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。(个人理解就是对调用目标的一种封装

静态代理

由程序员创建或者由第三方工具生成,再进行编译;在程序运行之前,代理类的.class文件已经存在了。
(静态代理类通常只代理一个类,静态代理事先知道要代理的是什么。)

动态代理:

在程序运行时,通过反射机制动态生成。动态代理类通常代理接口下的所有类。( 动态代理事先不知道要代理的是什么,只有在运行的时候才能确定。 ) 动态代理的调用处理程序必须事先InvocationHandler接口,及使用Proxy类中的newProxyInstance方法动态的创建代理类。JDK动态代理只能代理接口,要代理类需要使用第三方的CLIGB等类库。

二、JDK动态代理

在这里插入图片描述
上面的 JDK Proxy 例子,非常简单地实现了动态代理的构建和代理操作。
首先,实现对应的 InvocationHandler;
然后,以接口 Hello 为纽带,为被调用目标构建代理对象;
进而应用程序就可以使用代理对象间接运行调用目标的逻辑。
代理为应用插入额外逻辑(System.out.println("invoke:"))提供了便利的入口。

从 API 设计和实现的角度,这种实现仍然有局限性,因为它是以接口为中心的,相当于添加了一种对于被调用者没有太大意义的限制。我们实例化的是 Proxy 对象,而不是真正的被调用类型,这在实践中还是可能带来各种不便和能力退化。

如果被调用者没有实现接口,而我们还是希望利用动态代理机制,那么可以考虑其他方式(如cglib)。

三、cglib动态代理

cglib 动态代理采取的是创建目标类的子类的方式,因为是子类化,我们可以达到近似使用被调用者本身的效果,克服了接口的依赖。

  1. import org.springframework.cglib.proxy.Enhancer;
  2. import org.springframework.cglib.proxy.MethodInterceptor;
  3. import org.springframework.cglib.proxy.MethodProxy;
  4. import java.lang.reflect.Method;
  5. /** * @author wangcw * @create 2020-01-19 17:05 * @description:Cglib动态代理 **/
  6. public class DynamicProxyDemo {
  7. public static void main(String[] args) {
  8. HelloCglib helloCglib = new HelloCglib();
  9. Hello helloProxy = (Hello) helloCglib.getInstance(new Hello());
  10. helloProxy.sayHello();
  11. }
  12. /* 目标类 */
  13. static class Hello {
  14. public void sayHello() {
  15. System.out.println("hello world");
  16. }
  17. }
  18. static class HelloCglib implements MethodInterceptor {
  19. private Object target;
  20. public Object getInstance(Object target){
  21. this.target = target;
  22. Enhancer enhancer = new Enhancer();
  23. //设置父类为目标类
  24. enhancer.setSuperclass(this.target.getClass());
  25. // 回调方法
  26. enhancer.setCallback(this);
  27. // 创建代理对象
  28. return enhancer.create();
  29. }
  30. @Override
  31. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  32. System.out.println("扩展逻辑 1 - before invoke:");//扩展逻辑
  33. methodProxy.invokeSuper(o, objects);
  34. System.out.println("扩展逻辑 2 - after invoke!");//扩展逻辑
  35. return null;
  36. }
  37. }
  38. }

四、优势比较和应用

JDK Proxy 的优势:

1、最小化依赖关系,减少依赖意味着简化开发和维护,JDK 本身的支持,可能比 cglib 更加可靠;
2、平滑进行 JDK 版本升级,而字节码类库通常需要进行更新以保证在新版 Java 上能够使用;
3、代码实现简单;
4、新版本JDK也使用ASM提高性能。

基于类似 cglib 框架的优势:

1、有的时候调用目标可能不便实现额外接口,从某种角度看,限定调用者实现接口是有些侵入性的实践,类似 cglib 动态代理就没有这种限制;
2、只操作我们关心的类,而不必为其他相关类增加工作量;
3、基于ASM字节码,高性能;
4、通过生成业务类的子类作为代理类。

动态代理应用非常广泛,虽然最初多是因为 RPC 等使用进入我们视线,但是动态代理的使用场景远远不仅如此,它完美符合 Spring AOP 等切面编程。简单来说它可以看作是对 OOP 的一个补充,因为 OOP 对于跨越不同对象或类的分散、纠缠逻辑表现力不够,比如在不同模块的特定阶段做一些事情,类似日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等,你可以参考下面这张图。

在这里插入图片描述

发表评论

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

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

相关阅读

    相关 Java--代理模式(动态代理

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实