Spring的template与callback模式

来源:互联网 发布:logo软件下载 编辑:程序博客网 时间:2024/05/16 05:24

Spring中 Callback模式和Template模式合用 随处可见。下面以常用的HibernateTemplate为例进行简要简述。
    由于java的JDBC的开发过程中有许多步骤是固定的(建立连接,执行操作,释放连接),因此spring采用模板方法对JDBC开发进行改进。模板方法定义过程的架构,一般是在一个抽象类中定义某个操作的一系列过程,将这一系列的过程中的变化部分以抽象方法的形式给出,子类在进行这个操作时,只需要继承该抽象类,重写该抽象方法即可。代码如下:
    Java代码 
 public abstract class Ope{  
    public final void step1(){..}  
    public abstract  void step2();  
    public final void step3(){…}  
    public final void execute(){  
        step1();  
        step2();  
        step3();  
    }  
}  
 
public class MyOpe extends Ope{  
   public void step2(){…}  
   public final void execute(){  
        step1();  
        step2();  
        step3();  
   }  

 public abstract class Ope{
    public final void step1(){..}
    public abstract  void step2();
    public final void step3(){…}
    public final void execute(){
        step1();
        step2();
        step3();
    }
}

public class MyOpe extends Ope{
   public void step2(){…}
   public final void execute(){
        step1();
        step2();
        step3();
   }
}


这样,每一个具体的操作只需要实现step2()方法即可。

但是如果仅仅采用模板方法,就意味着每次进行增删改查操作,都需要继承某个类,在java开发中通常会频繁操作数据库,这种方法会显得十分的不方便。通常我们利用HibernateTemplate进行数据库操作时,是采用类似ht.save(…)的方式,在一个模板类中实现了所有的方法,而这其中用到了Callback模式。在HibernateTemplate模板类中有一个核心的方法,这个核心的方法完成相关的流程操作,其中的具体步骤通过回调传入的对象来完成(这个对象就是实现了Callback接口的类)。该类中的其它的方法(如save,update等)会通过Callback模式,调用这个核心的方法实现来完成最终的操作。这样就不需要实现多个类,只需在一个模板类中就可以完成全部的方法定义。
    HibernateCallback接口的代码如下:
  Java代码 
public interface HibernateCallback<T> {  
   T doInHibernate(Session session) throws HibernateException, SQLException;  

public interface HibernateCallback<T> {
   T doInHibernate(Session session) throws HibernateException, SQLException;
}

它只有一个方法doInHibernate 。HibernateTemplate中的方法,如save(),update()的具体实现都采用匿名类的方式实现了该接口,在doInHibernate中完成具体的操作。以save()方法为例:
Java代码 
public Serializable save(final Object entity) throws DataAccessException {  
    return executeWithNativeSession(new HibernateCallback<Serializable>() {  
      public Serializable doInHibernate(Session session)   
        throws HibernateException {  
        checkWriteOperationAllowed(session);  
        return session.save(entity);  
            }  
        });  
    } 

public Serializable save(final Object entity) throws DataAccessException {
 return executeWithNativeSession(new HibernateCallback<Serializable>() {
      public Serializable doInHibernate(Session session)
        throws HibernateException {
        checkWriteOperationAllowed(session);
        return session.save(entity);
   }
  });
 }

   save方法在doInHibernate方法中完成了session.save(entity)完成保存操作,而executeWithNativeSession方法可以看做是HibernateTemplate中的核心方法(它内部调用了doExecute()方法,doExecute()方法才是真正的核心方法,它完成了一系列操作)
Java代码 
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)  
            throws DataAccessException {  
 
        Assert.notNull(action, "Callback object must not be null");  
 
        Session session = (enforceNewSession ?  
                SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());  
        boolean existingTransaction = (!enforceNewSession &&  
                (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));  
        if (existingTransaction) {  
            logger.debug("Found thread-bound Session for HibernateTemplate");  
        }  
 
        FlushMode previousFlushMode = null;  
        try {  
            previousFlushMode = applyFlushMode(session, existingTransaction);  
            enableFilters(session);  
            Session sessionToExpose =  
                    (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));  
            T result = action.doInHibernate(sessionToExpose);  
            flushIfNecessary(session, existingTransaction);  
            return result;  
        }  
        catch (HibernateException ex) {  
            throw convertHibernateAccessException(ex);  
        }  
        catch (SQLException ex) {  
            throw convertJdbcAccessException(ex);  
        }  
        catch (RuntimeException ex) {  
            // Callback code threw application exception...  
            throw ex;  
        }  
        finally {  
            if (existingTransaction) {  
                logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");  
                disableFilters(session);  
                if (previousFlushMode != null) {  
                    session.setFlushMode(previousFlushMode);  
                }  
            }  
            else {  
                // Never use deferred close for an explicitly new Session.  
                if (isAlwaysUseNewSession()) {  
                    SessionFactoryUtils.closeSession(session);  
                }  
                else {  
                    SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());  
                }  
            }  
        }  
    } 

原创粉丝点击