使用过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的实例。

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

最新文章

  1. 手机平板等移动端适配跳转URL的js代码
  2. &lt;网页web工作面试题&gt;
  3. Java使用Scanner接收中文并输出时出现乱码
  4. Apache Shiro (一)
  5. 二项分布和Beta分布
  6. 试读《JavaScript语言精髓与编程实践》
  7. file与 byte[] 互转
  8. JavaScript(三)---- 控制流程语句
  9. SectionIndexer 利用系统的控件,制作比较美观的侧栏索引控件
  10. Sass之Compass学习笔记
  11. eclipse中 web项目缺少tomcatl lib的解决办法
  12. Python基础__字符串拼接、格式化输出与复制
  13. ACE在Linux下编译安装
  14. git 分支管理记录
  15. OpenJ_Bailian 2810 完美立方
  16. Git 藏匿操作
  17. OnSen UI结合AngularJs打造”美团&quot;APP底部导航栏 --Hybrid App
  18. docker命令及操作
  19. python 字符串的方法和注释
  20. (转)Tomcat配置调优与安全总结

热门文章

  1. python学习笔记9--日志模块logging
  2. 无线路由器的web漏洞
  3. UNIX环境高级编程--第一章 UNIX基础知识
  4. android 生成、pull解析xml文件
  5. div 只显示两行超出部分隐藏
  6. dubbo集群服务下一台服务挂了对服务调用的影响
  7. CF875F Royal Questions
  8. CF115B Lawnmower(贪心)
  9. Python2和Python3中print的不同点
  10. d 属性: 赋予字段执行动作的能力