Spring中 Callback模式和Template模式合用 随处可见。下面以常用的HibernateTemplate为例进行简要简述。 由于java的JDBC的开发过程中有许多步骤是固定的(建立连接,执行操作,释放连接),因此spring采用模板方法对JDBC开发进行改进。模板方法定义过程的架构,一般是在一个抽象类中定义某个操作的一系列过程,将这一系列的过程中的变化部分以抽象方法的形式给出,子类在进行这个操作时,只需要继承该抽象类,重写该抽象方法即可。代码如下: Java代码 1. public abstract class Ope{ 2. //public final void step1(){..} 3. public abstract void step2(); 4. //public final void step3(){…} 5. 6. } 7. 8. public class MyOpe { 9. //public void step2(){…} 10. public final void execute(Ope ope){ 11. step1(); 12. ope.step2(); 13. step3(); 14. } 15. } Save (){ step1(); fdsakl;fasdkl step3(); execute (new Ope(){ Public void step2(){ …………………… } }){ ) } Save (){ execute (new Ope(){ Public void step2(){ fdjkasjfasdjklfjlasd } }){ ) } 这样,每一个具体的操作只需要实现step2()方法即可。 但是如果仅仅采用模板方法,就意味着每次进行增删改查操作,都需要继承某个类,在java开发中通常会频繁操作数据库,这种方法会显得十分的不方便。通常我们利用HibernateTemplate进行数据库操作时,是采用类似ht.save(…)的方式,在一个模板类中实现了所有的方法,而这其中用到了Callback模式。在HibernateTemplate模板类中有一个核心的方法,这个核心的方法完成相关的流程操作,其中的具体步骤通过回调传入的对象来完成(这个对象就是实现了Callback接口的类)。该类中的其它的方法(如save,update等)会通过Callback模式,调用这个核心的方法实现来完成最终的操作。这样就不需要实现多个类,只需在一个模板类中就可以完成全部的方法定义。 HibernateCallback接口的代码如下: Java代码 1. public interface HibernateCallback<T> { 2. T doInHibernate(Session session) throws HibernateException, SQLException; 3. } 它只有一个方法doInHibernate 。HibernateTemplate中的方法,如save(),update()的具体实现都采用匿名类的方式实现了该接口,在doInHibernate中完成具体的操作。以save()方法为例: Java代码 1. public Serializable save(final Object entity) throws DataAccessException { 2. return executeWithNativeSession(new HibernateCallback<Serializable>() { 3. public Serializable doInHibernate(Session session) 4. throws HibernateException { 5. checkWriteOperationAllowed(session); 6. return session.save(entity); 7. } 8. }); 9. } save方法在doInHibernate方法中完成了session.save(entity)完成保存操作,而executeWithNativeSession方法可以看做是HibernateTemplate中的核心方法(它内部调用了doExecute()方法,doExecute()方法才是真正的核心方法,它完成了一系列操作) Java代码 1. protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession) 2. throws DataAccessException { 3. 4. Assert.notNull(action, "Callback object must not be null"); 5. 6. Session session = (enforceNewSession ? 7. SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession()); 8. boolean existingTransaction = (!enforceNewSession && 9. (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory()))); 10. if (existingTransaction) { 11. logger.debug("Found thread-bound Session for HibernateTemplate"); 12. } 13. 14. FlushMode previousFlushMode = null; 15. try { 16. previousFlushMode = applyFlushMode(session, existingTransaction); 17. enableFilters(session); 18. Session sessionToExpose = 19. (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); 20. T result = action.doInHibernate(sessionToExpose); 21. flushIfNecessary(session, existingTransaction); 22. return result; 23. } 24. catch (HibernateException ex) { 25. throw convertHibernateAccessException(ex); 26. } 27. catch (SQLException ex) { 28. throw convertJdbcAccessException(ex); 29. } 30. catch (RuntimeException ex) { 31. // Callback code threw application exception... 32. throw ex; 33. } 34. finally { 35. if (existingTransaction) { 36. logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate"); 37. disableFilters(session); 38. if (previousFlushMode != null) { 39. session.setFlushMode(previousFlushMode); 40. } 41. } 42. else { 43. // Never use deferred close for an explicitly new Session. 44. if (isAlwaysUseNewSession()) { 45. SessionFactoryUtils.closeSession(session); 46. } 47. else { 48. SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory()); 49. } 50. } 51. } 52. } spring中的JdbcTemplate等都采用了相同的方法。