好久没更新博客了,每天忙着接收新知识,博客好久没更新了。今天从新更细起来。


最近看spring源码,发现里面很多回调函数,可小白的我不知道回调是什么,经过多方查询,现在终于明白了,再看hibernatetemplete,感觉明朗了许多。下面附上个人理解。


由于本人还在努力着想着大神迈进,所以对于目前菜鸟的我,水平有限,大神勿笑。


对于一件事情的认识,我喜欢和另一件事情对比加以理解。那么,什么是回调呢?首先看看:回调,同步和异步的区别


               例如:同步:Class A ------------------>class B   类A 中的一个方法,调用类B中的一个方法,而且必须等待类B中的方法返回结果后类A中的方法才能向下走,这便是同步,同步在我们的代码中用的最多,我们经常用到,但我们也许没有在意。


异步: 一种类似消息或事件的机制。 不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。


举个例子:用户需要把相片上传至某个服务器A上,然后服务器A把他们的照片取出并传送到另一台服务器B上进行审批,若没有通过则通知对方。其中用户上传和审批没有阻塞关系,但当审批不通过时,则需要调用A的方法通知对方。


一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;


spring回调 spring异步回调_sql




下边结合一个例子说明下:

<span style="background-color: rgb(153, 153, 153);"><span style="color:#ffffff;"></span></span>
//这是我们最传统的方式,加载驱动,建立连接,设置参数,执行查询,重复性操作太多,那么,我们能不能简化?
public void update(User user){
	String sql="update user set pwd = ? where name = ?";
Connection connection=ConnectionUtil.getConnection();
try {
	PreparedStatement statement=connection.prepareStatement(sql);
	statement.setString(1, "小明");
	statement.setString(2, "123456");
	statement.executeQuery();
} catch (SQLException e) {
	try {
		connection.rollback();
	} catch (SQLException e1) {
		e1.printStackTrace();
	}
	e.printStackTrace();
}finally{
	try {
		connection.commit();
	} catch (SQLException e) {
		e.printStackTrace();
	}
	ConnectionUtil.close(connection);
}
}



简化一下:


public final Object execute(String sql){
	Connection connection=ConnectionUtil.getConnection();
	try {
		PreparedStatement statement=connection.prepareStatement(sql);
	  Object result= doinstatement(statement);//由子类去实现
	  return result;
	} catch (SQLException e) {
		e.printStackTrace();
	}finally{
		ConnectionUtil.close(connection);
	}
	return null;
}
public abstract Object doinstatement(PreparedStatement statement)throws SQLException;
}

子类代码:


public class JdbcTemeteInpl extends JdbcTemete {
	@Override
	public Object doinstatement(PreparedStatement statement) throws SQLException {
		// 
		statement.setString(1, "小明");
		statement.executeQuery();
		return null;
	}

}

怎么调用呢?


JdbcTemete jdbcTemete=new JdbcTemeteInpl();
		jdbcTemete.execute("select * from user where name = ?");
	}

这样,我们把查询的方法抽取成了一个模板, 但是这还不简便,每次查询要继承一次模板,能不能再简便点呢?


我们把 doinstatement()抽取到一个方法里面,变这样:


public abstract class JdbcCollBack {                         //我们把它叫做类B 
public abstract Object  doinstatement(PreparedStatement statement)throws SQLException;
}

然后模板这样一个方法:


public Object doexecute(JdbcCollBack collBack) throws SQLException{  //这个是模板的方法,叫类A中的方法 在这个方法中需要调用B的方法
	Object result=collBack.doinstatement(getStatement());//但是在这里,需要传个参数,这个参数调用了类A中的方法
	return result;
}

这样不好看,我们再封装,我们习惯用query


public Object query(JdbcCollBack collBack) throws SQLException{
	return doexecute(collBack);
}

此时的查询,这样:



public Object get(String sql,final String name) throws SQLException{
	JDBCTemete.sql = sql;
	connection=ConnectionUtil.getConnection();
     return query(new JdbcCollBack() {
		@Override
		public Object doinstatement(PreparedStatement statement)
				throws SQLException {
			statement.setString(1, name);
		ResultSet resultSet=	statement.executeQuery();
		while(resultSet.next()){
			String nameString=resultSet.getString("name");
			String passwString=resultSet.getString("pwd");
			User user=new User(nameString, passwString);
			return user;
		}
			return null;
		}
	});
}

这样,我们就可以自己写find load update 等,只要return 

query(new JdbcCollBack());这是个匿名内部类回调

这怎么回事呢?


类A中的方法: doexecute(JdbcCollBack collBack) 需要类B,然后调用B 的方法--- collBack.doinstatement(getStatement()),即A调B


类B 中的 doinstatement(PreparedStatement statement)方法需要一个参数PreparedStatement ,这个参数由类A中的方法提供。B调用A


这样对PreparedStatement 的管理由交给了类A,这样就是回调。这是面向对象的回调,对于面向过程的回调,本人菜鸟一个不知道。



最后,我们来理解HibernateTemplate的原理:


HibernateTemplate:有一个很重要的方法:protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)


下面看看怎么回事:


HibernateTemplate,我们用的较多的execute():


public Object execute(HibernateCallback action)
        throws DataAccessException
    {
        return doExecute(action, false, false);//这里调用了<span style="font-family: Arial;">doExecute方法</span>

    }

然后看看 

doExecute方法源码:

这是个模板方法:


protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)
         throws DataAccessException
     {
         org.hibernate.Session session;
         boolean existingTransaction;
         FlushMode previousFlushMode;
         Assert.notNull(action, "Callback object must not be null");
         session = enforceNewSession ? SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession();
         existingTransaction = !enforceNewSession && (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory()));
         if(existingTransaction)
             logger.debug("Found thread-bound Session for HibernateTemplate");
         previousFlushMode = null;
         Object obj;
         try
         {
             previousFlushMode = applyFlushMode(session, existingTransaction);
             enableFilters(session); 
//session代理
             org.hibernate.Session sessionToExpose = !enforceNativeSession && !isExposeNativeSession() ? createSessionProxy(session) : session;
           //  
   Object result = action.doInHibernate(sessionToExpose);
             flushIfNecessary(session, existingTransaction);
             obj = result;
         }
         catch(HibernateException ex)
         {
             throw convertHibernateAccessException(ex);
         }
         catch(SQLException ex)
         {
             throw convertJdbcAccessException(ex);
         }
         catch(RuntimeException ex)
         {
             throw ex;
         }
         if(existingTransaction)
         {
             logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
             disableFilters(session);
             if(previousFlushMode != null)
                 session.setFlushMode(previousFlushMode);
         } else
         if(isAlwaysUseNewSession())
             SessionFactoryUtils.closeSession(session);
         else
             SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
         return obj;
         Exception exception;
         exception;
         if(existingTransaction)
         {
             logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
             disableFilters(session);
             if(previousFlushMode != null)
                 session.setFlushMode(previousFlushMode);
         } else
         if(isAlwaysUseNewSession())
             SessionFactoryUtils.closeSession(session);
         else 
//关闭session 用hibernateTemelete不用关闭session
             SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
         throw exception;
     }



hibernate 中还有get load find 方法,他们是如何实现的呢?


以get为例:调用 executeWithNativeSession()方法,


public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)
        throws DataAccessException
    {
        return executeWithNativeSession(new HibernateCallback() {

            public Object doInHibernate(org.hibernate.Session session)
                throws HibernateException
            {
                if(lockMode != null)
                    return session.get(entityClass, id, lockMode);
                else
                    return session.get(entityClass, id);
            }

然后看看这个方法:


结果还是调用 doExecute()方法


public Object executeWithNativeSession(HibernateCallback action)
    {
        return doExecute(action, false, true);
    }

可以看出,HibernateTemplate 中的核心方法是 

doExecute 其他方法都调用这个方法,不过提供了不同的封装,而且session的管理由HibernateTemplate 来完成,对于session的开启,事物的提交,都有一个默认的设置。

由于我没有看清  executeWithNativeSession()让我纠结模板里面的get,find load 方法中的 doInHibernate(Session session)里面的session是谁传来的,现在终于清楚了。




好了到这里就结束了,每天进步一点点