程序员

代理模式

2020-10-20  本文已影响0人  CloudTL

2.代理模式

2.1 代理模式介绍

2.1.1 代理模式的应用场景

2.1.2 代理模式的UML图

UML图.png

代理模式一般分三个角色

  1. 抽象角色(ISbject):抽象主题类的主要职责是生命真实主题和代理的共同接口方法,该类可以是接口,也可以是抽象类。
  2. 真实角色(RealSubject):也被称为被代理类,该类定义了代理所表示的真实对象,是负责执行系统的真正的逻辑业务对象。
  3. 代理角色(Proxy):代理类,其内部有RealSubject的引用,因此具备完全的对RealSubject的代理权,客户端调用代理对象的方法,也调用被代理对象的方法,但是会在代理对象前后增加一些逻辑代码。

2.1.3 代理模式通用写法

public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new RealSubject());
        proxy.request();
    }

    interface ISbuject{
        void request();
    }

    //代理角色
    static class Proxy implements ISbuject{

        private ISbuject sbuject;

        public Proxy(ISbuject sbuject){
            this.sbuject = sbuject;
        }

        public void request() {
            before();
            sbuject.request();
            after();
        }

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

        private void before() {
            System.out.println("Proxy before");
        }
    }
    static class RealSubject implements ISbuject{

        public void request() {
            System.out.println("real subject");
        }
    }
}
QQ截图20201020151451.png

2.2 代理模式的实际问题解决

2.21 静态代理

一个代理对象对应一个被代理对象,不能代理其他被代理对象。

public interface IPerson {
    void find();

}

public class Son implements IPerson {
    public void find() {
        System.out.println("符合要求");
    }
}
public class Monther implements IPerson {

    private Son son;
    public Monther(Son son){
       this.son = son;
    }

    public void find() {
        before();
        son.find();
        after();
    }

    private void after() {
        System.out.println("开始相亲");
    }

    private void before() {
        System.out.println("家长催婚,并寻找相亲对象");
    }
}

静态代理.png

2.2.2 动态代理

静态代理太过于浪费成本,因此采用动态代理,只要实现了IPerson都可以进行代理,面前有JDK自带的代理以及CGLib代理。

public class JdkMeipo implements InvocationHandler {

    //获取字节码文件
    private IPerson instance;
    public IPerson getInstance(IPerson instance){
        this.instance = instance;
        Class<?> clazz = instance.getClass();
        return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(this.instance,args);
        after();
        return null;
    }

    private void after() {
        System.out.println("找到对象,开始相亲");
    }

    private void before() {
        System.out.println("媒婆收到需求,开始寻找对象");
    }
}
public class Zhangsan  implements IPerson{
    public void find() {
        System.out.println("符合张三需求");
    }

    //其他功能
}
    @Test
    public void test1(){
        JdkMeipo jdkMeipo = new JdkMeipo();
        IPerson zhangsan = jdkMeipo.getInstance(new Zhangsan());
        zhangsan.find();
    }
动态代理.png

2.2.3 三层架构种的静态代理

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;
    }
}
public class OrderDao {
    public int insert(Order order){
        System.out.println("OrderDao创建Order成功");
        return 1;
    }
}
public interface IOrderService {
    int createOrder(Order order);
}

public class OrderService implements IOrderService{
    private OrderDao orderDao;
    public OrderService(){
        //Spring自动注入OrderDao
        orderDao = new OrderDao();
    }

    public int createOrder(Order order) {
        System.out.println("OrderService调用OrderDao创建订单");

        return orderDao.insert(order);
    }
}
public class DynamicDataSourceEntry {
    //默认数据源
    public final static String DEFAULT_SOURCE=null;

    private final static ThreadLocal<String> local = new ThreadLocal<String>();

    private DynamicDataSourceEntry(){}

    //清空数据源
    public static void clear(){
        local.remove();
    }

    //获取当前正在使用的数据库名字
    public static String get(){
        return local.get();
    }

    //还原当前切换的数据源
    public static void restore(){
        local.set(DEFAULT_SOURCE);
    }

    //设置已知名字的数据源
    public static void set(String source){
        local.set(source);
    }

    //根据年份动态设置数据源
    public static void set(int year){
        local.set("DB_"+year);
    }
}
public class OrderServiceStaticProxy implements IOrderService {
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy");

    private IOrderService orderService;
    public OrderServiceStaticProxy(IOrderService orderService){
        this.orderService = orderService;
    }


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

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

    public int createOrder(Order order) {
        before();
        Long time = order.getCreateTime();
        Integer dbRouter = Integer.valueOf(sdf.format(new Date(time)));
        System.out.println("静态代理类自动分配到【DB_"+dbRouter+"】数据源处理数据");
        DynamicDataSourceEntry.set(dbRouter);
        orderService.createOrder(order);
        after();
        return 0;
    }
}
public class Test1 {
    @Test
    public void test(){
        try{
            Order order = new Order();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            Date date = sdf.parse("2011/11/11");
            order.setCreateTime(date.getTime());

            IOrderService orderService = new OrderServiceStaticProxy(new OrderService());
            orderService.createOrder(order);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
切换数据源.png 静态切换数据源.png

2.2.4 三层架构动态代理

public class OrderServiceDynamicProxy implements InvocationHandler {
    private SimpleDateFormat sdf = 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);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before(args[0]);
        Object object = method.invoke(target,args);
        after();
        return object;
    }

    private void after() {
    }

    private void before(Object target) {
        try {
            System.out.println("Proxy before method");
            Long time = (Long) target.getClass().getMethod("getCreateTime").invoke(target);
            Integer dbRouter = Integer.valueOf(sdf.format(new Date(time)));
            System.out.println("动态代理代理类自动分配到【DB_"+dbRouter+"】数据源处理数据");
            DynamicDataSourceEntry.set(dbRouter);
        }catch (Exception e){
            e.printStackTrace();

        }

    }
}
动态切换数据源.png

//TODO JDK源码分析,CGLib源码分析

上一篇 下一篇

猜你喜欢

热点阅读