SqlSessionFactory的Bean的注册容器

SqlSessionFactory的Bean的注册容器

总的流程如下:

  1. 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理
  2. 处理过程中会调用SpringFactoriesLoader#loadFactoryNames(),去查找所有jar下面META-INF/spring.factories中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,其中有org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
  3. 由于MybatisAutoConfiguration被@Configuratin注解,解析出里面有两个BeanMethod,name分别为SqlSessionFactory、SqlSessionTemplate
  4. 在ConfigurationClassPostProcessor#processConfigBeanDefinitions()中loadBeanDefinitions时,调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod(),对beanName分别为SqlSessionFactory、SqlSessionTemplate进行 BeanDefinition的属性设置,并注册IOC容器

具体自动配置加载过程可参考前文《Spring之事务源码》

mybatis-spring-boot-autoconfigure-xx.jar下面META-INF/spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

MybatisAutoConfiguration类源码如下:

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration implements InitializingBean {

  @Override
  public void afterPropertiesSet() {
    checkConfigFileExists();
  }

  private void checkConfigFileExists() {
    if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
      Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
    }
  }

  @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    applyConfiguration(factory);
    ......
    return factory.getObject();
  }
  
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    ExecutorType executorType = this.properties.getExecutorType();
    if (executorType != null) {
      return new SqlSessionTemplate(sqlSessionFactory, executorType);
    } else {
      return new SqlSessionTemplate(sqlSessionFactory);
    }
  }
}

SqlSessionFactory的实例化

调用链:

AbstractAutowireCapableBeanFactory#createBean() -->
AbstractAutowireCapableBeanFactory#doCreateBean() -->
AbstractAutowireCapableBeanFactory#createBeanInstance() --> AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod() --> ConstructorResolver#instantiateUsingFactoryMethod() --> ConstructorResolver#instantiate() --> SimpleInstantiationStrategy#instantiate() --> MybatisAutoConfiguration#sqlSessionFactory() --> SqlSessionFactory#getObject()-->SqlSessionFactory#afterPropertiesSet() --> SqlSessionFactory#buildSqlSessionFactory() --> XMLMapperBuilder#parse() --> XMLMapperBuilder#configurationElement() --> XMLMapperBuilder#buildStatementFromContext() --> XMLMapperBuilder#buildStatementFromContext() -->
XMLStatementBuilder#parseStatementNode() --> MapperBuilderAssistant#addMappedStatement() -- MappedStatement$Builder#()

和normal bean实例化不一样,sqlSessionFactory的实例化从instantiateUsingFactoryMethod()入口实现

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
    //sqlSessionFactory
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
}

其中afterPropertiesSet会进行sqlSessionFactory的build,进入后面重点

public class MybatisAutoConfiguration implements InitializingBean {
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
      ......
      return factory.getObject();
  }
}
  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }

    return this.sqlSessionFactory;
  }
  @Override
  public void afterPropertiesSet() throws Exception {
    this.sqlSessionFactory = buildSqlSessionFactory();
  }
mbd.factoryMethodToIntrospect

MybatisAutoConfiguration为factoryBean,取出里面所有满足条件的factoryMethod,其中包括public org.apache.ibatis.session.SqlSessionFactory org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration.sqlSessionFactory(javax.sql.DataSource) throws java.lang.Exception,将其赋值给 mbd.factoryMethodToIntrospect

protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {

	Method uniqueCandidate = mbd.factoryMethodToIntrospect;

	if (uniqueCandidate == null) {
        ......
		Method[] candidates = this.factoryMethodCandidateCache.computeIfAbsent(factoryClass,
				clazz -> ReflectionUtils.getUniqueDeclaredMethods(clazz, ReflectionUtils.USER_DECLARED_METHODS));

		for (Method candidate : candidates) {
			if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate) &&
					candidate.getParameterCount() >= minNrOfArgs) {
				// Declared type variables to inspect?
				if (candidate.getTypeParameters().length > 0) {
					......
				}
				else {
					uniqueCandidate = (commonType == null ? candidate : null);
				}
			}
		}
		mbd.factoryMethodToIntrospect = uniqueCandidate;
	}
}
posted @ 2020-11-26 09:42  曹自标  阅读(221)  评论(0编辑  收藏  举报