日期:2014-05-16  浏览次数:20470 次

模板方法和Callback回调应用实践-自己动手写JdbcTemplate(附源码)
    最近一直在研读spring源码和学习设计模式,想把自己的一些领悟与大家分享,前几天发了几篇简单的文章,可能由于文字过于简单,几次被评为新手贴,心中滴汗啊  没办法,工作太忙,大家都知道,写篇文章是要很大精力地~~~~~

今天恰有时间,把这两天的学习所得与大家分享,尽量写得详细一些,专家饶路走,新手觉得好赞一下(不要拍砖哦~~~~)。
文章源码在附件中

注:本文目的意不在“重复发明轮子”,而是借此文来探讨Spring JdbcTemplate的内部实现原理,掌握其运用精妙之处,以便在以后的“造轮运动”中能灵活运用

话回正转,这两天在读spring的jdbc模板,对Spring源码的精妙真是佩服得五体投地,极为经典。
spring中真是集设计模式之大成,而且用得是炉火纯青。模板方法(template method)就在spring中被大量使用,如:jdbcTemplate,hibernateTemplate,JndiTemplate以及一些包围的包装等都无疑使用了模板模式,但spring并不是单纯使用了模板方法,而是在此基础上做了创新,配合callback(回调)一起使用,用得极其灵活。

OK,为了防止文章再被拍砖,我写得更详细点吧,我们首先来回顾一下模板模式:
所谓模板板式,就是在父类中定义算法的主要流程,而把一些个性化的步骤延迟到子类中去实现,父类始终控制着整个流程的主动权,子类只是辅助父类实现某些可定制的步骤。

有些抽象???
好吧,我们用代码来说话吧:
首先,父类要是个抽象类:
public abstract class TemplatePattern {

	//模板方法
	public final void templateMethod(){
		
		method1();
		method2();//勾子方法
		method3();//抽象方法
	}
	private void method1(){
		System.out.println("父类实现业务逻辑");
	}
	public void method2(){
		System.out.println("父类默认实现,子类可覆盖");
	}
	protected abstract void method3();//子类负责实现业务逻辑
}


父类中有三个方法,分别是method1(),method2()和method3()。
method1()是私有方法,有且只能由父类实现逻辑,由于方法是private的,所以只能父类调用。
method2()是所谓的勾子方法。父类提供默认实现,如果子类觉得有必要定制,则可以覆盖父类的默认实现。
method3()是子类必须实现的方法,即制定的步骤。
由此可看出,算法的流程执行顺序是由父类掌控的,子类只能配合。

下面我们来写第一个子类:
public class TemplatePatternImpl extends TemplatePattern {

	@Override
	protected void method3() {
		System.out.println("method3()在子类TemplatePatternImpl中实现了!!");

	}

}

这个子类只覆盖了必须覆盖的方法,我们来测试一下:
TemplatePattern t1 = new TemplatePatternImpl();
t1.templateMethod();

在控制台中我们可以看到:
父类实现业务逻辑
父类默认实现,子类可覆盖
method3()在子类TemplatePatternImpl中实现了!!


OK,我们来看看勾子方法的使用:
定义第2个子类,实现勾子方法:
public class TemplatePatternImpl2 extends TemplatePattern {

	@Override
	protected void method3() {
		System.out.println("method3()在子类TemplatePatternImpl2中实现了!!");

	}

	/* (non-Javadoc)
	 * @see com.jak.pattern.template.example.TemplatePattern#method2()
	 */
	@Override
	public void method2() {
		System.out.println("子类TemplatePatternImpl2覆盖了父类的method2()方法!!");
	}
	
}


来测试一下:
TemplatePattern t2 = new TemplatePatternImpl2();
t2.templateMethod();

我们看控制台:
父类实现业务逻辑
子类TemplatePatternImpl2覆盖了父类的method2()方法!!
method3()在子类TemplatePatternImpl2中实现了!!


OK,经典的模板模式回顾完了(大家不要拍砖哦~~~~~~~~~~)

接下来,我们回到正题,自己模仿spring动手写一个基于模板模式和回调的jdbcTemplate。

回顾一下,spring为什么要封装JDBC API,对外提供jdbcTemplate呢(不要仍鸡蛋啊¥·%¥#%)
话说SUN的JDBC API也算是经典了,曾经在某个年代折服了一批人。但随着历史的发展,纯粹的JDBC API已经过于底层,而且不易控制,由开发人员直接接触JDBC API,会造成不可预知的风险。还有,数据连接缓存池的发展,也不可能让开发人员去手工获取JDBC了。

好了,我们来看一段曾经堪称经典的JDBC API代码吧:
	public List<User> query() {

		List<User> userList = new ArrayList<User>();
		String sql = "select * from User";

		Connection con = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		try {
			con = HsqldbUtil.getConnection();
			pst = con.prepareStatement(sql);
			rs = pst.executeQuery();

			User user = null;
			while (rs.next()) {

				user = new User();
				user.setId(rs.getInt("id"));
				user.setUserName(rs.getString("user_name"));
				user.setBirth(rs.getDate("birth"));
				user.setCreateDate(rs.getDate("create_date"));
				userList.add(user);
			}


		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(rs != null){
				try {
					rs.clo