一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 深入淺出重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)

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

2020-06-29 11:34linjisong JAVA教程

通常來講,重構(gòu)是指不改變功能的情況下優(yōu)化代碼,但本文所說的重構(gòu)也包括了添加功能。這篇文章主要介紹了重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)的相關(guān)資料,需要的朋友可以參考下

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

先說明兩點:

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

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

下面從Mybatis與Spring集成談起。

一、集成Mybatis與Spring

?
1
2
3
4
5
6
7
<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>

集成的關(guān)鍵類為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腳本配置文件(模式)。

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

二、為什么要重構(gòu)

1、源碼優(yōu)化

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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)秀的持久層框架,但老實說,這段代碼的確不怎么樣,有很大的重構(gòu)優(yōu)化空間。

2、功能擴展

(1)使用Schema來校驗SqlMapper

?
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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更復(fù)雜,但如果配合IDE,使用Schema的自動提示更加友好,校驗信息也更加清晰,同時還給其他開發(fā)人員打開了一扇窗口,允許他們在已有命名空間基礎(chǔ)之上自定義命名空間,比如可以引入<ognl>標簽,使用OGNL表達式來配置SQL語句等等。

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

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

?
1
2
3
4
5
6
7
8
<!--簡化前-->
<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)其它擴展,可參考筆者前面關(guān)于Mybatis擴展的相關(guān)博客

3、重構(gòu)可行性

(1)在代碼影響范圍上

下面是SqlSessionFactoryBean的繼承結(jié)構(gòu)

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

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

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

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

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

原文鏈接:http://www.cnblogs.com/linjisong/p/6022245.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 四虎论坛| 四虎院影永久在线观看 | 好男人资源大全免费观看 | 美国艳星lisann成人作品 | 色老板美国在线观看 | japanesemoms乱熟| 日韩国产成人资源精品视频 | 2021国产麻豆剧传媒剧情最新 | 无限在线观看免费入口 | 欧美日韩一区二区三区在线播放 | 456在线观看 | 91精品国产综合久久消防器材 | 草馏社区最新1024 | 欧美日韩一品道 | 美女被爆 | 美女被免费视频 | 九九精品视频在线观看 | 欧美香蕉视频 | 高清在线观看mv的网址免费 | 逼逼流水了 | 美女扒开腿让男人桶爽动态图片 | 无限在线看免费视频大全 | 青草碰人人澡人人澡 | 成人依依网 | 青青操在线播放 | 五月婷婷在线观看 | 高h辣文小说网 烧书阁 | 国产乱码一卡二卡3卡四卡 国产乱插 | 亚洲九九爱 | 忘忧草秋观看未满十八 | 憋尿调教绝望之岛 | 日韩欧美亚洲一区精选 | 欧美人妖大啪啪 | 无耻之徒第十一季在线观看 | 日日碰日日操 | 色哟哟在线播放 | 亚洲 日本 天堂 国产 在线 | 日韩色图区 | 百合女女师生play黄肉黄 | 男人狂躁女人gif动态图 | 性白俄罗斯高清xxxxx |