设计模式--代理模式(一、静态代理)

目标:

  1. 掌握代理的应用场景与实现原理
  2. 了解静态代理与动态代理的区别
  3. 了解CGLib与JDK Proxy的根本区别
  4. 手写实现自定义的JDK动态代理

代理模式:为其他对象提供一种代理,以控制对这个对象的访问。属于结构型设计模式
原理

一、静态代理(显示声明被代理对象)

1、案例一:

顶层接口–Person—找对象方法
目标对象–实现Person—儿子–找对象
代理对象–实现Person–父亲–替儿子物色对象

a、顶层Person接口

顶层接口

b、儿子找对象实现Person

儿子找对象实现Person

c、父亲帮儿子物色–Father类

4、测试
package com.ckw.proxy.staticproxy;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:27
 * @description: 静态代理测试
 */
public class StaticProxyTest {

    public static void main(String[] args) {

        Father father = new Father(new Son());

        father.findLove();

    }

}

结果

2、案例二

具体应用场景:在分布式业务场景中,我们通常会对数据库进行分库分表(如:按照年份来进行分库), 分库分表之后使用 Java 操作时,就可能需要配置多个数据源,我们通过设置数据源路由 来动态切换数据源-----在创建订单之前根据该订单的创建时间来存储到不同数据库

目标对象—创建订单方法
代理对象—在创建订单之前根据订单的创建时间存储不同数据库,实现动态切换数据源(增强创建订单的功能)

a、创建 Order 订单实体
package com.ckw.proxy.dbroute;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:45
 * @description: 订单实体类
 */
public class Order {
    private Object orderInfo;
    //订单创建时间进行按年分库
    private Long createTime;
    private String id;

    public Object getOrderInfo() {
        return orderInfo;
    }

    public void setOrderInfo(Object orderInfo) {
        this.orderInfo = orderInfo;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Long createTime) {
        this.createTime = createTime;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

b、创建 OrderDao 持久层操作类
package com.ckw.proxy.dbroute;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:45
 * @description: Dao层
 */
public class OrderDao {
    public int insert(Order order){
        System.out.println("OrderDao创建Order成功!");
        return 1;
    }
}

c、创建 IOrderService 接口
package com.ckw.proxy.dbroute;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:44
 * @description: 顶层接口:创建订单方法
 */
public interface IOrderService {
    int createOrder(Order order);
}

d、创建 OrderService 实现类
package com.ckw.proxy.dbroute;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:47
 * @description: service层
 */
public class OrderService implements IOrderService {
    private OrderDao orderDao;

    public OrderService(){
        //如果使用Spring应该是自动注入的
        //我们为了使用方便,在构造方法中将orderDao直接初始化了
        orderDao = new OrderDao();
    }

    @Override
    public int createOrder(Order order) {
        System.out.println("OrderService调用orderDao创建订单");
        return orderDao.insert(order);
    }
}

e、使用静态代理,主要完成的功能是,根据订单创建时间自动按年进行分库。原来写好的逻辑不去修改,通过代理对象来完成进行增强功能。先创建数据源路由对象,我们使用 ThreadLocal 的单例实现
package com.ckw.proxy.dbroute.proxy;

import com.ckw.proxy.dbroute.IOrderService;
import com.ckw.proxy.dbroute.Order;
import com.ckw.proxy.dbroute.OrderService;
import com.ckw.proxy.dbroute.db.DynamicDataSourceEntity;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:50
 * @description: 静态代理类
 */
public class OrderServiceStaticProxy implements IOrderService {

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");

    private OrderService orderService;

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

    //增强原有逻辑,但不会改变原有逻辑
    @Override
    public int createOrder(Order order) {
        before();
        Long createTime = order.getCreateTime();
        Integer dbRouter = Integer.valueOf(simpleDateFormat.format(new Date(createTime)));
        //增强逻辑(切换数据源)
        DynamicDataSourceEntity.set(dbRouter);
        System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据。");
        //原有逻辑
        this.orderService.createOrder(order);
        after();
        return 1;
    }

    private void before(){
        System.out.println("Proxy before method.");
    }

    private void after(){
        System.out.println("Proxy after method.");
    }
}

f、测试
package com.ckw.proxy.dbroute;

import com.ckw.proxy.dbroute.proxy.OrderServiceStaticProxy;
import org.junit.Test;

import java.util.Date;

/**
 * @author ckw
 * @version 1.0
 * @date 2020/6/9 19:54
 * @description: 代理测试
 */
public class DbRouteProxyTest {

    @Test
    public void testStaticProxy(){

        Order order = new Order();
        order.setCreateTime(new Date().getTime());

        OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy(new OrderService());

        orderServiceStaticProxy.createOrder(order);
    }

}

测试
结构图

g、静态代理缺点
  1. 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,则要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
  2. 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度

注:由于篇幅比较长、动态代理下一章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值