【设计模式实践系列】代理模式

代理模式

代理模式属于结构型设计模式,主要是为了能够在不改变原始类代码的情况下,通过引入代理类来给原始类添加功能,代理模式应该是我们非常熟悉的一种设计模式,一般又可以分为静态代理和动态代理,静态代理指的是代理类在编译器就完成了代理功能,而动态代理则是在运行期动态生成的,最熟悉的SpringAOP,面向切面编程,使用的就是动态代理模式,可以动态的增加事务、日志、缓存等功能。

静态代理实例

为原方法添加访问统计功能

public interface OrderService {
    
    

    void createOrder();

}
public class OrderServiceImpl implements OrderService {
    
    
    @Override
    public void createOrder() {
    
    
        System.out.println("创建订单");
    }
}
public class OrderServiceProxy implements OrderService {
    
    

    private OrderServiceImpl orderService;

    static Map<String, Integer> count = new ConcurrentHashMap<>();

    public OrderServiceProxy() {
    
    
        orderService = new OrderServiceImpl();
    }

    @Override
    public void createOrder() {
    
    
        count.put("create_order_req_count", count.getOrDefault("create_order_req_count", 0) + 1);
        orderService.createOrder();
    }

    public int getCreateOrderReqCount() {
    
    
        return count.getOrDefault("create_order_req_count", 0);
    }
}
public class OrderTest {
    
    
    public static void main(String[] args) {
    
    
        OrderServiceProxy os = new OrderServiceProxy();
        os.createOrder();
        os.createOrder();
        int createOrderReqCount = os.getCreateOrderReqCount();
        System.out.println(createOrderReqCount);
    }
}

动态代理

在代理业务很少的情况下可以直接使用静态代理来实现,但是如果代理类很多,我们就要把所有的业务接口都实现一遍,添加重复的功能,这显然太麻烦了,要解决这个问题,就可以使用动态代理了,通过在运行时动态的创建代理类,避免了代理类的代码编写。

JDK动态代理

public interface OrderService {
    
    

    void createOrder();

    void queryOrder();

}
public class OrderServiceImpl implements OrderService {
    
    
    @Override
    public void createOrder() {
    
    
        System.out.println("创建订单");
    }

    @Override
    public void queryOrder() {
    
    
        System.out.println("查看订单");
    }
}
public class OrderServiceDynamicProxy implements InvocationHandler {
    
    

    private OrderService orderService;

    static Map<String, Integer> count = new ConcurrentHashMap<>();

    public OrderServiceDynamicProxy(OrderService orderService) {
    
    
        this.orderService = orderService;
    }

    public int getCreateOrderReqCount() {
    
    
        return count.getOrDefault("createOrder_req_count", 0);
    }

    public int getQueryOrderReqCount() {
    
    
        return count.getOrDefault("queryOrder_req_count", 0);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        count.put(method.getName() + "_req_count", count.getOrDefault(method.getName() + "_req_count", 0) + 1);
        return method.invoke(orderService, args);
    }
}
public class OrderTest {
    
    
    public static void main(String[] args) {
    
    
        OrderService orderService = new OrderServiceImpl();
        OrderServiceDynamicProxy invocationHandler = new OrderServiceDynamicProxy(orderService);
        OrderService newProxyInstance = (OrderService) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),
                orderService.getClass().getInterfaces(),
                invocationHandler);
        
        newProxyInstance.createOrder();
        newProxyInstance.createOrder();

        newProxyInstance.queryOrder();
        newProxyInstance.queryOrder();
        newProxyInstance.queryOrder();

        System.out.println("创建订单:" + invocationHandler.getCreateOrderReqCount() + "次,查看订单:" + invocationHandler.getQueryOrderReqCount() + "次");
    }
}

在这里插入图片描述

代理模式的实际应用场景

1、SpringAOP

SpringAOP都应该很熟悉了,底层实际上就是通过动态代理来实现的。

2、MyBatis

MyBatis最经典的使用方式就是直接使用接口方法,这实际上也是通过动态代理实现的。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    
    
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
    
    
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
    
    
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
    
    
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  
protected T newInstance(MapperProxy<T> mapperProxy) {
    
    
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] {
    
     mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    
    
    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
  
@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
    try {
    
    
      if (Object.class.equals(method.getDeclaringClass())) {
    
    
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
    
    
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
    
    
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

3、RPC

RPC最经典的口号就是像调用本地方法一样调用远程方法,RPC框架把嗲用远程方法的细节都封装了起来,实际上也是一种代理模式的思想。

おすすめ

転載: blog.csdn.net/CSDN_WYL2016/article/details/120896406
おすすめ