1. 程式人生 > >spring原始碼解讀之 JdbcTemplate原始碼

spring原始碼解讀之 JdbcTemplate原始碼

    在Spring中,JdbcTemplate是經常被使用的類來幫助使用者程式操作資料庫,在JdbcTemplate為使用者程式提供了許多便利的資料庫操作方法,比如查詢,更新等,而且在Spring中,有許多類似 JdbcTemplate的模板,比如HibernateTemplate等等 - 看來這是Rod.Johnson的慣用手法,

    所謂模板板式,就是在父類中定義演算法的主要流程,而把一些個性化的步驟延遲到子類中去實現,父類始終控制著整個流程的主動權,子類只是輔助父類實現某些可定製的步驟。

我們用程式碼來說話吧: 
首先,父類要是個抽象類: 

Java程式碼  收藏程式碼
  1. public abstract class TemplatePattern {  
  2.     //模板方法  
  3.     public final void templateMethod(){  
  4.         method1();  
  5.         method2();//勾子方法  
  6.         method3();//抽象方法  
  7.     }  
  8.     private void method1(){  
  9.         System.out.println("父類實現業務邏輯");  
  10.     }  
  11.     public void method2(){  
  12.         System.out.println("父類預設實現,子類可覆蓋");  
  13.     }  
  14.     protected abstract void method3();//子類負責實現業務邏輯  
  15. }  


父類中有三個方法,分別是method1(),method2()和method3()。 
method1()是私有方法,有且只能由父類實現邏輯,由於方法是private的,所以只能父類呼叫。 
method2()是所謂的勾子方法。父類提供預設實現,如果子類覺得有必要定製,則可以覆蓋父類的預設實現。 
method3()是子類必須實現的方法,即制定的步驟。 

由此可看出,演算法的流程執行順序是由父類掌控的,子類只能配合。

下面我們來寫第一個子類: 

Java程式碼  收藏程式碼
  1. public class TemplatePatternImpl extends TemplatePattern {  
  2.     @Override  
  3.     protected void method3() {  
  4.         System.out.println("method3()在子類TemplatePatternImpl中實現了!!");  
  5.     }  
  6. }  

這個子類只覆蓋了必須覆蓋的方法,我們來測試一下: 
Java程式碼  收藏程式碼
  1. TemplatePattern t1 = new TemplatePatternImpl();  
  2. t1.templateMethod();  

在控制檯中我們可以看到: 
Java程式碼  收藏程式碼
  1. 父類實現業務邏輯  
  2. 父類預設實現,子類可覆蓋  
  3. method3()在子類TemplatePatternImpl中實現了!!  


OK,我們來看看勾子方法的使用: 
定義第2個子類,實現勾子方法: 

Java程式碼  收藏程式碼
  1. public class TemplatePatternImpl2 extends TemplatePattern {  
  2.     @Override  
  3.     protected void method3() {  
  4.         System.out.println("method3()在子類TemplatePatternImpl2中實現了!!");  
  5.     }  
  6.     /* (non-Javadoc) 
  7.      * @see com.jak.pattern.template.example.TemplatePattern#method2() 
  8.      */  
  9.     @Override  
  10.     public void method2() {  
  11.         System.out.println("子類TemplatePatternImpl2覆蓋了父類的method2()方法!!");  
  12.     }  
  13. }  


來測試一下: 
Java程式碼  收藏程式碼
  1. TemplatePattern t2 = new TemplatePatternImpl2();  
  2. t2.templateMethod();  

我們看控制檯: 
Java程式碼  收藏程式碼
  1. 父類實現業務邏輯  
  2. 子類TemplatePatternImpl2覆蓋了父類的method2()方法!!  
  3. method3()在子類TemplatePatternImpl2中實現了!!  


OK,經典的模板模式回顧完了(大家不要拍磚哦~~~~~~~~~~) 

接下來,我們回到正題,自己模仿spring動手寫一個基於模板模式和回撥的jdbcTemplate。 

回顧一下,spring為什麼要封裝JDBC API,對外提供jdbcTemplate呢(不要仍雞蛋啊¥·%¥#%) 
話說SUN的JDBC API也算是經典了,曾經在某個年代折服了一批人。但隨著歷史的發展,純粹的JDBC API已經過於底層,而且不易控制,由開發人員直接接觸JDBC API,會造成不可預知的風險。還有,資料連線快取池的發展,也不可能讓開發人員去手工獲取JDBC了。 

好了,我們來看一段曾經堪稱經典的JDBC API程式碼吧: 

Java程式碼  收藏程式碼
  1. public List<User> query() {  
  2.     List<User> userList = new ArrayList<User>();  
  3.     String sql = "select * from User";  
  4.     Connection con = null;  
  5.     PreparedStatement pst = null;  
  6.     ResultSet rs = null;  
  7.     try {  
  8.         con = HsqldbUtil.getConnection();  
  9.         pst = con.prepareStatement(sql);  
  10.         rs = pst.executeQuery();  
  11.         User user = null;  
  12.         while (rs.next()) {  
  13.             user = new User();  
  14.             user.setId(rs.getInt("id"));  
  15.             user.setUserName(rs.getString("user_name"));  
  16.             user.setBirth(rs.getDate("birth"));  
  17.             user.setCreateDate(rs.getDate("create_date"));  
  18.             userList.add(user);  
  19.         }  
  20.     } catch (SQLException e) {  
  21.         e.printStackTrace();  
  22.     }finally{  
  23.         if(rs != null){  
  24.             try {  
  25.                 rs.close();  
  26.             } catch (SQLException e) {  
  27.                 e.printStackTrace();  
  28.             }  
  29.         }  
  30.         try {  
  31.             pst.close();  
  32.         } catch (SQLException e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.         try {  
  36.             if(!con.isClosed()){  
  37.                 try {  
  38.                     con.close();  
  39.                 } catch (SQLException e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.             }  
  43.         } catch (SQLException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.     }  
  47.     return userList;  
  48. }  


上面的程式碼要若干年前可能是一段十分經典的,還可能被作為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程式碼  收藏程式碼
  1. public abstract class JdbcTemplate {  
  2.     //template method  
  3.     public final Object execute(String sql) throws SQLException{  
  4.         Connection con = HsqldbUtil.getConnection();  
  5.         Statement stmt = null;  
  6.         try {  
  7.             stmt = con.createStatement();  
  8.             ResultSet rs = stmt.executeQuery(sql);  
  9.             Object result = doInStatement(rs);//abstract method   
  10.             return result;  
  11.         }  
  12.         catch (SQLException ex) {  
  13.              ex.printStackTrace();  
  14.              throw ex;  
  15.         }  
  16.         finally {  
  17.             try {  
  18.                 stmt.close();  
  19.             } catch (SQLException e) {  
  20.                 e.printStackTrace();  
  21.             }  
  22.             try {  
  23. 相關推薦

    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