主要是实现动态增强接口的功能
具体实现:

  1. 写一个接口,接口中封装了客户端需要的操作。
  2. 写一个委托类实现该接口
  3. 写一个代理类实现InvocationHandler接口,这个类中存在委托类的引用
  4. 客户端利用Proxy类的静态方法(反射技术),让接口关联代理实现类的对象,利用接口来调用方法,实际通过代理来访问委托类的方法。

静态代理

  • 写一个接口A,定义一些功能

  • 写一个类B,实现接口

  • 写一个类C,实现接口,并且C的内部有一个B实例,构造方法中也需要传入一个B对象b,重写接口方法时实际上是调用b对象的对应方法,但是此时可以添加一些其他的操作,相当于加强了类。

  • 图示
    图片说明

  • 代码

      // 静态代理,定义了一个代理类并且内部包含接口的一个实现类,代理类再实现接口,
      // 并且通过内部的类实例调用方法,本身只用于加强方法
      public class SimpleStaticProxyDemo {
          static interface IService {
              public void sayHello();
          }
    
          static class RealService implements IService {
              @Override
              public void sayHello() {
                  System.out.println("你好呀!!");
              }
          }
    
          static class TraceProxy implements IService {
              private IService realService;
    
              public TraceProxy(IService realService) {
                  this.realService = realService;
              }
    
              @Override
              public void sayHello() {
                  System.out.println("进入sayHello方法");
                  realService.sayHello();
                  System.out.println("退出sayHello方法");
              }
          }
    
          public static void main(String[] args) {
              IService realService = new RealService();
              IService proxyService = new TraceProxy(realService);
              proxyService.sayHello();
          }
      }
    

动态代理

  • JDK动态代理

    • 代码

        import java.lang.reflect.*;
      
        public class SimpleJDKDynamicProxyDemo {
            static interface IService {
                public void sayHello();
            }
      
            static class RealService implements IService {
                @Override
                public void sayHello() {
                    System.out.println("你好呀!!");
                }
            }
      
            static class SimpleInvocationHandler implements InvocationHandler {
                private Object realObject;
      
                public SimpleInvocationHandler(Object realObject) {
                    this.realObject = realObject;
                }
      
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("进入" + method.getName() + "方法");
                    // 调用realObject对象的method方法,参数是args
                    Object result = method.invoke(realObject, args);
                    System.out.println("离开" + method.getName() + "方法");
                    return result;
                }
            }
      
            public static void main(String[] args) throws Exception {
                IService realService = new RealService();
                // 通过Proxy.getProxyClass创建代理类定义,类定义会被缓存
                Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class<?>[]{IService.class});
                // 获取代理类的构造方法,构造方法中会有一个InvocationHandler类型的参数
                Constructor constructor = proxyClass.getConstructor(new Class[]{InvocationHandler.class});
                // 创建InvocationHandler和IService对象
                InvocationHandler handler = new SimpleInvocationHandler(realService);
                IService proxyService = (IService) constructor.newInstance(handler);
                proxyService.sayHello();
            }
        }
    • 本质上来看Proxy.getProxyClass会动态生成一个代理类,h是一个InvocationHandler类实例

        final class $Proxy0 extends Proxy implements SimpleJDKDynamicProxyDemo.IService {
            private static Method m1;
            private static Method m3;
            private static Method m2;
            private static Method m0;
      
            public $Proxy0(InvocationHandler paramInvocationHandler) {
                super(paramInvocationHandler);
            }
      
            public final boolean equals(Object paramObject) {
                return ((Boolean) h.invoke(this, m1, new Object[]{paramObject})).booleanValue();
            }
      
            public final void sayHello() {
                h.invoke(this, m3, null);
            }
      
            public final String toString() {
                return (String) h.invoke(this, m2, null);
            }
      
            public final int hashCode() {
                return ((Integer) h.invoke(this, m0, null)).intValue();
            }
      
            static {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
                m3 = Class.forName("edu.hut.proxy.SimpleJDKDynamicProxyDemo$IService").getMethod("sayHello", new Class[0]);
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            }
        }
  • 作用

    • 可以实现一种方法模板,只需要传入接口的class和一个实现了接口的类对象,就可以增强对应的方法(比如打印日志)

      • 代码

          import java.lang.reflect.*;
        
          public class GeneralProxyDemo {
              static interface IServiceA {
                  public void sayHello();
              }
        
              static class ServiceAImpl implements IServiceA {
        
                  @Override
                  public void sayHello() {
                      System.out.println("你好呀!!");
                  }
              }
        
              static interface IServiceB {
                  public void fly();
              }
        
              static class ServiceBImpl implements IServiceB {
        
                  @Override
                  public void fly() {
                      System.out.println("正在飞翔!!");
                  }
              }
        
              static class SimpleInvocationHandler implements InvocationHandler {
                  private Object realObj;
        
                  public SimpleInvocationHandler(Object realObj) {
                      this.realObj = realObj;
                  }
        
                  @Override
                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                      System.out.println("进入 " + realObj.getClass().getSimpleName() + "类的" + method.getName() + "方法");
                      Object result = method.invoke(realObj, args);
                      System.out.println("退出 " + realObj.getClass().getSimpleName() + "类的" + method.getName() + "方法");
                      return result;
                  }
              }
        
              private static <T> T getProxy(Class<T> intf, T realObj) {
                  return (T) Proxy.newProxyInstance(intf.getClassLoader(), new Class<?>[] { intf }, new SimpleInvocationHandler(realObj));
              }
        
              public static void main(String[] args) throws Exception {
                  IServiceA a = new ServiceAImpl();
                  IServiceA aProxy = getProxy(IServiceA.class, a);
                  aProxy.sayHello();
        
                  System.out.println("\n--------------分界线--------------\n");
        
                  IServiceB b = new ServiceBImpl();
                  IServiceB bProxy = getProxy(IServiceB.class, b);
                  bProxy.fly();
              }
          }
        
          // 运行结果
          进入 ServiceAImpl类的sayHello方法
          你好呀!!
          退出 ServiceAImpl类的sayHello方法
        
          --------------分界线--------------
        
          进入 ServiceBImpl类的fly方法
          正在飞翔!!
          退出 ServiceBImpl类的fly方法
  • cglib动态代理

    • 作用:可以代理类(JDK代理无法实现)

    • 代码

        public class SimpleCGLibDemo {
            static class RealService {
                public void sayHello() {
                    System.out.println("hello");
                }
            }
      
            static class SimpleInterceptor implements MethodInterceptor {
      
                @Override
                public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    System.out.println("entering " + method.getName());
                    Object result = proxy.invokeSuper(object, args);
                    System.out.println("leaving " + method.getName());
                    return result;
                }
            }
      
            @SuppressWarnings("unchecked")
            private static <T> T getProxy(Class<T> cls) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(cls);
                enhancer.setCallback(new SimpleInterceptor());
                return (T) enhancer.create();
            }
      
            public static void main(String[] args) throws Exception {
                RealService proxyService = getProxy(RealService.class);
                proxyService.sayHello();
            }
        }