淺析java callback 回調模式

看過spring、hibernate源碼的朋友對callback回調模式應該並不陌生,用一句話來概括就是:“if you call me, i will call back”,說白了,就是有相互依賴關係的兩個類之間的互相調用,現在看看下面的代碼模型:

Java代碼
  1. package com.cuishen.callback;  
  2.   
  3. public class Context implements A.Callback {  
  4.   
  5.     private A a;  
  6.       
  7.     public void begin() {  
  8.         System.out.println("begin ...");  
  9.     }  
  10.   
  11.     public void end() {  
  12.         System.out.println("end ...");  
  13.     }  
  14.       
  15.     public Context() {  
  16.         this.a = new A(this);  
  17.     }  
  18.       
  19.     public void doSomething() {  
  20.         this.a.doIt();  
  21.     }  
  22.       
  23.     public static void main(String args[]) {  
  24.         new Context().doSomething();  
  25.     }  
  26. }  
  27.   
  28.   
  29. package com.cuishen.callback;  
  30.   
  31. public class A {  
  32.       
  33.     private final Callback callback;  
  34.       
  35.     public static interface Callback {  
  36.         public void begin();  
  37.         public void end();  
  38.     }  
  39.     public A(Callback callback) {  
  40.         this.callback = callback;  
  41.     }  
  42.     public void doIt() {  
  43.         callback.begin();  
  44.         System.out.println("do something ...");  
  45.         callback.end();  
  46.     }  
  47. }  


上面的代碼模型其原型是出自hibernate裏的org.hibernate.jdbc.JDBCContext 和 org.hibernate.jdbc.ConnectionManager兩個類,從上面的模型不難看出:Context類實現了A類的Callback接口,在Context類的構造器裏將自己注入了A類,在Context類裏調用A類的doIt()方法,這時就是:you call me;在doIt()方法體裏調用了Context類的begin()和end()方法,這時就是:i call back。Context類 和 A類相互依賴,互相調用

在hibernate的源代碼裏大量使用了上面的callback回調模型,又如:org.hibernate.jdbc.JDBCContext 和 org.hibernate.impl.SessionImpl等等,可以自己去看源代碼,這裏不再贅述。

當然上面提到的模型中的兩個類也可以寫在同一個類裏面,定義的Callback接口可以用內部匿名類來實現,比如下面的一個簡單的dao實現:

Java代碼
  1. package com.cuishen.callback;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5. import java.sql.SQLException;  
  6.   
  7. public class Dao {  
  8.     private interface Callback {  
  9.         Object doIt(Connection conn) throws SQLException;  
  10.     }  
  11.     private Object execute(Callback callback) throws SQLException {  
  12.         Connection conn = openConnection(); // 開啓數據庫連接  
  13.         try { return callback.doIt(conn); } // 執行具體操作並返回操作結果  
  14.         finally { closeConnection(conn); } // 關閉數據庫連接  
  15.     }  
  16.       
  17.     public Object sqlQuery(final String sql) throws SQLException {  
  18.         return execute(  
  19.             new Callback() {  
  20.                 public Object doIt(Connection conn) throws SQLException {  
  21.                     return conn.createStatement().executeQuery(sql);  
  22.                 }  
  23.             }  
  24.         );  
  25.     }  
  26.       
  27.     public Connection openConnection() throws SQLException {  
  28.         return DriverManager.getConnection(""null);  
  29.     }  
  30.     public void closeConnection(Connection conn) throws SQLException {  
  31.         if(conn != null && !conn.isClosed()) {  
  32.             conn.close();  
  33.         }  
  34.     }  
  35. }  


用這種回調模式方便的把openConnection()和closeConnection()做了切片,從代碼中剝離出來,使代碼複用性更高,也更簡潔
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章