代理模式

Posted linlf03

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式相关的知识,希望对你有一定的参考价值。

定义: 为其他对象提供一种代理,以控制对这个对象的访问

代理对象在客户端和目标对象之间起到中介的作用

类型: 结构性

 

适用场景

1、保护目标对象

2、增强目标对象

 

优点

代理模式能将代理对象与真实被调用的目标对象分离

一定程度上降低了系统的耦合度,扩展性好

保护目标对象

增强目标对象(如加before和after)

 

缺点:

代理模式会造成系统设计中类数目增加

在客户端和目标对象增加一个代理对象,会造成请求速度变慢

增加系统的复杂度

 

代理-扩展

静态代理

动态代理

CGLib代理

 

Spring 代理选择-扩展

当Bean有实现接口时,Spring就会用JDK的动态代理

当Bean没有实现接口时,Spring使用CGlib

可以强制使用Cglib

      在spring配置中加入 <aop:aspectj-autoproxy proxy-target-class="true" /> 

 

静态代理实践(另外一个静态代理的例子Spring AOP原理

1、创建实体Order

public class Order {
    private Object orderInfo;
    private Integer userId;

    public Object getOrderInfo() {
        return orderInfo;
    }

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

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}

  

2、创建Dao层

 IOrderDao接口

public interface IOrderDao {
    int insert(Order order);
}

  IOrderDao接口实现

public class OrderDaoImpl implements  IOrderDao {
    @Override
    public int insert(Order order) {
        System.out.println("Dao层添加Order成功");
        return 1;
    }
}

  

3、创建服务层

创建IOrderService 接口

public interface IOrderService {

    int saveOrder(Order order);

}

  创建IOrderService 接口实现

public class OrderServiceImpl   implements  IOrderService{

    private IOrderDao iOrderDao;

    @Override
    public int saveOrder(Order order) {
        //Spring会自己注入,这里就直接注入了
        iOrderDao = new OrderDaoImpl();
        System.out.println("Service层调用Dao层添加Order");
        return  iOrderDao.insert(order);
    }
}

  

4、模拟Spring中分库的使用介绍

创建DynamicDataSource  

public class DynamicDataSource  extends AbstractRoutingDataSource{


    /**
     * 返回值代表使用哪个Db
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDBType();
    }
}

  创建DataSourceContextHolder 

public class DataSourceContextHolder {

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

    public static  void setDBType(String dbType){
        CONTEXT_HOLDER.set(dbType);
    }

    public static  String getDBType(){
       return (String)  CONTEXT_HOLDER.get();
    }

    public static  void clearDBType(){
         CONTEXT_HOLDER.remove();
    }

}

  

5、创建代理类

public class OrderServiceStaticProxy {

    private IOrderService iOrderService;

    public int saveOrder(Order order){
        beforeMethod();
        iOrderService = new OrderServiceImpl();
        int userId = order.getUserId();
        int dbRouter = userId % 2;
        System.out.println("静态代理分配到【db" + dbRouter + "】处理数据");

        // TODO: 2020/1/27 设置dataSource
        DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
        afterMethod();
        return  iOrderService.saveOrder(order);
    }

    private void beforeMethod(){
        System.out.println("静态代理 before code");
    }

    private void afterMethod(){
        System.out.println("静态代理 after code");
    }

}

  

6、测试

public class Test {


    public static void main(String[] args) {
        Order order = new Order();
        order.setUserId(2);
        OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
        orderServiceStaticProxy.saveOrder(order);
    }
}

  

7、UML图如下

技术图片

 

 

8、输出结果如下

静态代理 before code
静态代理分配到【db0】处理数据
静态代理 after code
Service层调用Dao层添加Order
Dao层添加Order成功

  

 

以上是关于代理模式的主要内容,如果未能解决你的问题,请参考以下文章

scrapy按顺序启动多个爬虫代码片段(python3)

用于从 cloudkit 检索单列的代码模式/片段

java代码实现设计模式之代理模式

代理模式(静态代理动态代理)代码实战(详细)

Java设计模式-代理模式之动态代理(附源代码分析)

代理模式(静态代理)