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

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的一些常用操作进行了回调封装,可以自己分析下。

分享到:
评论

相关推荐

    spring源码分析(1-10)

    Spring 源代码分析系列涵盖了多个关键模块,包括事务处理、IoC容器、JDBC、MVC、AOP以及与...通过这些深入的源代码分析,我们可以理解Spring框架的内部工作机制,更好地利用它来设计和构建健壮、可维护的Java应用。

    spring-orm源码

    源码分析可以让我们学习到如何在测试环境中配置和使用Spring-ORM。 通过深入研究Spring-ORM的源码,开发者不仅可以提高对Spring框架的理解,还能学习到数据库访问的最佳实践,以及如何高效地集成和使用不同的ORM...

    spring源码分析(一)

    ### Spring源码分析知识点 #### 一、Spring框架概述 Spring框架是一个全面的企业级应用开发框架,它通过一系列模块化的组件来支持不同的应用场景和技术需求。Spring的核心价值在于提供了一种简洁的方式来解决企业...

    spring1.2.6源码

    Spring框架是Java开发中不可或缺的一部分,它以其IoC(Inversion of Control)和AOP(Aspect-Oriented Programming)的核心特性赢得了广泛的认可。版本1.2.6是Spring早期的一个稳定版本,对于初学者和想要深入理解...

    spring源码分析

    在Spring中,事务管理是通过声明式和编程式两种方式实现的。声明式事务管理基于XML配置或注解,使得开发者无需编写繁琐的事务控制代码,大大提高了开发效率。在源码中,我们可以看到`PlatformTransactionManager`...

    Spring_2000_Spring_Hibernate_HibernateTemplate

    标题中的"Spring_2000_Spring_Hibernate_HibernateTemplate"显然指的是一个关于Spring框架、Hibernate ORM框架以及其在2000年左右的版本或应用方式的专题。在这个主题下,我们将深入探讨Spring框架的核心特性,以及...

    Spring_Spring_Hibernate_HibernateTemplate

    在Java企业级开发中,Spring框架和Hibernate持久层框架的结合使用是常见的技术选型。本篇将深入探讨Spring与Hibernate的集成,特别是Spring提供的HibernateTemplate,它是Spring对Hibernate的一种封装,简化了数据库...

    Spring+hibernate整合源代码

    Spring 和 Hibernate 是两个非常重要的 Java 开发框架,它们在企业级应用开发中有着广泛的应用。Spring 是一个全面的后端应用程序框架,提供了依赖注入、面向切面编程、数据访问、事务管理等多种功能。Hibernate 则...

    深入分析Spring源码.docx

    本篇将详细探讨Spring中运用的设计模式及其重要性。 首先,Spring框架中广泛应用了23种经典设计模式,如工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式等。这些模式在Spring中起到了关键作用,使得...

    java+Spring+Hibernate整合的企业OA源码

    【标题】"java+Spring+Hibernate整合的企业OA源码"所代表的是一个使用Java编程语言,结合Spring框架和Hibernate持久层框架实现的企业级办公自动化(Office Automation,简称OA)系统的源代码。这样的系统通常用于...

    跟我学spring3-源码.

    《跟我学Spring3-源码》教程是一份深入解析Spring框架3.x版本核心源码的教育资源,适合对Java和J2EE技术有一定基础的开发者学习。本教程旨在帮助读者理解Spring框架的工作原理,提高在实际项目中的应用能力。通过...

    一个模拟Spring将SessionFactory注入到HibernateTemplate的小例子

    4. **源码分析**:通过阅读Spring和Hibernate的相关源码,我们可以更深入地理解这两个库是如何协同工作的。SessionFactory的创建过程、HibernateTemplate的内部实现,以及DI的原理等,都是值得研究的部分。 在...

    spring源码分析免费资源

    Spring框架是Java开发中最常用的轻量级开源框架之一,它以其IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为核心特性,极大地简化了企业级应用的开发。在对Spring进行...

    Spring,Hibernate整合源码

    源码分析通常涉及对配置文件的理解,如Spring的beans.xml和Hibernate的hibernate.cfg.xml,以及相关类的设计和交互。此外,还可以通过源码学习到如何处理异常、优化数据库操作,以及如何设计符合松耦合原则的架构。

    spring hibernatetemplate

    但是,如果在`HibernateTemplate`的`execute`方法中手动调用了`session.flush()`,那么这个事务就会被立即提交,而不是等待整个回调方法执行完毕。因此,如果需要确保多个操作都在同一个事务中,开发者需要自己控制...

    精通spring(及源码)

    《精通Spring(及源码)》是一本深度探讨Spring框架及其源码的书籍,旨在帮助读者全面理解Spring的核心机制,并能深入源码层面进行学习和分析。Spring作为Java企业级应用开发的重要框架,其强大的功能和灵活性使得它在...

    spring2.0宝典源码

    总之,《Spring2.0宝典》中的源码分析涵盖了Spring框架的核心特性,包括IoC、AOP、事务管理、数据访问和MVC,以及测试支持。通过学习这些源码,开发者可以深入了解Spring的工作原理,提升框架的使用技巧,从而在实际...

    spring java

    《Spring Java深度解析:源码、小项目与Hibernate整合》 Spring框架作为Java开发中的核心组件,以其强大的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)特性,极大地简化了企业级应用的开发。...

    spring入门笔记源码

    通过分析这些源码,我们可以更好地理解 Spring 框架的工作原理,并将所学应用到实际项目中。 学习过程中,推荐结合官方文档、教程以及在线资源,以便深入理解每个概念。同时,动手实践是学习编程的最好方式,尝试...

    HibernateTemplate详细描述以及使用范围

    通过本文的介绍,我们可以了解到`HibernateTemplate`在Spring框架中的重要地位及其应用场景。它不仅简化了Hibernate的使用,还提供了一套完善的API用于处理常见的数据库操作。此外,通过与Spring框架的良好集成,`...

Global site tag (gtag.js) - Google Analytics