装饰器设计模式
下面通过一个小例子描述了装饰器的概念
package com.example.zhuangshiqi;
/**
* @author Tao
* @date 2022/7/10 23:04
* @desciption: 装饰器设计模式
*/
public class Decorator {
//房子
public interface House{
//卧室
void bedroom();
}
//小房子
public static class SmallHouse implements House{
public SmallHouse(){
}
@Override
public void bedroom() {
System.out.println("小卧室");
}
}
//大房子
public static class BigHouse implements House{
public BigHouse(){
}
@Override
public void bedroom() {
System.out.println("大卧室");
}
}
//给房子按空调房子
public static class ConditionerHouse implements House{
//装饰者模式,维护一个对象。交给指定对象去实现
private final House delegate;
public ConditionerHouse(House delegate) {
this.delegate = delegate;
}
@Override
public void bedroom() {
delegate.bedroom();
buyAirConditioner();
}
public void buyAirConditioner(){
System.out.println("购买空调");
}
}
public static void main(String[] args) {
//给房子装空调
House house = roomSelection(true,"有钱");
house.bedroom();
}
//选房
public static House roomSelection(Boolean b,String status){
House house;
if (status.equals("没钱")){
house = new SmallHouse();
}else {
house = new BigHouse();
}
//天气太热是否安装空调
if (b){
house = new ConditionerHouse(house);
}
return house;
}
}
在mybatis 的Executor中体现
判断了在创建Executor的时候是否开启了缓存,如果开启了就利用缓存执行器装饰前面三种执行器。
模版设计模式
还是利用执行器举例 uml图
在抽象类里面出现下面这种抽象方法没有方法体的方法,这写称为模版方法
继承基础的执行器
总结: 这种将具体的实现方式交给 子类去实现 父类本身只是实现基本的方法的设计模式 称为 模板的设计模式
代理设计模式
先来个测试类,只要看过mybatis源码的都应该不陌生。
/**
* @Auther: xiaotao
* @Date: 2020/09/02/23:40
* @Description:
*/
public class Test001 {
@Test
public void testA() throws Exception{
//加载配置文件
Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
//获取一个事物
//SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取接口
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.queryById(1);
System.out.println("查询出来的对象是"+userById);
sqlSession.commit();
sqlSession.close();
}
}
是否有过这样的疑问?
mybatis明明就只写了一个简单的接口,如下面的UserMapper 。在使用的时候就能把数据从数据库中查询出来?
/**
* @Auther: xiaotao
* @Date: 2020/09/03/0:26
* @Description:
*/
public interface UserMapper {
User queryById(Integer id);
// @Select("select * from t_user where id = #{id}")
// User selectById(int id);
@Select("select * from user")
List<User> userPage(Page page);
}
解惑:使用了JDK动态代理,生成了代理类。
2:传入的是一个接口
1:返回的却是一个对象。
3:Proxy 关键字动态代理。
是整么实现的?
请下载源码,在上面图片处打断点,可以追一下流程。
描述一下大致流程。
mybatis 在项目启动的时候就会扫描所有的xml文件,根据xml中的标签,解析成一个一个的MappedStatement对象,放入Configuration 类的 mappedStatements 属性里面
//存放xml解析后的数据存放地方(描述xml的 增删改查 每一个节点放了一个在里面)。key为UserMapper.queryById
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());
这个map 的结构
到这一步。就会想。上面明明说的是 mapper接口为啥就能查出数据。那跟mybatis 启动的时候解析这些参数放入configuration中有什么关系呢?
有很大的关系。你想生成的代理类中的 sql,sqlSession,等 信息哪里来的?
肯定就是从这个map中取的晒。不然后面整么执行sql。整么处理数据?
下面就是对生成的代理类进行参数组装。
总结:就是把configuration中存的mappedStatements 赋值给代理对象,让他去执行mybatis的代码
责任链设计模式
mybatis的插件
项目启动将所有的插件放入集合中。每次执行sql语句的时候遍历插件集合。执行插件集合中具体的拦截器。实现数据的处理和实现。
分页插件 拦截器实现。
spring和mybatis和pageHelper整合的原理下次在记录一下