Spring源碼解析三

上傳人:每**** 文檔編號(hào):56562604 上傳時(shí)間:2022-02-22 格式:DOCX 頁(yè)數(shù):18 大小:80.06KB
收藏 版權(quán)申訴 舉報(bào) 下載
Spring源碼解析三_第1頁(yè)
第1頁(yè) / 共18頁(yè)
Spring源碼解析三_第2頁(yè)
第2頁(yè) / 共18頁(yè)
Spring源碼解析三_第3頁(yè)
第3頁(yè) / 共18頁(yè)

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁(yè)未讀,繼續(xù)閱讀

資源描述:

《Spring源碼解析三》由會(huì)員分享,可在線閱讀,更多相關(guān)《Spring源碼解析三(18頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。

1、 下面我們看看Spring JDBC相關(guān)的實(shí)現(xiàn),? 在Spring中,JdbcTemplate是經(jīng)常被使用的類(lèi)來(lái)幫助用戶程序操作數(shù)據(jù)庫(kù),在JdbcTemplate為用戶程序提供了許多便利的數(shù)據(jù)庫(kù)操作方法,比如查詢,更新等,而且在Spring中,有許多類(lèi)似 JdbcTemplate的模板,比如HibernateTemplate等等 – 看來(lái)這是Rod.Johnson的慣用手法,一般而言這種Template中都是通過(guò)回調(diào)函數(shù)CallBack類(lèi)的使用來(lái)完成功能的,客戶需要在回調(diào)接口中實(shí)現(xiàn)自己需要的定制行為,比如使用客戶想要用的SQL語(yǔ)句等。不過(guò)往往Spring通過(guò)這種回調(diào)函數(shù)的實(shí)現(xiàn)已經(jīng)為我們提供

2、了許多現(xiàn)成的方法供客戶使用。一般來(lái)說(shuō)回調(diào)函數(shù)的用法采用匿名類(lèi)的方式來(lái)實(shí)現(xiàn),比如:? ? 如轉(zhuǎn)載請(qǐng)注明,轉(zhuǎn)載自:關(guān)注Java[] 本文鏈接:?Spring源代碼分析(三):Spring JDBC Java代碼? 1. JdbcTemplate?=?new?JdbcTemplate(datasource); ?? 2. jdbcTemplate.execute(new?CallBack(){ ?? 3. ????????????public?CallbackInterfacedoInAction(){ ?? 4. ???????????????…… ?? 5. ?????????

3、??????//用戶定義的代碼或者說(shuō)Spring替我們實(shí)現(xiàn)的代碼??? 6. ????????????} ?? 推薦精選 7. }?? 在模板中嵌入的是需要客戶化的代碼,由Spring來(lái)作或者需要客戶程序親自動(dòng)手完成。下面讓我們具體看看在JdbcTemplate中的代碼是怎樣完成使命的,我們舉JdbcTemplate.execute()為例,這個(gè)方法是在JdbcTemplate中被其他方法調(diào)用的基本方法之一,客戶程序往往用這個(gè)方法來(lái)執(zhí)行基本的SQL語(yǔ)句:? ? Java代碼? 1. public?Object?execute(ConnectionCallback?action

4、)?throws?DataAccessException?{ ?? 2. ????//這里得到數(shù)據(jù)庫(kù)聯(lián)接??? 3. ????Connection?con?=?DataSourceUtils.getConnection(getDataSource()); ?? 4. ????try?{ ?? 5. ????????Connection?conToUse?=?con; ?? 6. ????????//有些特殊的數(shù)據(jù)庫(kù),需要我們使用特別的方法取得datasource??? 7. ????????if?(this.nativeJdbcExtractor?!=?null)?{ ?? 8.

5、 ????????????//?Extract?native?JDBC?Connection,?castable?to?OracleConnection?or?the?like.??? 推薦精選 9. ????????????conToUse?=?this.nativeJdbcExtractor.getNativeConnection(con); ?? 10. ????????} ?? 11. ????????else?{ ?? 12. ????????????//?Create?close-suppressing?Connection?proxy,?also?preparing

6、?returned?Statements.??? 13. ????????????conToUse?=?createConnectionProxy(con); ?? 14. ????????} ?? 15. ????//這里調(diào)用的是傳遞進(jìn)來(lái)的匿名類(lèi)的方法,也就是用戶程序需要實(shí)現(xiàn)CallBack接口的地方。??? 16. ????????return?action.doInConnection(conToUse); ?? 17. ????} ?? 18. ????catch?(SQLException?ex)?{ ?? 19. ????????//如果捕捉到數(shù)據(jù)庫(kù)異常,把數(shù)據(jù)庫(kù)聯(lián)接

7、釋放,同時(shí)拋出一個(gè)經(jīng)過(guò)Spring轉(zhuǎn)換過(guò)的Spring數(shù)據(jù)庫(kù)異常,??? 20. ????????//我們知道,Spring做了一個(gè)有意義的工作是把這些數(shù)據(jù)庫(kù)異常統(tǒng)一到自己的異常體系里了。??? 21. ????????DataSourceUtils.releaseConnection(con,?getDataSource()); ?? 22. ????????con?=?null; ?? 推薦精選 23. ????????throw?getExceptionTranslator().translate("ConnectionCallback",?getSql(action),?

8、ex); ?? 24. ????} ?? 25. ????finally?{ ?? 26. ????????//最后不管怎樣都會(huì)把數(shù)據(jù)庫(kù)連接釋放??? 27. ????????DataSourceUtils.releaseConnection(con,?getDataSource()); ?? 28. ????} ?? 29. }?? 對(duì)于JdbcTemplate中給出的其他方法,比如query,update,execute等的實(shí)現(xiàn),我們看看query():? ? Java代碼? 1. public?Object?query(PreparedStatementCreator

9、?psc,?final?PreparedStatementSetter?pss,?final?ResultSetExtractor?rse) ?? 2. ????????throws?DataAccessException?{ ?? 3. ????………. ?? 4. ????//這里調(diào)用了我們上面看到的execute()基本方法,然而這里的回調(diào)實(shí)現(xiàn)是Spring為我們完成的查詢過(guò)程??? 推薦精選 5. ????return?execute(psc,?new?PreparedStatementCallback()?{ ?? 6. ????????public?Object?d

10、oInPreparedStatement(PreparedStatement?ps)?throws?SQLException?{ ?? 7. ????????????//準(zhǔn)備查詢結(jié)果集??? 8. ????????????ResultSet?rs?=?null; ?? 9. ????????????try?{ ?? 10. ????????????//這里配置SQL參數(shù)??? 11. ????????????????if?(pss?!=?null)?{ ?? 12. ????????????????????pss.setValues(ps); ?? 13. ???????????

11、?????} ?? 14. ??????????//這里執(zhí)行的SQL查詢??? 15. ????????????????rs?=?ps.executeQuery(); ?? 16. ????????????????ResultSet?rsToUse?=?rs; ?? 17. ????????????????if?(nativeJdbcExtractor?!=?null)?{ ?? 18. ????????????????????rsToUse?=?nativeJdbcExtractor.getNativeResultSet(rs); ?? 19. ????????????????}

12、 ?? 20. ?????????//返回需要的記錄集合??? 21. ????????????????return?rse.extractData(rsToUse); ?? 22. ????????????} ?? 23. ????????????finally?{ ?? 推薦精選 24. ????????//最后關(guān)閉查詢的紀(jì)錄集,對(duì)數(shù)據(jù)庫(kù)連接的釋放在execute()中釋放,就像我們?cè)谏厦娣治龅目吹侥菢印??? 25. ????????????????JdbcUtils.closeResultSet(rs); ?? 26. ????????????????if?(pss

13、?instanceof?ParameterDisposer)?{ ?? 27. ????????????????????((ParameterDisposer)?pss).cleanupParameters(); ?? 28. ????????????????} ?? 29. ????????????} ?? 30. ????????} ?? 31. ????}); ?? 32. }?? 輔助類(lèi)DataSourceUtils來(lái)用來(lái)對(duì)數(shù)據(jù)庫(kù)連接進(jìn)行管理的主要工具,比如打開(kāi)和關(guān)閉數(shù)據(jù)庫(kù)連接等基本操作:? ? Java代碼? 1. public?static?Connection

14、?doGetConnection(DataSource?dataSource)?throws?SQLException?{ ?? 2. ???//把對(duì)數(shù)據(jù)庫(kù)連接放到事務(wù)管理里面進(jìn)行管理??? 3. ????ConnectionHolder?conHolder?=?(ConnectionHolder)?TransactionSynchronizationManager.getResource(dataSource); ?? 推薦精選 4. ????if?(conHolder?!=?null?&&?(conHolder.hasConnection()?||?conHolder.isSy

15、nchronizedWithTransaction()))?{ ?? 5. ????????conHolder.requested(); ?? 6. ????????if?(!conHolder.hasConnection())?{ ?? 7. ????????????logger.debug("Fetching?resumed?JDBC?Connection?from?DataSource"); ?? 8. ????????????conHolder.setConnection(dataSource.getConnection()); ?? 9. ????????} ?? 10.

16、 ????????return?conHolder.getConnection(); ?? 11. ????} ?? 12. ????//?這里得到需要的數(shù)據(jù)庫(kù)連接,在配置文件中定義好的。??? 13. ????logger.debug("Fetching?JDBC?Connection?from?DataSource"); ?? 14. ????Connection?con?=?dataSource.getConnection(); ?? 15. ?? 16. ????if?(TransactionSynchronizationManager.isSynchronizationA

17、ctive())?{ ?? 17. ????????logger.debug("Registering?transaction?synchronization?for?JDBC?Connection"); ?? 18. ????????//?Use?same?Connection?for?further?JDBC?actions?within?the?transaction.??? 推薦精選 19. ????????//?Thread-bound?object?will?get?removed?by?synchronization?at?transaction?completion

18、.??? 20. ????????ConnectionHolder?holderToUse?=?conHolder; ?? 21. ????????if?(holderToUse?==?null)?{ ?? 22. ????????????holderToUse?=?new?ConnectionHolder(con); ?? 23. ????????} ?? 24. ????????else?{ ?? 25. ????????????holderToUse.setConnection(con); ?? 26. ????????} ?? 27. ????????holderToU

19、se.requested(); ?? 28. ????????TransactionSynchronizationManager.registerSynchronization( ?? 29. ????????????????new?ConnectionSynchronization(holderToUse,?dataSource)); ?? 30. ????????holderToUse.setSynchronizedWithTransaction(true); ?? 31. ????????if?(holderToUse?!=?conHolder)?{ ?? 32. ??????

20、??????TransactionSynchronizationManager.bindResource(dataSource,?holderToUse); ?? 33. ????????} ?? 34. ????} ?? 推薦精選 35. ?? 36. ????return?con; ?? 37. }?? 那我們實(shí)際的DataSource對(duì)象是怎樣得到的?很清楚我們需要在上下文中進(jìn)行配置:它作為JdbcTemplate父類(lèi)JdbcAccessor的屬性存在:? ? Java代碼? 1. public?abstract?class?JdbcAccessor?implem

21、ents?InitializingBean?{ ?? 2. ?? 3. ????/**?這里是我們依賴注入數(shù)據(jù)庫(kù)數(shù)據(jù)源的地方。?*/?? 4. ????private?DataSource?dataSource; ?? 5. ?? 6. ????/**?Helper?to?translate?SQL?exceptions?to?DataAccessExceptions?*/?? 7. ????private?SQLExceptionTranslator?exceptionTranslator; ?? 8. ?? 9. ????private?boolean?lazyInit?=

22、?true; ?? 10. ?? 11. ????…….. ?? 推薦精選 12. }?? 而對(duì)于DataSource的緩沖池實(shí)現(xiàn),我們通過(guò)定義Apache Jakarta Commons DBCP或者C3P0提供的DataSource來(lái)完成,然后只要在上下文中配置好就可以使用了。從上面我們看到JdbcTemplate提供了許多簡(jiǎn)單查詢和更新功能,但是如果需要更高層次的抽象,以及更面向?qū)ο蟮姆椒▉?lái)訪問(wèn)數(shù)據(jù)庫(kù)。Spring為我們提供了 org.springframework.jdbc.object包,這里面包含了SqlQuery,SqlMappingQuery, SqlUpdate

23、和StoredProcedure等類(lèi),這些類(lèi)都是Spring JDBC應(yīng)用程序可以使用的主要類(lèi),但我們要注意使用這些類(lèi)的時(shí)候,用戶需要為他們配置好一個(gè)JdbcTemplate作為其基本的操作的實(shí)現(xiàn)。? 比如說(shuō)我們使用MappingSqlQuery來(lái)將表數(shù)據(jù)直接映射到一個(gè)對(duì)象集合 – 具體可以參考書(shū)中的例子? 1.我們需要建立DataSource和sql語(yǔ)句并建立持有這些對(duì)象的MappingSqlQuery對(duì)象? 2.然后我們需要定義傳遞的SqlParameter,具體的實(shí)現(xiàn)我們?cè)贛appingSqlQuery的父類(lèi)RdbmsOperation中可以找到:? ? Java代碼? 1.

24、 public?void?declareParameter(SqlParameter?param)?throws?InvalidDataAccessApiUsageException?{ ?? 推薦精選 2. ???//如果聲明已經(jīng)被編譯過(guò),則該聲明無(wú)效??? 3. ???if?(isCompiled())?{ ?? 4. ???????throw?new?InvalidDataAccessApiUsageException("Cannot?add?parameters?once?query?is?compiled"); ?? 5. ???} ?? 6. ???//這里對(duì)參數(shù)值

25、進(jìn)行聲明定義??? 7. ???this.declaredParameters.add(param); ?? 而這個(gè)declareParameters維護(hù)的是一個(gè)列表:? ? Java代碼? 1. /**?List?of?SqlParameter?objects?*/?? 2. private?List?declaredParameters?=?new?LinkedList();?? 這個(gè)列表在以后compile的過(guò)程中會(huì)被使用。? 3.然后用戶程序需要實(shí)現(xiàn)MappingSqlQuery的mapRow接口,將具體的ResultSet數(shù)據(jù)生成我們需要的對(duì)象,這是我們迭代使用的方法

26、。1,2,3步實(shí)際上為我們定義好了一個(gè)迭代的基本單元作為操作模板。? 4.在應(yīng)用程序,我們直接調(diào)用execute()方法得到我們需要的對(duì)象列表,列表中的每一個(gè)對(duì)象的數(shù)據(jù)來(lái)自于執(zhí)行SQL語(yǔ)句得到記錄集的每一條記錄,事實(shí)上執(zhí)行的execute 推薦精選 在父類(lèi)SqlQuery中起作用:? ? Java代碼? 1. public?List?executeByNamedParam(Map?paramMap,?Map?context)?throws?DataAccessException?{ ?? 2. ????validateNamedParameters(paramMap); ??

27、 3. ????Object[]?parameters?=?NamedParameterUtils.buildValueArray(getSql(),?paramMap); ?? 4. ????RowMapper?rowMapper?=?newRowMapper(parameters,?context); ?? 5. ????String?sqlToUse?=?NamedParameterUtils.substituteNamedParameters(getSql(),?new?MapSqlParameterSource(paramMap)); ?? 6. ????//我們又看到了Jd

28、bcTemplate,這里使用JdbcTemplate來(lái)完成對(duì)數(shù)據(jù)庫(kù)的查詢操作,所以我們說(shuō)JdbcTemplate是基本的操作類(lèi)。??? 7. ?????return?getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse,?parameters),?rowMapper); ?? 8. }?? 在這里我們可以看到template模式的精彩應(yīng)用和對(duì)JdbcTemplate的靈活使用。通過(guò)使用它,我們免去了手工迭代ResultSet并將其中的數(shù)據(jù)轉(zhuǎn)化為對(duì)象列表的重復(fù)過(guò)程。在這里我們只需要定義SQL語(yǔ)句和 推薦精選 Sq

29、lParameter – 如果需要的話,往往SQL語(yǔ)句就常常能夠滿足我們的要求了。這是靈活使用JdbcTemplate的一個(gè)很好的例子。? Spring還為其他數(shù)據(jù)庫(kù)操作提供了許多服務(wù),比如使用SqlUpdate插入和更新數(shù)據(jù)庫(kù),使用UpdatableSqlQuery更新ResultSet,生成主鍵,調(diào)用存儲(chǔ)過(guò)程等。? 書(shū)中還給出了對(duì)BLOB數(shù)據(jù)和CLOB數(shù)據(jù)進(jìn)行數(shù)據(jù)庫(kù)操作的例子:? 對(duì)BLOB數(shù)據(jù)的操作通過(guò)LobHander來(lái)完成,通過(guò)調(diào)用JdbcTemplate和RDBMS都可以進(jìn)行操作:? 在JdbcTemplate中,具體的調(diào)用可以參考書(shū)中的例子 – 是通過(guò)以下調(diào)用起作用的:?

30、 ? Java代碼? 1. public?Object?execute(String?sql,?PreparedStatementCallback?action)?throws?DataAccessException?{ ?? 2. ????return?execute(new?SimplePreparedStatementCreator(sql),?action); ?? 3. }?? 然后通過(guò)對(duì)實(shí)現(xiàn)PreparedStatementCallback接口的AbstractLobCreatingPreparedStatementCallback的回調(diào)函數(shù)來(lái)完成:? 推薦精選

31、 ? Java代碼? 1. public?final?Object?doInPreparedStatement(PreparedStatement?ps)?throws?SQLException,?DataAccessException?{ ?? 2. ????LobCreator?lobCreator?=?this.lobHandler.getLobCreator(); ?? 3. ????try?{ ?? 4. ????????//這是一個(gè)模板方法,具體需要由客戶程序?qū)崿F(xiàn)??? 5. ????????setValues(ps,?lobCreator); ?? 6. ???

32、?????return?new?Integer(ps.executeUpdate()); ? 7. ????} ?? 8. ????finally?{ ?? 9. ????????lobCreator.close(); ?? 10. ????} ?? 11. } ?? 12. //定義的需要客戶程序?qū)崿F(xiàn)的虛函數(shù)??? 13. protected?abstract?void?setValues(PreparedStatement?ps,?LobCreator?lobCreator) ?? 14. ????????throws?SQLException,?DataAccessExc

33、eption;?? 推薦精選 而我們注意到setValues()是一個(gè)需要實(shí)現(xiàn)的抽象方法,應(yīng)用程序通過(guò)實(shí)現(xiàn)setValues來(lái)定義自己的操作 – 在setValues中調(diào)用lobCreator.setBlobAsBinaryStrem()。讓我們看看具體的BLOB操作在LobCreator 是怎樣完成的,我們一般使用DefaultLobCreator作為BLOB操作的驅(qū)動(dòng):? ? Java代碼? 1. public?void?setBlobAsBinaryStream( ?? 2. ????????PreparedStatement?ps,?int?paramIndex,?In

34、putStream?binaryStream,?int?contentLength) ?? 3. ????????throws?SQLException?{ ?? 4. ????//通過(guò)JDBC來(lái)完成對(duì)BLOB數(shù)據(jù)的操作,對(duì)Oracle,Spring提供了OracleLobHandler來(lái)支持BLOB操作。??? 5. ????ps.setBinaryStream(paramIndex,?binaryStream,?contentLength); ?? 6. ????…….. ?? 7. }?? 上面提到的是零零碎碎的Spring JDBC使用的例子,可以看到使用Spring JD

35、BC可以幫助我們完成許多數(shù)據(jù)庫(kù)的操作。Spring對(duì)數(shù)據(jù)庫(kù)操作最基本的服務(wù)是通過(guò)JdbcTeamplate和他常用的回調(diào)函數(shù)來(lái)實(shí)現(xiàn)的,在此之上,又提供了許多RMDB的操作來(lái)幫助我們更便利的對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行操作 – 注意這里沒(méi)有引入向Hibernate這樣的O/R方案。對(duì)這些O/R方案的支持,Spring由其他包來(lái)完成服務(wù)。? 推薦精選 書(shū)中還提到關(guān)于execute和update方法之間的區(qū)別,update方法返回的是受影響的記錄數(shù)目的一個(gè)計(jì)數(shù),并且如果傳入?yún)?shù)的話,使用的是 java.sql.PreparedStatement,而execute方法總是使用 java.sql.Statement,不接受參數(shù),而且他不返回受影響記錄的計(jì)數(shù),更適合于創(chuàng)建和丟棄表的語(yǔ)句,而update方法更適合于插入,更新和刪除操作,這也是我們?cè)谑褂脮r(shí)需要注意的。 (注:可編輯下載,若有不當(dāng)之處,請(qǐng)指正,謝謝!) 推薦精選

展開(kāi)閱讀全文
溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔

相關(guān)搜索

關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號(hào):ICP2024067431號(hào)-1 川公網(wǎng)安備51140202000466號(hào)


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺(tái),本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng),我們立即給予刪除!