引用博客:代理模式详解:静态代理+JDK/CGLIB 动态代理实战
代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
image.png

静态代理

从 JVM 层面来说, 静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。
实现步骤
1.定义一个接口和实现类
2.创建代理类同样实现接口
3.将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情

动态代理 - 图2

在SmsProxy里注入接口,并且实现接口,对方法增强

  1. private final SmsService smsService;
  2. public SmsProxy(SmsService smsService) {
  3. this.smsService=smsService;
  4. }
  5. @Override
  6. public String send(String message) {
  7. //调用方法之前,我们可以添加自己的操作
  8. System.out.println("before method send()");
  9. smsService.send(message);
  10. //调用方法之后,我们同样可以添加自己的操作
  11. System.out.println("after method send()");
  12. return null;
  13. }

动态代理

jdk动态代理

  1. 定义一个接口及其实现类;
  2. 自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑;
  3. 通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象;

    cglib动态代理

  4. 定义一个类;

  5. 自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,和 JDK 动态代理中的 invoke 方法类似;
  6. 通过 Enhancer 类的 create()创建代理类;

    JDK 动态代理和 CGLIB 动态代理对比

    1.JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
    2.就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。
    3.CGLIB实现的是方法级别的代理。