最近正在如火如荼的研究spring2中,正在拜读良葛格的大作《Spring2.0 技术手册》。
在看到Spring2.0 的callback-template机制时,一下不是很理解。向baidu求证后,才发现原来Spring2.0 的callback-template机制其实就是template模式和java callback的组合应用,template模式我已然十分熟悉了。那callback机制又是怎么回子事呢,但这次baidu并没有再次给我一个好的答案,在做了一番功课后终于搞明白了callback,也就是回调其实是这个样子的:
java是通过内部类提供闭包的功能来提供回调实现的。
假设现在有一个接口Idosomething,定义了一个methodA()方法
interface Idosomething {
void mehtodA();
}
有一个类A
class A {
void methodA() {
System.out.println("this is methodA");
}
}
有一个类B,继承了类A
class B extends A {
...
}
接口Idosomething和类A都有一个methodA方法,如果类B想实现接口Idosomething的方法的话,就会覆盖类A的methodA方法,那么类B可不可以即实现接口Idosomething的mehtodA方法,又不用覆盖A的methodA方法呢?callback的魅力就在这个地方,修改下类B的代码,
class B extends A {
// 方法myMethodA用来实现实现接口Idosomething的mehtodA方法
private void myMethodA() {
System.out.println(new Date().toString());
}
// 声明一个内部类来实现接口Idosomething
private class Closure implements Idosomething {
public void mehtodA() { myMethodA() ;}
}
// 声明返回内部类的方法
Idosomething getCallBackReference() {
return new Closure();
}
}
class Test {
Idosomething ids;
public static void main(String[] args) {
B b = new B();
// 此处调用的是A类的menthodA方法
b.methodA();
ids = b.getCallBackReference();
// 此处就是类B对接口Idosomething 的实现
ids.methodA();
}
}
此例说明了,通过callback可以更加灵活的实现。
再回过头来看spring中的callback,引用下良葛格的代码:
...
public void insert(User user) {
final string name = user.getName();
final int age = user.getAge().intValue();
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedSatement(Connection conn) throws SQLException {
String sql = "insert into user (name, age) values(?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
ps.setInt(2, age);
return ps;
}
});
}
...
匿名类PreparedStatementCreator就是回调的实现,返回一个PreparedStatementCreator的实例,用来生成SQL文,用比较专业的语言来描述就是在回调接口中实现自己需要的定制行为,值得注意的是,变量name和age的要声明为final的,这样匿名类才能访问。
回调的优点是,代码比较紧凑,回调实现可以使用外围类的变量。
回调的缺点是,如果回调实现是冗长的,那么代码会很难阅读。