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

服務(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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 大好硬好深好爽想要视频 | 奇米色88欧美一区二区 | 成年人视频在线免费看 | 成人男女啪啪免费观看网站 | 性free非洲老妇 | 亚洲女性色尼古综合网 | 久久伊人免费 | bbbxxx乱大交欧美小说 | h动态图男女啪啪27报 | 美女靠逼动漫 | 被调教的校花 | 日本人护士免费xxxx视频 | 亚洲国产精品综合久久网络 | 美女被的在线网站91 | 糖心在线观看网 | 色老妇 | 热99re久久精品国产首页 | 国产亚洲精品一区在线播 | 全彩成人18h漫画 | 国产精品成人一区二区1 | 亚洲男人第一天堂 | 精品一区二区三区免费毛片 | 国产欧美日韩精品一区二区三区 | 国产成人精品曰本亚洲77美色 | 国产精品久久久久久久久免费hd | 国内精品久久久久久野外 | 深夜免费网站 | 欧美一区精品二区三区 | 操穴勤| 国产午夜免费秋霞影院 | 亚洲乱码尤物193yw在线播放 | 黑人巨大精品战中国美女 | 国产精品在线 | 小辣椒精品福利视频导航 | 久久九九亚洲精品 | 视频在线观看入口一二三2021 | 国产亚洲欧美日韩俺去了 | 国产老妇| 涩涩屋在线观看 | 秋葵视频成人 | 女人全身裸露无遮挡免费观看 |