转载

mybatis的sqlSessionFactory的加载过程

使用过SSM的框架的都知道mybatis这个持久层框架,今天小编就来简单说说这个框架的核心工厂类sqlSessionFactory的加载过程,一般的SSM框架我们都会在spring的application.xml中引入如下的配置:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource"></property>

<property name="configLocation" value="classpath:config/mybatis-config.xml"></property>

</bean>

其中的SqlSessionFactoryBean便是加载sqlSessionFactory的入口,首先我们来看看这个类的源代码:

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

private static final Log logger = LogFactory.getLog(SqlSessionFactoryBean.class);

private Resource configLocation;

private Resource[] mapperLocations;

private DataSource dataSource;

private TransactionFactory transactionFactory;

private Properties configurationProperties;

private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

private SqlSessionFactory sqlSessionFactory;

其中标红的两处,就是我们在application.xml中注入的两个属性,从源码中我们可以看出该类实现了InitializingBean接口,实现了其afterPropertiesSet()方法,

该方法是在当前bean的所有属性被初始化完成之后再执行,也就是其中的datasource和configurationProperties等属性,接下来我们看看这个方法主要干什么了?

public void afterPropertiesSet() throws Exception {

notNull(dataSource, "Property 'dataSource' is required");

notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");

this.sqlSessionFactory = buildSqlSessionFactory();

}

其中第5行很明显的buildSqlSessionFactory()方法初始化了sqlSessionFactory ,接下来我们看看这个方法的主要行为:

Configuration configuration;

XMLConfigBuilder xmlConfigBuilder = null;

if (this.configLocation != null) {

xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);

configuration = xmlConfigBuilder.getConfiguration();

} else {

if (logger.isDebugEnabled()) {

logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");

}

configuration = new Configuration();

configuration.setVariables(this.configurationProperties);

}

if (this.objectFactory != null) {

configuration.setObjectFactory(this.objectFactory);

}

if (this.objectWrapperFactory != null) {

configuration.setObjectWrapperFactory(this.objectWrapperFactory);

}

if (hasLength(this.typeAliasesPackage)) {

String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,

ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

for (String packageToScan : typeAliasPackageArray) {

configuration.getTypeAliasRegistry().registerAliases(packageToScan,

typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);

if (logger.isDebugEnabled()) {

logger.debug("Scanned package: '" + packageToScan + "' for aliases");

}

}

}

if (!isEmpty(this.typeAliases)) {

for (Class<?> typeAlias : this.typeAliases) {

configuration.getTypeAliasRegistry().registerAlias(typeAlias);

if (logger.isDebugEnabled()) {

logger.debug("Registered type alias: '" + typeAlias + "'");

}

}

}

if (!isEmpty(this.plugins)) {

for (Interceptor plugin : this.plugins) {

configuration.addInterceptor(plugin);

if (logger.isDebugEnabled()) {

logger.debug("Registered plugin: '" + plugin + "'");

}

}

}

if (hasLength(this.typeHandlersPackage)) {

String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,

ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

for (String packageToScan : typeHandlersPackageArray) {

configuration.getTypeHandlerRegistry().register(packageToScan);

if (logger.isDebugEnabled()) {

logger.debug("Scanned package: '" + packageToScan + "' for type handlers");

}

}

}

if (!isEmpty(this.typeHandlers)) {

for (TypeHandler<?> typeHandler : this.typeHandlers) {

configuration.getTypeHandlerRegistry().register(typeHandler);

if (logger.isDebugEnabled()) {

logger.debug("Registered type handler: '" + typeHandler + "'");

}

}

}

if (xmlConfigBuilder != null) {

try {

xmlConfigBuilder.parse();

if (logger.isDebugEnabled()) {

logger.debug("Parsed configuration file: '" + this.configLocation + "'");

}

} catch (Exception ex) {

throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);

} finally {

ErrorContext.instance().reset();

}

}

if (this.transactionFactory == null) {

this.transactionFactory = new SpringManagedTransactionFactory();

}

Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);

configuration.setEnvironment(environment);

if (this.databaseIdProvider != null) {

try {

configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));

} catch (SQLException e) {

throw new NestedIOException("Failed getting a databaseId", e);

}

}

if (!isEmpty(this.mapperLocations)) {

for (Resource mapperLocation : this.mapperLocations) {

if (mapperLocation == null) {

continue;

}

try {

XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),

configuration, mapperLocation.toString(), configuration.getSqlFragments());

xmlMapperBuilder.parse();

} catch (Exception e) {

throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);

} finally {

ErrorContext.instance().reset();

}

if (logger.isDebugEnabled()) {

logger.debug("Parsed mapper file: '" + mapperLocation + "'");

}

}

} else {

if (logger.isDebugEnabled()) {

logger.debug("Property 'mapperLocations' was not specified or no matching resources found");

}

}

该方法主要就是设置configuration参数,首先是从mybatis-config.xml中获取对应的配置信息,然后再从spring的注入属性中获取所有的配置信息,从后调用

sqlSessionFactoryBuilder.build(configuration)方法获取sqlSessionFactory的实例。

由于整个加载过程没有过多的难点,所以就介绍到这里,感兴趣的朋友可以自己去源码,了解更多知识。

Linux公社的RSS地址: https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2018-08/153451.htm

原文  https://www.linuxidc.com/Linux/2018-08/153451.htm
正文到此结束
Loading...