23种设计模式-java-代理

模式概述:

让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。

使用场景:

1.延迟初始化 (虚拟代理)。 如果你有一个偶尔使用的重量级服务对象, 一直保持该对象运行会消耗系统资源时, 可使用代理模式。
2.访问控制 (保护代理)。 如果你只希望特定客户端使用服务对象, 这里的对象可以是操作系统中非常重要的部分, 而客户端则是各种已启动的程序 (包括恶意程序), 此时可使用代理模式。
3.本地执行远程服务 (远程代理)。 适用于服务对象位于远程服务器上的情形。
4.记录日志请求 (日志记录代理)。 适用于当你需要保存对于服务对象的请求历史记录时。 代理可以在向服务传递请求前进行记录。
5. 智能引用。 可在没有客户端使用某个重量级对象时立即销毁该对象。

代码样例(静态代理):

代码背景:在不改变源码的情况下,分析相关业务接口的耗时情况(接口调用前、后记录时间)并对接口的调用记录日志。代理与装饰者模式非常相像。

/**
 * 被代理对象接口
 */
public interface OrderService {
    Map<String,String> getOrderInfoByOrderId(long orderId);
}
/**
 * 被代理对象接口实现
 */
public class OrderServiceImpl implements OrderService{
    @Override
    public Map<String, String> getOrderInfoByOrderId(long orderId) {
        System.out.println("被代理对象执行方法,orderId="+orderId);
        Map<String,String> map = new HashMap<>();
        map.put("orderId",String.valueOf(orderId));
        map.put("orderName","灰机");
        return map;
    }
}
/**
 * 代理--时间
 */
public class OrderServiceTimeProxy implements OrderService{
    private OrderService orderService;
    public OrderServiceTimeProxy(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public Map<String, String> getOrderInfoByOrderId(long orderId) {
        Map<String,String> map = null;
        System.out.println("时间代理----before--time:"+System.currentTimeMillis());
        map = orderService.getOrderInfoByOrderId(orderId);
        System.out.println("时间代理----after--time:"+System.currentTimeMillis());
        return map;
    }
}
/**
 * 代理--日志
 */
public class OrderServiceLogProxy implements OrderService{
    private OrderService orderService;
    public OrderServiceLogProxy(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public Map<String, String> getOrderInfoByOrderId(long orderId) {
        Map<String,String> map = null;
        System.out.println("日志代理----before");
        map = orderService.getOrderInfoByOrderId(orderId);
        System.out.println("日志代理----after");
        return map;
    }
}
/**
 * 代理测试
 */
public class TestProxy {
    public static void main(String[] args) {
        //静态代理
        System.out.println("静态代理:");
        OrderService orderService = new OrderServiceLogProxy(new OrderServiceTimeProxy(new OrderServiceImpl()));
        orderService.getOrderInfoByOrderId(1001l);

//        System.out.println();
//        System.out.println();
//        System.out.println();
//        System.out.println("动态代理:");
//        //动态代理
//        OrderService orderService2 = new OrderServiceImpl();
//        OrderService orderServiceDynamicProxy = (OrderService) DynamicProxyFactory.createProxy(orderService2);
//        Map<String,String> map = orderServiceDynamicProxy.getOrderInfoByOrderId(1002l);
//        System.out.println("接口返回信息:"+map.toString());
    }
}

测试结果:
23种设计模式-java-代理
此案例中是对orderService接口的getOrderInfoByOrderId()方法进行了代理;如果想要对orderService接口中的其他方法也设置代理,甚至对其他接口也设置日志和时间的代理,那么就需要增加很多代理类,因为静态代理类中代理对象和代理对象的方法都是已知固定的;只能代理指定的接口。因此就有了对应的动态代理,动态代理是动态生成代理类,而不是事先编码好代理类;动态代理和静态代理都是为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息;静态代理是事先编码好代理类,动态代理是程序运行时,动态生成代理类load到内存中。
JDK中的动态代理,生成代理对象需要传入3个参数,第一个是被代理对象的类加载器,第二个参数是被代理对象实现的接口,第三个参数InvocationHandler,可以理解是代理的实现逻辑。动态代理的生成是在程序运行时进行动态生成的,是操作字节码生成动态代理load到内存中的,生成的代理类会包含第二个参数中的接口数组的所有方法,方法内部的逻辑是调用第三个参数InvocationHandler的invoke方法;InvocationHandler的invoke方法通过反射调用到被代理对象的方法。注意JDK的代理的对象必须是实现接口 类;以下是JDK的代理的代码样例:


/**
 * 动态代理工厂--日志
 */
public class DynamicProxyFactory {
    public static <T> Object createProxy(T t){
        return Proxy.newProxyInstance(t.getClass().getClassLoader(),t.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object o;
                        System.out.println("动态代理--日志--before");
                        o = method.invoke(t,args);
                        System.out.println("动态代理--日志--after");
                        return o;
                    }
                });
    }
}
/**
 * 代理测试
 */
public class TestProxy {
    public static void main(String[] args) {
        //静态代理
//        System.out.println("静态代理:");
//        OrderService orderService = new OrderServiceLogProxy(new OrderServiceTimeProxy(new OrderServiceImpl()));
//        orderService.getOrderInfoByOrderId(1001l);

//        System.out.println();
//        System.out.println();
//        System.out.println();
//        System.out.println("动态代理:");
        //动态代理
        OrderService orderService2 = new OrderServiceImpl();
        OrderService orderServiceDynamicProxy = (OrderService) DynamicProxyFactory.createProxy(orderService2);
        Map<String,String> map = orderServiceDynamicProxy.getOrderInfoByOrderId(1002l);
        System.out.println("接口返回信息:"+map.toString());
    }
}

测试结果:
23种设计模式-java-代理

上一篇:IO测试工具之fio详解


下一篇:.NetCore选项数据热更新