spring原始碼解讀之 JdbcTemplate原始碼
在Spring中,JdbcTemplate是經常被使用的類來幫助使用者程式操作資料庫,在JdbcTemplate為使用者程式提供了許多便利的資料庫操作方法,比如查詢,更新等,而且在Spring中,有許多類似 JdbcTemplate的模板,比如HibernateTemplate等等 - 看來這是Rod.Johnson的慣用手法,
所謂模板板式,就是在父類中定義演算法的主要流程,而把一些個性化的步驟延遲到子類中去實現,父類始終控制著整個流程的主動權,子類只是輔助父類實現某些可定製的步驟。
我們用程式碼來說話吧:
首先,父類要是個抽象類:
- public abstract class TemplatePattern {
- //模板方法
- public final void templateMethod(){
- method1();
- method2();//勾子方法
- method3();//抽象方法
- }
- private void method1(){
- System.out.println("父類實現業務邏輯");
- }
-
public void method2(){
- System.out.println("父類預設實現,子類可覆蓋");
- }
- protected abstract void method3();//子類負責實現業務邏輯
- }
父類中有三個方法,分別是method1(),method2()和method3()。
method1()是私有方法,有且只能由父類實現邏輯,由於方法是private的,所以只能父類呼叫。
method2()是所謂的勾子方法。父類提供預設實現,如果子類覺得有必要定製,則可以覆蓋父類的預設實現。
method3()是子類必須實現的方法,即制定的步驟。
由此可看出,演算法的流程執行順序是由父類掌控的,子類只能配合。
下面我們來寫第一個子類:
Java程式碼
- public class TemplatePatternImpl extends TemplatePattern {
- @Override
- protected void method3() {
- System.out.println("method3()在子類TemplatePatternImpl中實現了!!");
- }
- }
這個子類只覆蓋了必須覆蓋的方法,我們來測試一下:
Java程式碼
- TemplatePattern t1 = new TemplatePatternImpl();
- t1.templateMethod();
在控制檯中我們可以看到:
Java程式碼
- 父類實現業務邏輯
- 父類預設實現,子類可覆蓋
- method3()在子類TemplatePatternImpl中實現了!!
OK,我們來看看勾子方法的使用:
定義第2個子類,實現勾子方法:
Java程式碼
- public class TemplatePatternImpl2 extends TemplatePattern {
- @Override
- protected void method3() {
- System.out.println("method3()在子類TemplatePatternImpl2中實現了!!");
- }
- /* (non-Javadoc)
- * @see com.jak.pattern.template.example.TemplatePattern#method2()
- */
- @Override
- public void method2() {
- System.out.println("子類TemplatePatternImpl2覆蓋了父類的method2()方法!!");
- }
- }
來測試一下:
Java程式碼
- TemplatePattern t2 = new TemplatePatternImpl2();
- t2.templateMethod();
我們看控制檯:
Java程式碼
- 父類實現業務邏輯
- 子類TemplatePatternImpl2覆蓋了父類的method2()方法!!
- method3()在子類TemplatePatternImpl2中實現了!!
OK,經典的模板模式回顧完了(大家不要拍磚哦~~~~~~~~~~)
接下來,我們回到正題,自己模仿spring動手寫一個基於模板模式和回撥的jdbcTemplate。
回顧一下,spring為什麼要封裝JDBC API,對外提供jdbcTemplate呢(不要仍雞蛋啊¥·%¥#%)
話說SUN的JDBC API也算是經典了,曾經在某個年代折服了一批人。但隨著歷史的發展,純粹的JDBC API已經過於底層,而且不易控制,由開發人員直接接觸JDBC API,會造成不可預知的風險。還有,資料連線快取池的發展,也不可能讓開發人員去手工獲取JDBC了。
好了,我們來看一段曾經堪稱經典的JDBC API程式碼吧:
Java程式碼
- public List<User> query() {
- List<User> userList = new ArrayList<User>();
- String sql = "select * from User";
- Connection con = null;
- PreparedStatement pst = null;
- ResultSet rs = null;
- try {
- con = HsqldbUtil.getConnection();
- pst = con.prepareStatement(sql);
- rs = pst.executeQuery();
- User user = null;
- while (rs.next()) {
- user = new User();
- user.setId(rs.getInt("id"));
- user.setUserName(rs.getString("user_name"));
- user.setBirth(rs.getDate("birth"));
- user.setCreateDate(rs.getDate("create_date"));
- userList.add(user);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }finally{
- if(rs != null){
- try {
- rs.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- try {
- pst.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- try {
- if(!con.isClosed()){
- try {
- con.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- return userList;
- }
上面的程式碼要若干年前可能是一段十分經典的,還可能被作為example被推廣。但時過境遷,倘若哪位程式設計師現在再在自己的程式中出現以上程式碼,不是說明該公司的開發框架管理混亂,就說明這位程式設計師水平太“高”了。
我們試想,一個簡單的查詢,就要做這麼一大堆事情,而且還要處理異常,我們不防來梳理一下:
1、獲取connection
2、獲取statement
3、獲取resultset
4、遍歷resultset並封裝成集合
5、依次關閉connection,statement,resultset,而且還要考慮各種異常
6、.....
啊~~~~ 我快要暈了,在面向物件程式設計的年代裡,這樣的程式碼簡直不能上人容忍。試想,上面我們只是做了一張表的查詢,如果我們要做第2張表,第3張表呢,又是一堆重複的程式碼:
1、獲取connection
2、獲取statement
3、獲取resultset
4、遍歷resultset並封裝成集合
5、依次關閉connection,statement,resultset,而且還要考慮各種異常
6、.....
這時候,使用模板模式的時機到了!!!
通過觀察我們發現上面步驟中大多數都是重複的,可複用的,只有在遍歷ResultSet並封裝成集合的這一步驟是可定製的,因為每張表都對映不同的java bean。這部分程式碼是沒有辦法複用的,只能定製。那就讓我們用一個抽象的父類把它們封裝一下吧:
Java程式碼
- public abstract class JdbcTemplate {
- //template method
- public final Object execute(String sql) throws SQLException{
- Connection con = HsqldbUtil.getConnection();
- Statement stmt = null;
- try {
- stmt = con.createStatement();
- ResultSet rs = stmt.executeQuery(sql);
- Object result = doInStatement(rs);//abstract method
- return result;
- }
- catch (SQLException ex) {
- ex.printStackTrace();
- throw ex;
- }
- finally {
- try {
- stmt.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- try {
-
相關推薦
spring原始碼解讀之 JdbcTemplate原始碼
在Spring中,JdbcTemplate是經常被使用的類來幫助使用者程式操作資料庫,在JdbcTemplate為使用者程式提供了許多便利的資料庫操作方法,比如查詢,更新等,而且在Spring中,有許多類似 JdbcTemplate的模板,比如HibernateT
Spring原始碼解讀之核心容器上節
Spring架構圖 說明 Spring的流行程度就不用我來說了,相信大家如果使用JAVA開發就一定知道它。寫這篇文章的初衷在於:1.瞭解Spring底層實現原理,提升對Spring的認識與理解。2.學習優秀框架程式設計實現,學習優秀的設計模式。3.使用Spring三年多,對於底層細節希望知道更多,便於
Spring原始碼解讀之核心容器下節
續 上一篇我們通過ClassPathXmlApplicationContext載入xml檔案,通過BeanFactory獲取例項bean的demo程式碼去解讀了Spring Core Container中的spring-beans,spring-core,spring-context三個元件之間的一些具體類
Spring原始碼解讀之Spring MVC HandlerMapping元件(二)
一、HandlerMapping HandlerMapping作用是根據request找到相應的處理器Handler和Interceptors,並將Handler和Interceptors封裝成HandlerExecutionChain 物件返回。Handler
Spring原始碼解讀之——bean的生命週期(隨筆)
bean建立---初始化----銷燬的過程 容器管理bean的生命週期; 我們可以自定義初始化和銷燬方法;容器在bean進行到當前生命週期的時候來呼叫我們自定義的初始化和銷燬方法 構造(物件建立) 單例項:在容器啟動的時候建立物件 多例項:在每次獲取的時
Spring原始碼解讀之——元件註冊(隨筆)
@ComponentScan value:指定要掃描的包 excludeFilters = Filter[] :指定掃描的時候按照什麼規則排除那些元件 includeFilters = Filt
spring beans原始碼解讀之 ioc容器之始祖--DefaultListableBeanFactory
spring Ioc容器的實現,從根源上是beanfactory,但真正可以作為一個可以獨立使用的ioc容器還是DefaultListableBeanFactory,因此可以這麼說, DefaultListableBeanFactory 是整個spring ioc的始祖,研究透它
Spring原始碼解讀之——自動裝配(隨筆)
Spring利用依賴注入(DI),完成對IOC容器中中各個元件的依賴關係賦值; 1、@Autowired:自動注入: 1)、預設優先按照型別去容器中找對應的元件:applicationContext.getBean(BookDao.class);找到就賦值
spring beans原始碼解讀之--bean definiton解析器
spring提供了有兩種方式的bean definition解析器:PropertiesBeanDefinitionReader和XmLBeanDefinitionReader即屬性檔案格式的bean definition解析器和xml檔案格式的bean definition解析器。 我們先從簡單的Prop
spring beans原始碼解讀之--Bean的註解(annotation)
隨著spring註解的引入,越來越多的開發者開始使用註解,這篇文章將對註解的機制進行串聯式的講解,不求深入透徹,但求串起spring beans註解的珍珠,展示給大家。 1. spring beans常用的註解: public @interface Autowired:可以對成員變數、方法和建構函式進
spring beans原始碼解讀之--總結篇
spring beans下面有如下原始檔包: org.springframework.beans, 包含了操作java bean的介面和類。org.springframework.beans.annotation, 支援包,提供對java 5註解處理bean樣式的支援。org.springframework
spring beans原始碼解讀之--Bean的定義及包裝
bean的定義,包裝是java bean的基礎。再怎麼強調它的重要性都不為過,因此深入 瞭解這塊的程式碼對以後的程式碼研究可以起到事半功倍的功效。 1. Bean的定義BeanDefinition 1.1 BeanDefinition 作用 一個BeanDefinition描述了一個bean的例項,
spring beans原始碼解讀之--XmlBeanFactory
導讀: XmlBeanFactory繼承自DefaultListableBeanFactory,擴充套件了從xml文件中讀取bean definition的能力。從本質上講,XmlBeanFactory等同於DefaultListableBeanFactory+XmlBeanDefinitionReader
Spring原始碼解讀之BeanFactoryPostProcessor的處理
前言 前段時間旁聽了某課堂兩節Spring原始碼解析課,剛好最近自己又在重新學習中,便在這裡記錄一下學習所得。我之前寫過一篇博文,是介紹BeanFactoryPostProcessor跟BeanPostProcessor是如何發揮作用的,當時覺得講的還行,但是現在看來,太粗劣了,
【1】pytorch torchvision原始碼解讀之Alexnet
最近開始學習一個新的深度學習框架PyTorch。 框架中有一個非常重要且好用的包:torchvision,顧名思義這個包主要是關於計算機視覺cv的。這個包主要由3個子包組成,分別是:torchvision.datasets、torchvision.models、torchvision.trans
java原始碼解讀之HashMap
1:首先下載openjdk(http://pan.baidu.com/s/1dFMZXg1),把原始碼匯入eclipse,以便看到jdk原始碼 Windows-Prefe
PyTorch原始碼解讀之torch.utils.data.DataLoader(轉)
原文連結 https://blog.csdn.net/u014380165/article/details/79058479 寫得特別好!最近正好在學習pytorch,學習一下! PyTorch中資料讀取的一個重要介面是torch.utils.data.DataLoade
PyTorch原始碼解讀之torchvision.models(轉)
原文地址:https://blog.csdn.net/u014380165/article/details/79119664 PyTorch框架中有一個非常重要且好用的包:torchvision,該包主要由3個子包組成,分別是:torchvision.datasets、torchvision.mode
PyTorch原始碼解讀之torchvision.transforms(轉)
原文地址:https://blog.csdn.net/u014380165/article/details/79167753 PyTorch框架中有一個非常重要且好用的包:torchvision,該包主要由3個子包組成,分別是:torchvision.dat
jQuery原始碼解讀之init函式
jQuery的構造方法: // 直接new了一個物件。同時根據jQuery.fn = jQuery.prototype,jQuery.fn相當於jQuery.prototype。 jQuery = function( selector, context ) { return