Java设计模式:代理模式

2018-08-22  本文已影响0人  vczyh

Java设计模式——代理模式

代理模式主要分为接口,委托类,代理类

接口:规定具体方法
委托类:实现接口,完成具体的业务逻辑
代理类:实现接口,在方法里面调用委托类的方法,自己不实现核心业务,在调用委托类的方法前后可以执行其他操作,也就是增强。

代理重要的特征就是: 委托类和代理类实现了相同的接口,由此对于调用者来说委托类和代理类没有什么不同,而且代理类的定制性更强,这也是和适配器模式的重要区别。

静态代理

静态代理是在编译时期就将接口,实现类,代理类全部编码,也就是在运行之前所有的class文件已经存在。

接口:


public interface Service {

    int increaseOne(int num);

    String toUpperCase(String str);
}

接口实现类(委托类):

public class ServiceImpl implements Service {

    @Override
    public int increaseOne(int num) {
        return ++num;
    }

    @Override
    public String toUpperCase(String str) {
        return str.toUpperCase();
    }
}

代理类:

public class ServiceProxy implements Service{

    private Service service;

    public ServiceProxy(Service service) {
        this.service = service;
    }

    @Override
    public int increaseOne(int num) {
        System.out.println("将要执行increaseOne");
        int i = service.increaseOne(num);
        System.out.println("increaseOne执行完毕");
        return i;
    }

    @Override
    public String toUpperCase(String str) {
        return service.toUpperCase(str);
    }
}

测试类:

public class MainTest {

    public static void main(String[] args) {

        Service service = new ServiceImpl();
        ServiceProxy serviceProxy = new ServiceProxy(service);
        /**
         * 在执行真正 increaseOne方法之前或者之后可以执行一系列操作
         * 这里用sout模拟
         */
        System.out.println(serviceProxy.increaseOne(5));

        /**
         * 调用真正的 toUpperCase方法
         */
        System.out.println(serviceProxy.toUpperCase("hello world"));
    }
}

输出:

将要执行increaseOne
increaseOne执行完毕
6
HELLO WORLD

JDK动态代理

JDK动态代理简化了静态代理的繁琐操作,不需要人工硬编码代理类实现接口。

实现InvocationHandler接口

public class DynamicProxyHandler implements InvocationHandler {

    private Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        if ("increaseOne".equals(method.getName())) {
            System.out.println("将要执行increaseOne");
            result = method.invoke(target, args);
            System.out.println("increaseOne执行完毕");
        } else {
            result = method.invoke(target, args);
        }

        return result;
    }

测试类:

public class MainTest {

    public static void main(String[] args) {

        Service service = new ServiceImpl();

        DynamicProxyHandler dynamicProxyHandler = new DynamicProxyHandler(service);

        Service serviceProxy = (Service) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                service.getClass().getInterfaces(), dynamicProxyHandler);

        System.out.println(serviceProxy.increaseOne(5));
        System.out.println(serviceProxy.toUpperCase("hello world"));
    }
}

输出:

将要执行increaseOne
increaseOne执行完毕
6
HELLO WORLD

比较分析

静态代理的实现方式:
代理类实现接口,实例化代理类,代理类的成员变量引用委托类对象,代理类调用方法,方法内部委托类对象调用方法。

JDK动态代理的实现方式:
与静态代理的过程是一样的,但是代理类编码是由JVM完成,我们只需要关注方法的实现细节。

CGLIB动态代理

CGLIB代理的是类,不同于JDK只能代理接口

委托类:

public class DelegateClass {

    public int increaseOne(int num) {
        return ++num;
    }

    public String toUpperCase(String str) {
        return str.toUpperCase();
    }
}

代理类:

public class CGLIBProxy implements MethodInterceptor {

  private Object target;

  public CGLIBProxy(Object target) {
      this.target = target;
  }

  @Override
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
      Object result;
      if ("increaseOne".equals(method.getName())) {
          System.out.println("将要执行increaseOne");
          result = method.invoke(target, args);
          System.out.println("increaseOne执行完毕");
      } else {
          result = method.invoke(target, args);
      }
      return result;
  }
}

测试类:

public class MainTest {

    public static void main(String[] args) {

        DelegateClass delegateClass = new DelegateClass();
        MethodInterceptor methodInterceptor = new CGLIBProxy(delegateClass);

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(DelegateClass.class);
        enhancer.setCallback(methodInterceptor);
        DelegateClass cglibProxy = (DelegateClass) enhancer.create();

        System.out.println(cglibProxy.increaseOne(5));
        System.out.println(cglibProxy.toUpperCase("hello world"));
    }
}

分析:

上一篇 下一篇

猜你喜欢

热点阅读