mybatis的sqlSessionFactory的加载过程

Posted 倾慕已久

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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等属性,接下来我们看看这个方法主要干什么了?

1 public void afterPropertiesSet() throws Exception {
2     notNull(dataSource, "Property ‘dataSource‘ is required");
3     notNull(sqlSessionFactoryBuilder, "Property ‘sqlSessionFactoryBuilder‘ is required");
4 
5     this.sqlSessionFactory = buildSqlSessionFactory();
6   }

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

技术分享图片
  1 Configuration configuration;
  2 
  3     XMLConfigBuilder xmlConfigBuilder = null;
  4     if (this.configLocation != null) {
  5       xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
  6       configuration = xmlConfigBuilder.getConfiguration();
  7     } else {
  8       if (logger.isDebugEnabled()) {
  9         logger.debug("Property ‘configLocation‘ not specified, using default MyBatis Configuration");
 10       }
 11       configuration = new Configuration();
 12       configuration.setVariables(this.configurationProperties);
 13     }
 14 
 15     if (this.objectFactory != null) {
 16       configuration.setObjectFactory(this.objectFactory);
 17     }
 18 
 19     if (this.objectWrapperFactory != null) {
 20       configuration.setObjectWrapperFactory(this.objectWrapperFactory);
 21     }
 22 
 23     if (hasLength(this.typeAliasesPackage)) {
 24       String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
 25           ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
 26       for (String packageToScan : typeAliasPackageArray) {
 27         configuration.getTypeAliasRegistry().registerAliases(packageToScan,
 28                 typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
 29         if (logger.isDebugEnabled()) {
 30           logger.debug("Scanned package: ‘" + packageToScan + "‘ for aliases");
 31         }
 32       }
 33     }
 34 
 35     if (!isEmpty(this.typeAliases)) {
 36       for (Class<?> typeAlias : this.typeAliases) {
 37         configuration.getTypeAliasRegistry().registerAlias(typeAlias);
 38         if (logger.isDebugEnabled()) {
 39           logger.debug("Registered type alias: ‘" + typeAlias + "‘");
 40         }
 41       }
 42     }
 43 
 44     if (!isEmpty(this.plugins)) {
 45       for (Interceptor plugin : this.plugins) {
 46         configuration.addInterceptor(plugin);
 47         if (logger.isDebugEnabled()) {
 48           logger.debug("Registered plugin: ‘" + plugin + "‘");
 49         }
 50       }
 51     }
 52 
 53     if (hasLength(this.typeHandlersPackage)) {
 54       String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
 55           ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
 56       for (String packageToScan : typeHandlersPackageArray) {
 57         configuration.getTypeHandlerRegistry().register(packageToScan);
 58         if (logger.isDebugEnabled()) {
 59           logger.debug("Scanned package: ‘" + packageToScan + "‘ for type handlers");
 60         }
 61       }
 62     }
 63 
 64     if (!isEmpty(this.typeHandlers)) {
 65       for (TypeHandler<?> typeHandler : this.typeHandlers) {
 66         configuration.getTypeHandlerRegistry().register(typeHandler);
 67         if (logger.isDebugEnabled()) {
 68           logger.debug("Registered type handler: ‘" + typeHandler + "‘");
 69         }
 70       }
 71     }
 72 
 73     if (xmlConfigBuilder != null) {
 74       try {
 75         xmlConfigBuilder.parse();
 76 
 77         if (logger.isDebugEnabled()) {
 78           logger.debug("Parsed configuration file: ‘" + this.configLocation + "‘");
 79         }
 80       } catch (Exception ex) {
 81         throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
 82       } finally {
 83         ErrorContext.instance().reset();
 84       }
 85     }
 86 
 87     if (this.transactionFactory == null) {
 88       this.transactionFactory = new SpringManagedTransactionFactory();
 89     }
 90 
 91     Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
 92     configuration.setEnvironment(environment);
 93 
 94     if (this.databaseIdProvider != null) {
 95       try {
 96         configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
 97       } catch (SQLException e) {
 98         throw new NestedIOException("Failed getting a databaseId", e);
 99       }
100     }
101 
102     if (!isEmpty(this.mapperLocations)) {
103       for (Resource mapperLocation : this.mapperLocations) {
104         if (mapperLocation == null) {
105           continue;
106         }
107 
108         try {
109           XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
110               configuration, mapperLocation.toString(), configuration.getSqlFragments());
111           xmlMapperBuilder.parse();
112         } catch (Exception e) {
113           throw new NestedIOException("Failed to parse mapping resource: ‘" + mapperLocation + "‘", e);
114         } finally {
115           ErrorContext.instance().reset();
116         }
117 
118         if (logger.isDebugEnabled()) {
119           logger.debug("Parsed mapper file: ‘" + mapperLocation + "‘");
120         }
121       }
122     } else {
123       if (logger.isDebugEnabled()) {
124         logger.debug("Property ‘mapperLocations‘ was not specified or no matching resources found");
125       }
126     }
View Code

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

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

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

 

以上是关于mybatis的sqlSessionFactory的加载过程的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis源码解读——SqlSessionFactory

mybatis SqlSessionFactory的创建过程

mybatis源码阅读-SqlSessionFactory

MyBatis根据 XML 构建 SqlSessionFactory 时 Resources.getResourceAsStream 和 SqlSessionFactory 报红

mybatis中,sqlsessionfactory实例通过啥获得

12MyBatis-SqlSessionFactory的创建