当前位置:   article > 正文

mybatis扩展mybatis-plus原理剖析_sqlsessionfactorybean mybatis plus

sqlsessionfactorybean mybatis plus

一.mybatis-plus运行源码介绍

1.MybatisPlusAutoConfiguration初始化SqlSessionFactory的bean,初始化参数,调用getObject方法

  1. @Bean
  2. @ConditionalOnMissingBean
  3. public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
  4. throws Exception {
  5. // TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean
  6. MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
  7. factory.setDataSource(dataSource);
  8. return factory.getObject();
  9. }

2.MybatisSqlSessionFactoryBean工厂bean,生产SqlSessionFactory调用afterPropertiesSet,解析mapper.xml,放入自定义annotation的类对象xmlMapperBuilder.parse();

  1. public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
  2. public void afterPropertiesSet() throws Exception {
  3. this.sqlSessionFactory = buildSqlSessionFactory();
  4. }
  5. protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
  6. try {
  7. XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
  8. targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
  9. xmlMapperBuilder.parse();
  10. } catch (Exception e) {
  11. throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
  12. } finally {
  13. ErrorContext.instance().reset();
  14. }
  15. final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(targetConfiguration);
  16. return sqlSessionFactory;
  17. }
  18. }

3.XMLMapperBuilder.bindMapperForNamespace解析mapper.xml放入MybatisConfiguration对象

  1. public class XMLMapperBuilder extends BaseBuilder {
  2. private void bindMapperForNamespace() {
  3. if (boundType != null && !configuration.hasMapper(boundType)) {
  4. configuration.addMapper(boundType);
  5. }
  6. }
  7. }

4.MybatisConfiguration对象调用mybatisMapperRegistry注册对象

  1. public class MybatisConfiguration extends Configuration {
  2. public <T> void addMapper(Class<T> type) {
  3. mybatisMapperRegistry.addMapper(type);
  4. }
  5. }

5.MybatisMapperRegistry调用MybatisMapperAnnotationBuilder组装自定义mapper放入配置对象,knownMappers.put(type, new MybatisMapperProxyFactory<>(type));

  1. public class MybatisMapperRegistry extends MapperRegistry {
  2. @Override
  3. public <T> void addMapper(Class<T> type) {
  4. if (type.isInterface()) {
  5. boolean loadCompleted = false;
  6. try {
  7. knownMappers.put(type, new MybatisMapperProxyFactory<>(type));
  8. MapperAnnotationBuilder
  9. MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
  10. parser.parse();
  11. loadCompleted = true;
  12. } finally {
  13. if (!loadCompleted) {
  14. knownMappers.remove(type);
  15. }
  16. }
  17. }
  18. }
  19. }

6.MybatisMapperAnnotationBuilder.parserInjector解析注入

  1. public class MybatisMapperAnnotationBuilder extends
  2. MapperAnnotationBuilder {
  3. @Override
  4. public void parse() {
  5. if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) {
  6. parserInjector();
  7. }
  8. }
  9. void parserInjector() {
  10. GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
  11. }
  12. }

7.DefaultSqlInjector.inspectInject注入到配置,TableInfo tableInfo = TableInfoHelper.initTableInfo解析mapper接口类,初始化成tableInfo对象,方法inject循环注入

  1. */
  2. public abstract class AbstractSqlInjector implements ISqlInjector {
  3. @Override
  4. public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
  5. if (modelClass != null) {
  6. if (!mapperRegistryCache.contains(className)) {
  7. TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
  8. List<AbstractMethod> methodList = this.getMethodList(mapperClass, tableInfo);
  9. if (CollectionUtils.isNotEmpty(methodList)) {
  10. // 循环注入自定义方法
  11. methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
  12. } else {
  13. logger.debug(mapperClass.toString() + ", No effective injection method was found.");
  14. }
  15. mapperRegistryCache.add(className);
  16. }
  17. }
  18. }
  19. }

 8.每个操作类,select,insert,delete,update调用MapperBuilderAssistant.addMappedStatement将包括sql在内的MappedStatement通过mappedStatements.put(ms.getId(), ms)加入到MybatisConfiguration.mappedStatements

  1. public class MybatisConfiguration extends Configuration {
  2. protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
  3. .conflictMessageProducer((savedValue, targetValue) ->
  4. ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
  5. @Override
  6. public void addMappedStatement(MappedStatement ms) {
  7. mappedStatements.put(ms.getId(), ms);
  8. }
  9. }

9.SqlSessionTemplate.getMapper最终会调MybatisMapperRegistry.getMapper

  1. public class MybatisMapperRegistry extends MapperRegistry {
  2. public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  3. // TODO 这里换成 MybatisMapperProxyFactory 而不是 MapperProxyFactory
  4. // fix https://github.com/baomidou/mybatis-plus/issues/4247
  5. MybatisMapperProxyFactory<T> mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.get(type);
  6. if (mapperProxyFactory == null) {
  7. mapperProxyFactory = (MybatisMapperProxyFactory<T>) knownMappers.entrySet().stream()
  8. .filter(t -> t.getKey().getName().equals(type.getName())).findFirst().map(Map.Entry::getValue)
  9. .orElseThrow(() -> new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry."));
  10. }
  11. try {
  12. return mapperProxyFactory.newInstance(sqlSession);
  13. } catch (Exception e) {
  14. throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  15. }
  16. }
  17. }

10.MybatisMapperProxyFactory.newInstance调用jdk的动态代理生成mapper接口代理对象

  1. public class MybatisMapperProxyFactory<T> {
  2. @SuppressWarnings("unchecked")
  3. protected T newInstance(MybatisMapperProxy<T> mapperProxy) {
  4. return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
  5. }
  6. }

总结:

      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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/201422
推荐阅读
相关标签
  

闽ICP备14008679号