浅析java callback 回调模式

来源:互联网 发布:益盟按部就班指标源码 编辑:程序博客网 时间:2024/06/05 08:49
看过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()做了切片,从代码中剥离出来,使代码复用性更高,也更简洁
0 0
原创粉丝点击