• 代理模式-2(动态代理)


      动态代理和静态代理的基本思路是一致的,只不过动态代理的功能更加强大,随着业务的扩展适应更强大。如果还以找对象为例,那么使用动态代理相当于能够适应复杂的业务场景。不仅包括父亲给儿子找对象,如果找对象这项业务发展成了一个产业,出现了媒婆、婚介所等,那么用静态代理成本太高了,需要一个更加通用的解决方案,满足任何单身人士找对象的需求。

      1.JDK 实现方式

      创建媒婆(婚介所)类 JDKMeipo:

    package com.xq.design.proxy.dynamicproxy.jdkproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.rmi.server.ExportException;
    
    public class JDKMeipo implements InvocationHandler {
        //被代理 的对象,把引用保存下来
        private Object target;
        public Object getInstance(Object target) throws ExportException {
            this.target = target;
            Class<?> clazz = target.getClass();
            return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object obj = method.invoke(this.target,args);
            after();
            return obj;
        }
        private void before(){
            System.out.println("我是媒婆:我要给你找对象,现在已经确认你的需求");
            System.out.println("开始物色");
        }
        private void after(){
            System.out.println("如果合适的话,就准备办事吧");
        }
    }

      创建单身客户类 Customer:

      

    public class Customer implements Person {
        @Override
        public void findLove() {
            System.out.println("高富帅");
            System.out.println("身高170");
            System.out.println("我有12块腹肌");
        }
    }

      测试代码如下:

      

        @Test
        void test(){
            try{
                Person obj = (Person) new JDKMeipo().getInstance(new Customer());
                obj.findLove();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

      测试结果如下:

      动态代理实现 数据源动态路由业务。 创建动态代理类 OrderServiceDynamicProxy:

    package com.xq.design.proxy.dynamicproxy.jdkproxy;
    
    import com.xq.design.proxy.staticproxy.dbroute.db.DynamicDataSourceEntry;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class OrderServiceDynamicProxy implements InvocationHandler {
        private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
        private Object target;
        public Object getInstance(Object target){
            this.target = target;
            Class<?> clazz = target.getClass();
            return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
         }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before(args[0]);
            Object object = method.invoke(target, args);
            after();
            return object;
        }
        public void before(Object target){
            try{
                System.out.println("Proxy before method.");
                Long time = (Long) target.getClass().getMethod("getCreateTime").invoke(target);
                Integer dbRouter = Integer.valueOf(yearFormat.format(new Date()));
                System.out.println("动态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据");
                DynamicDataSourceEntry.set(dbRouter);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        private void after(){
            System.out.println("Proxy after method.");
        }
    }

      测试代码如下:

        @Test
        void test(){
            try{
                Order order = new Order();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
                Date date = sdf.parse("2020/05/10");
                order.setCreateTime(date.getTime());
                IOrderService orderService = (IOrderService)new OrderServiceDynamicProxy().getInstance(new OrderService());
                orderService.createOrder(order);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

      测试结果如下:

      依然能够达到相同运行效果。但是,使用动态代理实现之后,我们不仅能实现 Order 的数据源冬天路由,还可以实现其他任何类的数据源路由。当然,有个比较重要的约定,必须实现 getCreateTiem() 方法。因为路由规则是根据时间来运算的。我们可以通过接口规范来达到约束的目的。

    本文来自博客园,作者:l-coil,转载请注明原文链接:https://www.cnblogs.com/l-coil/p/12865938.html

  • 相关阅读:
    查找mysql数据库中所有包含特定名字的字段所在的表
    redis在windows下安装和PHP中使用
    CentOS 6.3下源码安装LAMP(Linux+Apache+Mysql+Php)环境
    telnet: connect to address 127.0.0.1: Connection refused
    [Java]局域网五子棋
    springboot-web进阶(三)——统一异常处理
    springboot-web进阶(二)——AOP统一处理请求
    springboot-web进阶(一)——表单验证
    springboot快速入门(五)——事务管理
    springboot快速入门(四)——数据库操作
  • 原文地址:https://www.cnblogs.com/xianquan/p/12865938.html
Copyright © 2020-2023  润新知