`
u011721609
  • 浏览: 40381 次
社区版块
存档分类
最新评论

Java 回调机制及其Spring 中HibernateTemplate的源码分析

 
阅读更多

在分析HibernateTemplate前,首先从网上了解下一些关于回调的一些概念。我相信在了解其原理实现的基础上,可以更好的进行开发和扩展,关键得理解其思想。
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。
同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用。(简单来说就是顺序执行啦。)
回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。(个人觉得有点像模板方法的实现。)
异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。(差不多就是异步执行吧。)
回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。
由于本文章主要关注的是Java 的回调机制,所以其他就不介绍了。下面来看看Java 是怎么来实现回调机制的。

Java代码收藏代码
  1. packagecallback;
  2. /**
  3. *
  4. *@authorzhxing
  5. *@since2010.4.16
  6. *
  7. */
  8. publicclassTest{
  9. privateCallbackcallback;
  10. publicvoidsetCallback(Callbackcallback){
  11. this.callback=callback;
  12. }
  13. //实际方法
  14. publicvoidfoo(){
  15. System.out.println("thisisfoo();");
  16. //在这里调用回调函数
  17. if(callback!=null){
  18. callback.doSomething();
  19. }
  20. }
  21. //测试
  22. publicstaticvoidmain(String[]args){
  23. Testt=newTest();
  24. t.setCallback(newCallback(){
  25. publicvoiddoSomething(){
  26. System.out.println("thisiscallback.");
  27. }
  28. });
  29. t.foo();
  30. }
  31. }
  32. //回调函数
  33. interfaceCallback{
  34. voiddoSomething();
  35. }

一般在我们数据库开发中,都会有打开和关闭数据、捕获异常等的一些固定的操作,写久了也就特别的反感了。是吧。。下面来利用回调简化数据库操作,例子很简单,对于数据的打开和关闭我只做了简单的描述。

Java代码收藏代码
  1. packagecallback;
  2. publicclassUserDao{
  3. privateUserTemplatetemplate=newUserTemplate();
  4. //这个实际上也是用回调方法,不过在UserTemplate进行了封装
  5. publicvoidadd(finalStringname){
  6. this.template.add(name);
  7. }
  8. //这个是用回调方法来实现的
  9. publicStringgetName(){
  10. return(String)this.template.execute(newUserCallback(){
  11. publicObjectdoSomething(){
  12. System.out.println("成功读取数据库。。。name=zhxing");
  13. return"zhxing";
  14. }
  15. });
  16. }
  17. //测试
  18. publicstaticvoidmain(String[]args){
  19. UserDaou=newUserDao();
  20. u.add("zhxing");
  21. System.out.println(u.getName());
  22. }
  23. }
  24. packagecallback;
  25. //回调函数的实现
  26. publicclassUserTemplate{
  27. //调用回调函数,这里是不是有点像模板方法了,呵呵
  28. publicObjectexecute(UserCallbackcallback){
  29. System.out.println("打开数据库连接");
  30. Objecto=callback.doSomething();
  31. System.out.println("关闭数据库连接");
  32. returno;
  33. }
  34. //这里用来简化常用的操作
  35. publicvoidadd(finalStringname){
  36. execute(newUserCallback(){
  37. publicObjectdoSomething(){
  38. System.out.println("name="+name+"成功加入数据库。。。");
  39. returnnull;
  40. }
  41. });
  42. }
  43. }
  44. packagecallback;
  45. //回调函数接口
  46. publicinterfaceUserCallback{
  47. ObjectdoSomething();
  48. }

好了,进入正题吧。。来研究下Spring 中HibernateTemplate 是怎么实现了。。其实上面的那个例子已经可以说明全部了,呵呵。。下面我们按照开发的流程来进行一些源码分析。
当我们用Spring+Hibernate实现Dao层的时候,一般会去继承HibernateDaoSupport这个类。
来分析下这个HibernateDaoSupport类(具体方法细节请查看源码):

Java代码收藏代码
  1. publicabstractclassHibernateDaoSupportextendsDaoSupport{
  2. privateHibernateTemplatehibernateTemplate;
  3. //SettheHibernateSessionFactorytobeusedbythisDAO.
  4. publicfinalvoidsetSessionFactory(SessionFactorysessionFactory){
  5. }
  6. protectedHibernateTemplatecreateHibernateTemplate(SessionFactorysessionFactory){
  7. }
  8. //返回这个HiberanteTemplate中的成员变量SessionFactory
  9. publicfinalSessionFactorygetSessionFactory(){
  10. }
  11. publicfinalvoidsetHibernateTemplate(HibernateTemplatehibernateTemplate){
  12. this.hibernateTemplate=hibernateTemplate;
  13. }
  14. publicfinalHibernateTemplategetHibernateTemplate(){
  15. returnthis.hibernateTemplate;
  16. }
  17. //检查HibernateTemplate是否为空,如果类中的HibernateTemplate未设置则会报错
  18. protectedfinalvoidcheckDaoConfig(){
  19. if(this.hibernateTemplate==null){
  20. thrownewIllegalArgumentException("'sessionFactory'or'hibernateTemplate'isrequired");
  21. }
  22. }
  23. //获得Hibernate中的session,可以在HibernateTemplate中配置是否在Session没创建时新创建一个,在事务处理中很有用
  24. protectedfinalSessiongetSession()
  25. throwsDataAccessResourceFailureException,IllegalStateException{
  26. returngetSession(this.hibernateTemplate.isAllowCreate());
  27. }
  28. //这里是获得Hibernate的session的主要方法
  29. protectedfinalSessiongetSession(booleanallowCreate)
  30. throwsDataAccessResourceFailureException,IllegalStateException{
  31. return(!allowCreate?
  32. SessionFactoryUtils.getSession(getSessionFactory(),false):
  33. SessionFactoryUtils.getSession(
  34. getSessionFactory(),
  35. this.hibernateTemplate.getEntityInterceptor(),
  36. this.hibernateTemplate.getJdbcExceptionTranslator()));
  37. }
  38. //把HibernateException异常转换成DataAccessException异常
  39. protectedfinalDataAccessExceptionconvertHibernateAccessException(HibernateExceptionex){
  40. returnthis.hibernateTemplate.convertHibernateAccessException(ex);
  41. }
  42. //释放Hibernate的session
  43. protectedfinalvoidreleaseSession(Sessionsession){
  44. SessionFactoryUtils.releaseSession(session,getSessionFactory());
  45. }
  46. }

从上面可知道,HibernateDaoSupport 的主要作用是获取Hibernate 的Session (如果直接用HibernateTemplate是没有办法获得Session 的)和管理HibernateTemplate。在Spring 中可以对直接继承该类,然后在Dao 的配置上就可以直接进行注入SessionFactory了,还可以直接从Dao中获取Hibernate的Session进行操作。
现在回到正题,进行分析下HibernateTemplate,先看下他的成员变量有哪些。

Java代码收藏代码
  1. publicclassHibernateTemplateextendsHibernateAccessorimplementsHibernateOperations{
  2. //是否在Session不存在的时候进行创建
  3. privatebooleanallowCreate=true;
  4. //是否每次都生成新的Session
  5. privatebooleanalwaysUseNewSession=false;
  6. //是不是用原生的Hibernate的session而不是用它的代理
  7. privatebooleanexposeNativeSession=false;
  8. //检查Hibernate的session是否为只读模式
  9. privatebooleancheckWriteOperations=true;
  10. //缓存Query
  11. privatebooleancacheQueries=false;
  12. //设置Query缓存的名称
  13. privateStringqueryCacheRegion;
  14. //设置批量获取的大小
  15. privateintfetchSize=0;
  16. //设置最大的数据集
  17. privateintmaxResults=0;
  18. }

HibernateTemplate 封装了很多Hibernate 的原始的操作,但把Hibernate 的session设置为了protected,而不能在它的子类外进行获取。下面来看看我们最常用get 和save 方法。

Java代码收藏代码
  1. publicObjectget(ClassentityClass,Serializableid)throwsDataAccessException{
  2. returnget(entityClass,id,null);
  3. }
  4. //实际get调用这个方法,增加了一个锁模式。
  5. publicObjectget(finalClassentityClass,finalSerializableid,finalLockModelockMode)
  6. throwsDataAccessException{
  7. //这里就是我们上面讨论的回调方法了。。
  8. returnexecuteWithNativeSession(newHibernateCallback(){
  9. publicObjectdoInHibernate(Sessionsession)throwsHibernateException{
  10. if(lockMode!=null){
  11. returnsession.get(entityClass,id,lockMode);
  12. }
  13. else{
  14. returnsession.get(entityClass,id);
  15. }
  16. }
  17. });
  18. }
  19. publicSerializablesave(finalObjectentity)throwsDataAccessException{
  20. //这里也是用了回调,和上面一样的。
  21. return(Serializable)executeWithNativeSession(newHibernateCallback(){
  22. publicObjectdoInHibernate(Sessionsession)throwsHibernateException{
  23. checkWriteOperationAllowed(session);
  24. returnsession.save(entity);
  25. }
  26. });
  27. }

下面来看看这个回调函数的方法。

Java代码收藏代码
  1. protectedObjectdoExecute(HibernateCallbackaction,booleanenforceNewSession,booleanenforceNativeSession)
  2. throwsDataAccessException{
  3. Assert.notNull(action,"Callbackobjectmustnotbenull");
  4. //判断是否强制新建Session
  5. Sessionsession=(enforceNewSession?
  6. SessionFactoryUtils.getNewSession(getSessionFactory(),getEntityInterceptor()):getSession());
  7. //判断是否设置了事务且是否强制新建session
  8. booleanexistingTransaction=(!enforceNewSession&&
  9. (!isAllowCreate()||SessionFactoryUtils.isSessionTransactional(session,getSessionFactory())));
  10. if(existingTransaction){
  11. logger.debug("Foundthread-boundSessionforHibernateTemplate");
  12. }
  13. FlushModepreviousFlushMode=null;
  14. try{
  15. //设置并返回FlushMode
  16. previousFlushMode=applyFlushMode(session,existingTransaction);
  17. //设置过滤器
  18. enableFilters(session);
  19. //是否创建session代理
  20. SessionsessionToExpose=
  21. (enforceNativeSession||isExposeNativeSession()?session:createSessionProxy(session));
  22. //这里调用回调函数了
  23. Objectresult=action.doInHibernate(sessionToExpose);
  24. flushIfNecessary(session,existingTransaction);
  25. returnresult;
  26. }
  27. catch(HibernateExceptionex){
  28. throwconvertHibernateAccessException(ex);
  29. }
  30. catch(SQLExceptionex){
  31. throwconvertJdbcAccessException(ex);
  32. }
  33. catch(RuntimeExceptionex){
  34. //Callbackcodethrewapplicationexception...
  35. throwex;
  36. }
  37. finally{
  38. if(existingTransaction){
  39. logger.debug("Notclosingpre-boundHibernateSessionafterHibernateTemplate");
  40. disableFilters(session);
  41. if(previousFlushMode!=null){
  42. session.setFlushMode(previousFlushMode);
  43. }
  44. }
  45. else{
  46. //NeverusedeferredcloseforanexplicitlynewSession.
  47. if(isAlwaysUseNewSession()){
  48. SessionFactoryUtils.closeSession(session);
  49. }
  50. else{
  51. //把session绑定到线程变量中(ThreadLocal)SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session,getSessionFactory());
  52. }
  53. }
  54. }
  55. }

到这里基本就简单分析完了,关于HibernateTemplate的其他操作,其实都差不多的,对Hibernate的一些常用操作进行了回调封装,可以自己分析下。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics