代理模式和 Java 动态代理

系统管理员 2022-07-24 09:20 271阅读 0赞

本文涉及到代理模式和 Java 反射的相关知识,如果对这两部分不熟的话,可以阅读作者的 代理模式 和 Java 反射教程。

代理模式

在代理模式中涉及到一个接口以及这个接口的两个实现类。这两个实现类,其中一个类为代理类,另一个为被代理的类。

一个接口

MyInterface.java

  1. public interface MyInterface {
  2. void doSomething1();
  3. void doSomething2();
  4. void doSomething3();
  5. }

被代理的类

MyTest.java

  1. public class MyTest implements MyInterface {
  2. @Override
  3. public void doSomething1() {
  4. System.out.println("doSomething1() called");
  5. }
  6. @Override
  7. public void doSomething2() {
  8. System.out.println("doSomething2() called");
  9. }
  10. @Override
  11. public void doSomething3() {
  12. System.out.println("doSomething3() called");
  13. }
  14. }

代理类

ProxyTest.java

  1. public class ProxyTest implements MyInterface {
  2. // 被代理对象
  3. private MyInterface realMyInterface;
  4. public ProxyTest(MyInterface realMyInterface) {
  5. this.realMyInterface = realMyInterface;
  6. }
  7. @Override
  8. public void doSomething1() {
  9. System.out.println("before doSomething1()");
  10. realMyInterface.doSomething1();
  11. System.out.println("after doSomething1()");
  12. System.out.println();
  13. }
  14. @Override
  15. public void doSomething2() {
  16. System.out.println("before doSomething2()");
  17. realMyInterface.doSomething2();
  18. System.out.println("after doSomething2()");
  19. System.out.println();
  20. }
  21. @Override
  22. public void doSomething3() {
  23. System.out.println("before doSomething3()");
  24. realMyInterface.doSomething3();
  25. System.out.println("after doSomething3()");
  26. System.out.println();
  27. }
  28. }

Demo.java

  1. public class Demo {
  2. public static void main(String[] args) {
  3. MyInterface myInterface = new MyTest();
  4. MyInterface proxy = new ProxyTest(myInterface);
  5. proxy.doSomething1();
  6. proxy.doSomething2();
  7. proxy.doSomething3();
  8. }
  9. }

输出结果:

  1. before doSomething1()
  2. doSomething1() called
  3. after doSomething1()
  4. before doSomething2()
  5. doSomething2() called
  6. after doSomething2()
  7. before doSomething3()
  8. doSomething3() called
  9. after doSomething3()

动态代理

在代理模式中的接口中如果有很多个方法,代理类就需要实现接口中的所有的方法,有些繁琐。有时候我们仅会在被代理方法的前面或后面加上相同或相似的处理,但我们在代理类中仍然需要实现接口中的每一个方法。

代理模式能实现的功能,动态代理也能实现,动态代理实现起来可能还要更简洁。
在代理模式中涉及到一个接口和该接口的两个实现类。在动态代理中涉及到一个接口和该接口的一个实现类和一个实现了 InvocationHandler 的实现类。

一个接口。

MyInterface.java

  1. public interface MyInterface {
  2. void doSomething1();
  3. void doSomething2();
  4. void doSomething3();
  5. }

被代理的类

MyTest.java

  1. public class MyTest implements MyInterface {
  2. @Override
  3. public void doSomething1() {
  4. System.out.println("doSomething1() called");
  5. }
  6. @Override
  7. public void doSomething2() {
  8. System.out.println("doSomething2() called");
  9. }
  10. @Override
  11. public void doSomething3() {
  12. System.out.println("doSomething3() called");
  13. }
  14. }

InvocationHandler.java

  1. public interface InvocationHandler {
  2. // proxy 是代理对象
  3. public Object invoke(Object proxy, Method method, Object[] args);
  4. }

MyInvocationHandler.java

  1. public class MyInvocationHandler implements InvocationHandler {
  2. // 被代理的对象
  3. private MyInterface myInterface;
  4. public MyInvocationHandler(MyInterface myInterface) {
  5. this.myInterface = myInterface;
  6. }
  7. @Override
  8. public Object invoke(Object proxy, Method method, Object[] args) {
  9. // proxy 是代理对象,不过在 invoke 方法中好像一般不会用到它
  10. System.out.println("before " + method.getName() + "()");
  11. // 通过反射调用被代理对象的 method
  12. Object returnValue = method.invoke(myInterface, args);
  13. System.out.println("after " + method.getName() + "()");
  14. System.out.println();
  15. return returnValue;
  16. }
  17. }

Demo.java

  1. public class Demo {
  2. public static void main(String[] args) {
  3. // 被代理的对象
  4. MyInterface myInterface = new MyTest();
  5. InvocationHandler invocationHandler = new MyInvocationHandler(myInterface);
  6. // 代理对象
  7. MyInterface myProxy = (MyInterface) Proxy.newProxyInstance(Demo.class.getClassLoader(), new Class[] {MyInterface.class}, invocationHandler);
  8. myProxy.doSomething1();
  9. myProxy.doSomething2();
  10. myProxy.doSomething3();
  11. }
  12. }

输出结果:

  1. before doSomething1()
  2. doSomething1() called
  3. after doSomething1()
  4. before doSomething2()
  5. doSomething2() called
  6. after doSomething2()
  7. before doSomething3()
  8. doSomething3() called
  9. after doSomething3()

代理模式和 Java 动态代理的比较

从输出结果来看,代理模式的输出结果和动态代理的输出结果是完全一样的。

代理模式和动态代理的相同点:

  • 两者可以实现同样的功能换句话说用代理模式能实现的用动态代理也能实现。
  • 两者都需要一个一个接口和该接口的一个实现类,在本例中是 MyInterface 接口和 MyTest(被代理的类)。

代理模式和动态代理的不同点:

  • 代理模式需要自己创建一个代理类,这个代理类和被代理类需要实现同一个接口。而动态代理不需要自己创建代理类,代理类是由 JVM 动态(在运行时)创建的,所以叫动态代理。
  • 动态代理中用户需要自己创建一个实现了 InvocationHandler 接口的类。一般来说,这个 invocation handler 有一个成员变量,这个成员变量是被代理的对象,有一个只有一个参数的共有构造方法,用于在创建 invocation handler 的时候把被代理的对象传入构造方法。
  • 代理模式中用户需要在代理类中去实现接口中的每一个方法,在动态代理中所有的逻辑处理都放在 invocation handler 中的 invoke() 方法中,由 invoke() 方法统一处理。
  • 动态代理中代理类关联了一个 InvocationHandler 对象,调用代理对象的某个方法时代理对象会把这个调用请求转发给 InvocationHandler 对象由 InvocationHandler 的 invoke() 方法来统一处理。

发表评论

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

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

相关阅读

    相关 代理模式java动态代理

    代理模式的作用及使用场景 使用代理模式的根本目的在于:如何在不直接操作对象的情况下,对此对象进行访问? 常用的场合包括:1)延迟加载;2)在调用实际对象的方法前后加入

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

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