一.mybatis-plus运行源码介绍
1.MybatisPlusAutoConfiguration初始化SqlSessionFactory的bean,初始化参数,调用getObject方法
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
throws Exception {
// TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
return factory.getObject();
}
2.MybatisSqlSessionFactoryBean工厂bean,生产SqlSessionFactory调用afterPropertiesSet,解析mapper.xml,放入自定义annotation的类对象xmlMapperBuilder.parse();
public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
public void afterPropertiesSet() throws Exception {
this.sqlSessionFactory = buildSqlSessionFactory();
}
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(targetConfiguration);
return sqlSessionFactory;
}
}
3.XMLMapperBuilder.bindMapperForNamespace解析mapper.xml放入MybatisConfiguration对象
public class XMLMapperBuilder extends BaseBuilder {
private void bindMapperForNamespace() {
if (boundType != null && !configuration.hasMapper(boundType)) {
configuration.addMapper(boundType);
}
}
}
4.MybatisConfiguration对象调用mybatisMapperRegistry注册对象
public class MybatisConfiguration extends Configuration {
public <T> void addMapper(Class<T> type) {
mybatisMapperRegistry.addMapper(type);
}
}
5.MybatisMapperRegistry调用MybatisMapperAnnotationBuilder组装自定义mapper放入配置对象,knownMappers.put(type, new MybatisMapperProxyFactory<>(type));
public class MybatisMapperRegistry extends MapperRegistry {
@Override
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
boolean loadCompleted = false;
try {
knownMappers.put(type, new MybatisMapperProxyFactory<>(type));
MapperAnnotationBuilder
MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
}
6.MybatisMapperAnnotationBuilder.parserInjector解析注入
public class MybatisMapperAnnotationBuilder extends
MapperAnnotationBuilder {
@Override
public void parse() {
if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) {
parserInjector();
}
}
void parserInjector() {
GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
}
}
7.DefaultSqlInjector.inspectInject注入到配置,TableInfo tableInfo = TableInfoHelper.initTableInfo解析mapper接口类,初始化成tableInfo对象,方法inject循环注入
*/
public abstract class AbstractSqlInjector implements ISqlInjector {
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
if (modelClass != null) {
if (!mapperRegistryCache.contains(className)) {
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
List<AbstractMethod> methodList = this.getMethodList(mapperClass, tableInfo);
if (CollectionUtils.isNotEmpty(methodList)) {
// 循环注入自定义方法
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
} else {
logger.debug(mapperClass.toString() + ", No effective injection method was found.");
}
mapperRegistryCache.add(className);
}
}
}
}
8.每个操作类,select,insert,delete,update调用MapperBuilderAssistant.addMappedStatement将包括sql在内的MappedStatement通过mappedStatements.put(ms.getId(), ms)加入到MybatisConfiguration.mappedStatements
public class MybatisConfiguration extends Configuration {
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
.conflictMessageProducer((savedValue, targetValue) ->
". please check " + savedValue.getResource() + " and " + targetValue.getResource());
@Override
public void addMappedStatement(MappedStatement ms) {
mappedStatements.put(ms.getId(), ms);
}
}
9.SqlSessionTemplate.getMapper最终会调MybatisMapperRegistry.getMapper
public class MybatisMapperRegistry extends MapperRegistry {
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// TODO 这里换成 MybatisMapperProxyFactory 而不是 MapperProxyFactory
// fix https://github.com/baomidou/mybatis-plus/issues/4247
MybatisMapperProxyFactory<T> mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.entrySet().stream()
.filter(t -> t.getKey().getName().equals(type.getName())).findFirst().map(Map.Entry::getValue)
.orElseThrow(() -> new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry."));
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
}
10.MybatisMapperProxyFactory.newInstance调用jdk的动态代理生成mapper接口代理对象
public class MybatisMapperProxyFactory<T> {
@SuppressWarnings("unchecked")
protected T newInstance(MybatisMapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
}
总结:
1.mybatis-plus在mybatis的基础上通过解析mapper注解类的方式给mapper接口代理对象增加select,update,delete,insert,selectById等方法,查用简单方法无需再在mapper.xml中写sql
2.mybatis-plus逻辑删除,租户隔离,乐观锁,数据权限等操作是通过MybatisPlusInterceptor插件实现
3.集成点,在解析mapper.xml的时候,新建MybatisConfiguration继承configration,重写addMapper方法,新建MybatisMapperAnnotationBuilder继承MapperAnnotationBuilder,在parse注册自定义的MappedStatement
4.用户项目中如果有通用业务的查询,更新,添加或者删除可以仿照mybatis-plus的集成方式,添加自定义的MappedStatement
本文含有隐藏内容,请 开通VIP 后查看