SqlSessionFactory的Bean的注册容器
总的流程如下:
- 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理
- 处理过程中会调用SpringFactoriesLoader#loadFactoryNames(),去查找所有jar下面META-INF/spring.factories中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,其中有org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
- 由于MybatisAutoConfiguration被@Configuratin注解,解析出里面有两个BeanMethod,name分别为SqlSessionFactory、SqlSessionTemplate
- 在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;
}
}