MyBatis接口(Bean)與配置信息(Mapper)綁定

目的java

MyBatis的XML配置文件解析成JAVA類並在內存中存儲,可是在程序運行時須要對應的類去調用,而相應的調用類尚未實例化,如今流行的都是使用Spring去管理須要的對象,Spring提供2種方式,分別爲XML與註解。下面來分析調用類的實例化及與配置綁定。spring

1 XML方式sql

<bean id="menuMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    <property name="mapperInterface" value="cn.vansky.schedule.time.menu.dao.MenuMapper" />
</bean>

這裏相等於實例一個id爲menuMapper的對象,這個對象實際類是MapperFactoryBean,裏面包含2個屬性。當須要使用此對象時,直接使用id注入便可。下面來看看類裏面作了哪些操做?mybatis

protected void checkDaoConfig() {
    super.checkDaoConfig();
    notNull(this.mapperInterface, "Property 'mapperInterface' is required");
    Configuration configuration = getSqlSession().getConfiguration();
    if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
      try {
        configuration.addMapper(this.mapperInterface);
      } catch (Throwable t) {
        logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", t);
        throw new IllegalArgumentException(t);
      } finally {
        ErrorContext.instance().reset();
      }
    }
}

protected void checkDaoConfig() {
    notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}

@Autowired(required = false)
  public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (!this.externalSqlSession) {
      this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
}

@Autowired(required = false)
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    this.sqlSession = sqlSessionTemplate;
    this.externalSqlSession = true;
}

自身校驗接口類不能爲空,父類校驗SqlSession不能爲空,說明SqlSessionFactory與SqlSessionTemplate必須存在一個。app

MyBatis整合Spring的實現(17)中分析已經知道,SQL對應的Mapper文件已經解析並添加到Configuration(全局配置類)中,爲何這裏還會添加Mapper呢?由於前面分析的是對XML的解析,若是咱們的配置使用的註解方式,那麼這裏,個人Mapper是沒有解析的,當沒有解析時,這裏就會去解析註解並添加到Configuration(全局配置類)中。post

2 註解方式ui

<bean name="mapperScannerConfigurer_one" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="cn.vansky.schedule.time" />
        <property name="annotationClass" value="cn.vansky.framework.core.orm.mybatis.annotation.SqlMapper" />
        <property name="markerInterface" value="org.mybatis.spring.mapper.MapperFactoryBean" />
</bean>

這裏使用註解方式,把包cn.vansky.schedule.time下面的全部JAVA類所有實例化,可是這樣實例的話,那麼實際類型就是對應JAVA類的類型,也就至關於下面的配置。this

<bean id="menuMapper" class="cn.vansky.schedule.time.menu.dao.MenuMapper">
</bean>

這裏若是要是直接使用id注入,那麼就調用不到MyBatis的配置,因此分析MapperScannerConfigurer類作了哪些操做?spa

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }
    Scanner scanner = new Scanner(beanDefinitionRegistry);
    scanner.setResourceLoader(this.applicationContext);
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}

MapperScannerConfigurer類實現BeanDefinitionRegistryPostProcessor,須要執行postProcessBeanDefinitionRegistry方法。上圖紅框中,Spring把接口MenuMapper類的屬性修改了,使此類的實例化最終的Bean變成MapperFactoryBean並注入MapperFactoryBean類的屬性mapperInterface。也就至關於XML的配置(查看本章節1)。.net

3 BEAN注入

JAVA代碼裏面注入使用註解@Autowired,此註解默認使用類型獲取對應的對象。

這裏類型MenuMapper,而實際類型爲MapperFactoryBean,應該會出現類型轉換異常呀!

MyBatis作了進一步處理,MapperFactoryBean實現FactoryBean,必須實現getObject方法。

這裏是獲取最終的對象,mapperInterface屬性就是實際的類型MenuMapper。


SqlSession是SqlSessionTemplate,SqlSessionTemplate的getMapper方法。

經過代理工廠,實際的對象就經過代理實例化完成。最終的代理類就是MapperProxy。

總結

註解方式就是對XML的整合,把多個Bean實例化整合成一個XML配置,這樣省去多餘的配置信息,並且還提供了註解方式來配置SQL的Mapper信息。

相關文章
相關標籤/搜索