spring启动时mybatis-plus注入sql源码解析

MP在spring启动就会挨个分析xxxMapper中的方法,并且将对应的SQL语句处理好,保存到configuration对象中的mappedStatements中。

 

首先,在contextApplication.xml文件中配置的sqlSessionFactory配置的是mybatisplus的MyBatisSqlSessionFactoryBean,其implements

ApplicationListener,

FactoryBean,

InitializingBean

ssm启动信息

spring启动时mybatis-plus注入sql源码解析_第1张图片

前置知识:

Spring的InitializingBean接口有很好的用处,位于spring beans中,它只提供一个方法afterPropertiesSet(),当你实现了该方法后,spring就会对你提供框架级的支持:当你通过sring容器生产出实现了该接口的类的实例后,它就会调用afterPropertiesSet方法,通过这个方法,你可以检查你的bean是否正确地被初始化了。

在com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean#afterPropertiesSet中

 

this.sqlSessionFactory = buildSqlSessionFactory();

 

在buildSqlSessionFactory方法中

final MybatisConfiguration targetConfiguration;
SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(targetConfiguration);

初始化我们后面要使用的MybatisConfiguration

通过调用栈,可以看到,后面其执行了DaoSupport中的方法,DaoSupport也实现了InitializingBean,其afterPropertiesSet()方法中

checkDaoConfig();

最后执行的是MapperFactoryBean中的checkDaoConfig方法

Configuration configuration = getSqlSession().getConfiguration();
configuration.addMapper(this.mapperInterface);

 

在MyBatisConfiguration中

/**

 * 使用自己的 MybatisMapperRegistry

 */

@Override

public  void addMapper(Class type) {

    mybatisMapperRegistry.addMapper(type);

}

 

其addMapper方法进入到mybatis-plus中 MyBatisMapperRegistry

之后执行

 

MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
parser.parse();

 

进入到MybatisMapperAnnotationBuilder中(这个是mybatis中的对象)

注意:在其构造函数中,构造了后面要使用的MapperBuilderAsssistant

this.assistant = new MapperBuilderAssistant(configuration, resource);

 

执行parse方法

GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);

返回DefaultSqlInjector,执行inspectInject方法

在AbstractSqlInjector中,得到methodList,逐个执行inject方法

spring启动时mybatis-plus注入sql源码解析_第2张图片

List methodList = this.getMethodList();
// 循环注入自定义方法

methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));

之后在AbstractMethod中执行inject方法,调用其抽象方法injectMappedStatement

/**

 * 注入自定义方法

 */

public void inject(MapperBuilderAssistant builderAssistant, Class mapperClass, Class modelClass, TableInfo tableInfo) {

    /* 注入自定义方法 */

    injectMappedStatement(mapperClass, modelClass, tableInfo);

}

AbstractMethod的继承关系

spring启动时mybatis-plus注入sql源码解析_第3张图片

抽象方法在子类中有不同的实现类

如方法是selectById,那么就会进入到SelectById子类中,调用其injectMappedStatement,准备好参数后,再调用AbstractMethod中的addMappedStatement方法

public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) {

    SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;

    SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),

        sqlSelectColumns(tableInfo, false),

        tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),

        tableInfo.getLogicDeleteSql(true, false)), Object.class);

    return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, tableInfo);

}

SqlMethod : 枚举对象,MP支持的SQL方法

LOGIC_SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s"),

 

TableInfo:数据库表反射信息,可以获取到数据库表相关的信息

 

其通过String.format来构造sql,包括sql语句及对应的表,列名,参数,主键列等,对应到%s上

String.format(sqlMethod.getSql(),

    sqlSelectColumns(tableInfo, false),

    tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),

    tableInfo.getLogicDeleteSql(true, false))

 

public RawSqlSource(Configuration configuration, String sql, Class parameterType) {

最后得到的sql:

 

构造出一个SqlSource

SqlSource: SQL语句处理对象

 

MapperBuilderAssistant:用于缓存、SQL参数、查询方法结果集处理等

通过MapperBuilderAssistant将每一个mappedStatement 添加到configuration中的mappedstatements中

MappedStatement statement = statementBuilder.build();

configuration.addMappedStatement(statement);

 

这个configuration为mybatis-plus的MyBatisConfiguration,调用其addMappedStatement方法

public void addMappedStatement(MappedStatement ms) {

    logger.debug("addMappedStatement: " + ms.getId());

    super.addMappedStatement(ms);

}

在这里打印日志

spring启动时mybatis-plus注入sql源码解析_第4张图片

之后调用mybatis Configuration中的addMappedStatement方法,真正将方法添加到mappedStatements中

public void addMappedStatement(MappedStatement ms) {

  mappedStatements.put(ms.getId(), ms);

}

 

这样就在Configuration的mappedStatements中注入了这17个BaseMapper提供的方法

spring启动时mybatis-plus注入sql源码解析_第5张图片

这个过程的流程图:

spring启动时mybatis-plus注入sql源码解析_第6张图片

项目源码参考:https://gitee.com/constfafa/mybatis-plus-spring-demo.git

你可能感兴趣的:(mybatis,阅读源码,源码解析)