通过分析整合示例中的配置文件,我们可以知道配置的bean其实是成树状结构的,而在树的最顶层是类型为org.mybatis.spring.SqlSessionFactoryBean的bean,它将其他相关bean组装在了一起,那么,我们的分析就从此类开始。
- InitializingBean接口:实现了这个接口,那么当bean初始化的时候,spring就会调用该接口的实现类的afterPropertiesSet方法,去实现当spring初始化该Bean的时候所需要的逻辑。
- FactoryBean接口:实现了该接口的类,在调用getBean的时候会返回该工厂返回的实例对象,也就是再调一次getObject方法返回工厂的实例。
- ApplicationListener接口:实现了该接口,如果注册了该监听的话,那么就可以了监听到Spring的一些事件,然后做相应的处理
SqlSessionFactoryBean的初始化
public void afterPropertiesSet() throws Exception { notNull(dataSource, "Property 'dataSource' is required"); notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required"); this.sqlSessionFactory = buildSqlSessionFactory(); }
从中我们可以看到,sqlSessionFactory的实例化便在这个方法里面实例化,buildSqlSessionFactory()方法会对我们的sqlSessionFactory做定制的初始化,初始化sqlSessionFactory有两种方式,一种是我们直接通过property直接注入到该实例中,另一种是通过解析xml的方式,就是我们在configuration.xml里面的配置,根据这些配置做了相应的初始化操作,里面也是一些标签的解析属性的获取,操作,和Spring的默认标签解析有点类似。
从buildSqlSessionFactory函数中可以看到,尽管我们还是习惯于将MyBatis的配置与Spring的配置独立出来,但是,这并不代表Spring中的配置不支持直接配置。也就是说,你完全可以取消配置中的configLocation属性,而把其中的属性直接写在SqlSessionFactoryBean中。配置文件还可以支持其他多种属性的配置,如configLocation、objectFactory、objectWrapperFactory、typeAliasesPackage、typeAliases、typeHandlersPackage、plugins、typeHandlers、transactionFactory、databaseIdProvider、mapperLocations。但是,为了体现Spring更强大的兼容性,Spring还整合了MyBatis中其他属性的注入,并通过实例configuration来承载每一步所获取的信息并最终使用sqlSessionFactoryBuilder实例根据解析到的configuration创建SqlSessionFactory实例。
获取SqlSessionFactoryBean实例
public SqlSessionFactory getObject() throws Exception { if (this.sqlSessionFactory == null) { afterPropertiesSet(); } return this.sqlSessionFactory; }
在给dao注入sqlSessionFactory的时候,依赖填写SqlSessionFactoryBean的实例就可以了。
fail-fast的检验
@Override public void onApplicationEvent(ApplicationEvent event) { if (failFast && event instanceof ContextRefreshedEvent) { // fail-fast -> check all statements are completed this.sqlSessionFactory.getConfiguration().getMappedStatementNames(); } }