通過分析整合示例中的配置文件,我們可以知道配置的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(); } }