回调函数在Spring中的使用

本文解析了Spring框架中JdbcTemplate的回调模式,介绍了如何通过RowCallbackHandler接口实现数据库查询逻辑,探讨了该模式如何简化JDBC操作并提高代码的可维护性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  这是一种对单个方法的参数使用控制反转,把控制权和差错处理交给框架来处理。严格的说,这是一种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的大作,强烈建议看原版!

### 关于Spring框架中的回调函数Spring框架中,回调机制被广泛应用于各种场景。通过接口定义抽象行为,并允许具体的实现类提供具体的行为逻辑。 #### 使用`ApplicationListener`作为事件监听器 一种常见的回调方式是在应用程序上下文中注册事件监听器。当特定类型的事件发生时,会自动调用这些监听器的方法: ```java @Component public class MyEventListener implements ApplicationListener<MyEvent> { @Override public void onApplicationEvent(MyEvent event) { System.out.println("Received custom event: " + event.getMessage()); } } ``` 此类实现了`ApplicationListener<T>`接口并重写了`onApplicationEvent()`方法,在该方法内部可以处理接收到的事件实例[^1]。 #### 利用`SmartLifecycle`管理组件生命周期 对于希望控制其启动和关闭过程的服务组件来说,可以通过继承自`SmartLifecycle`来设置回调钩子: ```java @Component public class MyService implements SmartLifecycle { private volatile boolean running = false; @Override public void start() { // 启动服务所需的初始化操作 running = true; } @Override public void stop() { // 停止服务前执行清理工作 running = false; } @Override public boolean isRunning() { return running; } } ``` 这里定义了一个名为MyService的服务bean,它会在容器刷新完成后由Spring自动调用start()方法完成必要的准备工作;同样地,在销毁之前也会触发stop()[^2]。 #### 结合AOP切面编程技术 面向方面编程(Aspect-Oriented Programming,AOP)也是实现回调的一种有效手段之一。借助@AfterReturning,@Around等注解可以在目标方法前后插入额外的功能模块: ```java @Aspect @Configuration public class LoggingAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods(){} @Before("serviceMethods()") public void logBefore(JoinPoint joinPoint){ System.out.println("Method Name : "+joinPoint.getSignature().getName()); } @AfterReturning(pointcut="serviceMethods()", returning="result") public void logAfterReturning(Object result){ System.out.println("Return Value :"+result); } } ``` 上述代码片段展示了如何利用AOP特性拦截指定包下的所有业务层方法,并在其执行前后打印日志信息[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值