逝去的青春

勇往直前

2006年3月30日 #

回调函数在Spring中的使用

   这是一种对单个方法的参数使用控制反转,把控制权和差错处理交给框架来处理。严格的说,这是一种Strategy模式的特例,他们的区别就在于接口的复杂度不同。
   在Spring的JdbcTemplate中就使用了这种模式。JdbcTemplate实现了query()方法,参数是SQL字符串,和一个实现了回调接口的,将在读取resultSet每行时被调用。

1 public   interface  RowCallbackHandler 
2 {
3      void  processRow(ResultSet rs)  throws  SQLException;
4 }
 


  query()方法封装了对JDBC底层API的调用。

public   void  query(String sql, RowCallbackHandler callbackHandler)  throws  JdbcSqlException 
{
    Connection con 
=   null ;
    PreparedStatement ps 
=   null ;
    ResultSet rs 
=   null ;
    
try  
    
{
        con 
=   < code to get connection >
        ps 
=  con.prepareStatement (sql);
        rs 
=  ps.executeQuery();
        
while  (rs.next()) 
        
{
            callbackHandler.processRow(rs);
        }

        rs.close();
        ps.close();
    }
 
    
catch  (SQLException ex) 
    
{
        
throw   new  JdbcSqlException( " Couldn't run query [ "   +  sql  +   " ] " , ex);
    }

    
finally  
    
{
        DataSourceUtils.closeConnectionIfNecessary(
this .dataSource, con);
    }

}


   在上面的例子中,JdbcSqlException继承了java.lang.RuntimeException,也就是说调用者可以选择去捕获它,但是这不是必须的。假如实现了回调接口的子类里的方法出错,而且不是RuntimeException的子类,也就是必须捕获的异常,但是query()方法中在逻辑上是没有办法捕获它的。所以Rod_Johnson把接口定义成JdbcTemplate的inner interface。这就可以JdbcTemplate就可以捕获它。
   回调方法也是框架的一种基本方法,比如java.io.File类中的listFiles(FilenameFilter filter),FilenameFilter就是一个接口,我们实现这个接口中的方法accept(File dir, String name) ,这就是一个典型的回调方法。
   观察者模式的使用符合开闭原则,并且分离了关注点。这种对模块修改开发,影响关闭的原则促进了AOP面向方面编程的发展。Spring中的AOP可能就是这种思想的实现,个人猜测而已。    
    把方法的参数放在一个类中,这样以后要增加参数的话,不用修改方法签名,感觉很干净,唯一可能的缺点是可能对性能有所下降,不过很小。如果没有用EJB的话,应该差不多。

   对异常的处理,分为checked和unchecked异常,checked异常是继承java.lang.Exception的。Unchecked异常继承java.lang.RuntimeException。Rod_Johnson主张在对出现异常后,程序不能处理,只能给予没用的提示时用RuntimeException,因为RuntimeException容器会自动处理。关于异常的详细说明,我也没看明白,希望那位大虾能指点指点。

备注:本文主要内容来源于Rod_Johnson的大作,强烈建议看原版!

posted @ 2006-03-30 21:57 逝去的年华 阅读(1448) | 评论 (0)编辑 收藏