最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入淺出重構Mybatis與Spring集成的SqlSessionFactoryBean(上)

 更新時間:2016年11月02日 14:04:52   作者:linjisong  
通常來講,重構是指不改變功能的情況下優(yōu)化代碼,但本文所說的重構也包括了添加功能。這篇文章主要介紹了重構Mybatis與Spring集成的SqlSessionFactoryBean(上)的相關資料,需要的朋友可以參考下

一般來說,修改框架的源代碼是極其有風險的,除非萬不得已,否則不要去修改。但是今天卻小心翼翼的重構了Mybatis官方提供的與Spring集成的SqlSessionFactoryBean類,一來是抱著試錯的心態(tài),二來也的確是有現(xiàn)實需要。

先說明兩點:

通常來講,重構是指不改變功能的情況下優(yōu)化代碼,但本文所說的重構也包括了添加功能

本文使用的主要jar包(版本):spring-*-4.3.3.RELEASE.jar、mybatis-3.4.1.jar、mybatis-spring-1.3.0.jar

下面從Mybatis與Spring集成談起。

一、集成Mybatis與Spring

<bean id="sqlSessionFactory" p:dataSource-ref="dataSource" class="org.mybatis.spring.SqlSessionFactoryBean" p:configLocation="classpath:mybatis/mybatis-config.xml">
<property name="mapperLocations">
<array>
<value>classpath*:**/*.sqlmapper.xml</value>
</array>
</property>
</bean>

集成的關鍵類為org.mybatis.spring.SqlSessionFactoryBean,是一個工廠Bean,用于產(chǎn)生Mybatis全局性的會話工廠SqlSessionFactory(也就是產(chǎn)生會話工廠的工廠Bean),而SqlSessionFactory用于產(chǎn)生會話SqlSession對象(SqlSessionFactory相當于DataSource,SqlSession相當于Connection)。

其中屬性(使用p命名空間或property子元素配置):

dataSource是數(shù)據(jù)源,可以使用DBCP、C3P0、Druid、jndi-lookup等多種方式配置

configLocation是Mybatis引擎的全局配置,用于修飾Mybatis的行為

mapperLocations是Mybatis需要加載的SqlMapper腳本配置文件(模式)。

當然還有很多其它的屬性,這里不一一例舉了。

二、為什么要重構

1、源碼優(yōu)化

SqlSessionFactoryBean的作用是產(chǎn)生SqlSessionFactory,那我們看一下這個方法(SqlSessionFactoryBean.java 384-538行):
/**
* Build a {@code SqlSessionFactory} instance.
*
* The default implementation uses the standard MyBatis {@code XMLConfigBuilder} API to build a
* {@code SqlSessionFactory} instance based on an Reader.
* Since 1.3.0, it can be specified a {@link Configuration} instance directly(without config file).
*
* @return SqlSessionFactory
* @throws IOException if loading the config file failed
*/
protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
Configuration configuration;
XMLConfigBuilder xmlConfigBuilder = null;
if (this.configuration != null) {
configuration = this.configuration;
if (configuration.getVariables() == null) {
configuration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
configuration.getVariables().putAll(this.configurationProperties);
}
} else if (this.configLocation != null) {
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Property `configuration` or '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 (this.vfs != null) {
configuration.setVfsImpl(this.vfs);
}
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 (this.databaseIdProvider != null) {//fix #64 set databaseId before parse mapper xmls
try {
configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
} catch (SQLException e) {
throw new NestedIOException("Failed getting a databaseId", e);
}
}
if (this.cache != null) {
configuration.addCache(this.cache);
}
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();
}
configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));
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");
}
}
return this.sqlSessionFactoryBuilder.build(configuration);
}

雖然Mybatis是一個優(yōu)秀的持久層框架,但老實說,這段代碼的確不怎么樣,有很大的重構優(yōu)化空間。

2、功能擴展

(1)使用Schema來校驗SqlMapper

<!-- DTD方式 -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dysd.dao.mybatis.config.IExampleDao">
</mapper>
<!-- SCHEMA方式 -->
<?xml version="1.0" encoding="UTF-8" ?>
<mapper xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://dysd.org/schema/sqlmapper"
xsi:schemaLocation="http://dysd.org/schema/sqlmapper http://dysd.org/schema/sqlmapper.xsd"
namespace="org.dysd.dao.mybatis.config.IExampleDao">
</mapper>

初看上去使用Schema更復雜,但如果配合IDE,使用Schema的自動提示更加友好,校驗信息也更加清晰,同時還給其他開發(fā)人員打開了一扇窗口,允許他們在已有命名空間基礎之上自定義命名空間,比如可以引入<ognl>標簽,使用OGNL表達式來配置SQL語句等等。

(2)定制配置,SqlSessionFactoryBean已經(jīng)提供了較多的參數(shù)用于定制配置,但仍然有可能需要更加個性化的設置,比如:

A、設置默認的結果類型,對于沒有設置resultType和resultMap的<select>元素,解析后可以為其設置默認的返回類型為Map,從而簡化SqlMapper的配置

<!--簡化前-->
<select id="select" resultType="map">
SELECT * FROM TABLE_NAME WHERE FIELD1 = #{field1, jdbcType=VARCHAR} 
</select>
<!--簡化后-->
<select id="select">
SELECT * FROM TABLE_NAME WHERE FIELD1 = #{field1, jdbcType=VARCHAR} 
</select>

B、擴展Mybatis原有的參數(shù)解析,原生解析實現(xiàn)是DefaultParameterHandler,可以繼承并擴展這個實現(xiàn),比如對于spel:為前綴的屬性表達式,使用SpEL去求值

(3)其它擴展,可參考筆者前面關于Mybatis擴展的相關博客

3、重構可行性

(1)在代碼影響范圍上

下面是SqlSessionFactoryBean的繼承結構

從中可以看出,SqlSessionFactoryBean繼承體系并不復雜,沒有繼承其它的父類,只是實現(xiàn)了Spring中的三個接口(JDK中的EventListener只是一個標識)。并且SqlSessionFactoryBean是面向最終開發(fā)用戶的,沒有子類,也沒有其它的類調(diào)用它,因此從代碼影響范圍上,是非常小的。

(2)在重構實現(xiàn)上,可以新建一個SchemaSqlSessionFactoryBean,然后一開始代碼完全復制SqlSessionFactoryBean,修改包名、類名,然后以此作為重構的基礎,這樣比較簡單。

(3)在集成應用上,只需要修改和spring集成配置中的class屬性即可。

以上所述是小編給大家介紹的重構Mybatis與Spring集成的SqlSessionFactoryBean(上),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關文章

  • Mybatis 插件原理解析

    Mybatis 插件原理解析

    mybatis是一款優(yōu)秀的ORM開源框架,這個框架具有極強的靈活性,本文再次給大家介紹Mybatis 插件原理,感興趣的朋友一起看看吧
    2021-10-10
  • Java設計模式之抽象工廠模式淺析講解

    Java設計模式之抽象工廠模式淺析講解

    當系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結構中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式,抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)
    2022-08-08
  • 簡述Springboot @Async 異步方法

    簡述Springboot @Async 異步方法

    這篇文章主要介紹了Springboot @Async 異步方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-05-05
  • Java 10 局部變量類型推斷淺析

    Java 10 局部變量類型推斷淺析

    這篇文章主要介紹了Java 10 局部變量類型推斷淺析,Java 10 引進一種新的閃閃發(fā)光的特性叫做局部變量類型推斷。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下
    2019-06-06
  • 關于Maven依賴沖突解決之exclusions

    關于Maven依賴沖突解決之exclusions

    這篇文章主要介紹了關于Maven依賴沖突解決之exclusions用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java this 關鍵字的使用方法詳解

    Java this 關鍵字的使用方法詳解

    這篇文章主要介紹了Java this 關鍵字的使用方法詳解的相關資料,希望通過本文能幫助到大家,讓大家徹底理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • 關于Hystrix的監(jiān)控及可視化面板

    關于Hystrix的監(jiān)控及可視化面板

    這篇文章主要介紹了關于Hystrix的監(jiān)控及可視化面板,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java如何將任意類型的Object對象轉(zhuǎn)換為相應的實體對象

    Java如何將任意類型的Object對象轉(zhuǎn)換為相應的實體對象

    這篇文章主要介紹了Java如何將任意類型的Object對象轉(zhuǎn)換為相應的實體對象問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Elasticsearch配置文件選項作用詳解(es7)

    Elasticsearch配置文件選項作用詳解(es7)

    這篇文章主要為大家介紹了Elasticsearch配置文件選項作用詳解(es7),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • 詳解springcloud 基于feign的服務接口的統(tǒng)一hystrix降級處理

    詳解springcloud 基于feign的服務接口的統(tǒng)一hystrix降級處理

    這篇文章主要介紹了詳解springcloud 基于feign的服務接口的統(tǒng)一hystrix降級處理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06

最新評論

八宿县| 大渡口区| 台南市| 佛坪县| 卓尼县| 莱西市| 周口市| 红安县| 田林县| 海原县| 怀来县| 柏乡县| 古田县| 潍坊市| 永善县| 天峻县| 泸西县| 崇文区| 肇东市| 林西县| 车致| 乌海市| 克山县| 乌兰察布市| 花莲县| 陆河县| 周口市| 闵行区| 永嘉县| 包头市| 周至县| 新竹县| 清远市| 承德县| 永兴县| 东丽区| 岗巴县| 广丰县| 开远市| 锡林郭勒盟| 军事|