亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

directory search
前言 簡(jiǎn)介 概覽 使用場(chǎng)景 Spring 2.0和 2.5的新特性 簡(jiǎn)介 控制反轉(zhuǎn)(IoC)容器 新的bean作用域 更簡(jiǎn)單的XML配置 可擴(kuò)展的XML編寫(xiě) Annotation(注解)驅(qū)動(dòng)配置 在classpath中自動(dòng)搜索組件 面向切面編程(AOP) 更加簡(jiǎn)單的AOP XML配置 對(duì)@AspectJ 切面的支持 對(duì)bean命名pointcut( bean name pointcut element)的支持 對(duì)AspectJ裝載時(shí)織入(AspectJ load-time weaving)的支持 中間層 在XML里更為簡(jiǎn)單的聲明性事務(wù)配置 對(duì)Websphere 事務(wù)管理的完整支持 JPA 異步的JMS JDBC Web層 Spring MVC合理的默認(rèn)值 Portlet 框架 基于Annotation的控制器 Spring MVC的表單標(biāo)簽庫(kù) 對(duì)Tiles 2 支持 對(duì)JSF 1.2支持 JAX-WS支持 其他 動(dòng)態(tài)語(yǔ)言支持 增強(qiáng)的測(cè)試支持 JMX 支持 將Spring 應(yīng)用程序上下文部署為JCA adapter 計(jì)劃任務(wù) 對(duì)Java 5 (Tiger) 支持 移植到Spring 2.5 改變 支持的JDK版本 Spring 2.5的Jar打包 XML配置 Deprecated(淘汰)的類(lèi)和方法 Apache OJB iBATIS Hibernate JDO UrlFilenameViewController 更新的樣例應(yīng)用 改進(jìn)的文檔 核心技術(shù) IoC(控制反轉(zhuǎn))容器 簡(jiǎn)介 基本原理 - 容器和bean 容器 配置元數(shù)據(jù) 實(shí)例化容器 XML配置元數(shù)據(jù)的結(jié)構(gòu) 多種bean bean的命名 bean的別名 實(shí)例化bean 用構(gòu)造器來(lái)實(shí)例化 使用靜態(tài)工廠方法實(shí)例化 使用實(shí)例工廠方法實(shí)例化 使用容器 依賴(lài) 注入依賴(lài) 構(gòu)造器注入 構(gòu)造器參數(shù)解析 構(gòu)造器參數(shù)類(lèi)型匹配 構(gòu)造參數(shù)索引 Setter注入 一些例子 依賴(lài)配置詳解 直接變量(基本類(lèi)型、Strings類(lèi)型等。) idref元素 引用其它的bean(協(xié)作者) 內(nèi)部bean 集合 集合的合并 強(qiáng)類(lèi)型集合(僅適用于Java5+) Nulls XML配置文件的簡(jiǎn)寫(xiě)及其他 XML-based configuration metadata shortcuts 使用p名稱(chēng)空間配置屬性 組合屬性名稱(chēng) 使用depends-on 延遲初始化bean 自動(dòng)裝配(autowire)協(xié)作者 將bean排除在自動(dòng)裝配之外 依賴(lài)檢查 方法注入 Lookup方法注入 自定義方法的替代方案 Bean的作用域 Singleton作用域 Prototype作用域 Singleton beans和prototype-bean的依賴(lài) 其他作用域 初始化web配置 Request作用域 Session作用域 global session作用域 作用域bean與依賴(lài) 選擇創(chuàng)建代理的類(lèi)型 自定義作用域 創(chuàng)建自定義作用域 使用自定義作用域 定制bean特性 生命周期回調(diào) 初始化回調(diào) 析構(gòu)回調(diào) 缺省的初始化和析構(gòu)方法 組合生命周期機(jī)制 在非web應(yīng)用中優(yōu)雅地關(guān)閉Spring IoC容器 了解自己 BeanFactoryAware BeanNameAware bean定義的繼承 容器擴(kuò)展點(diǎn) 用BeanPostProcessor定制bean 使用BeanPostProcessor的Hello World示例 RequiredAnnotationBeanPostProcessor示例 用BeanFactoryPostProcessor定制配置元數(shù)據(jù) PropertyPlaceholderConfigurer示例 PropertyOverrideConfigurer示例 使用FactoryBean定制實(shí)例化邏輯 The ApplicationContext BeanFactory 還是 ApplicationContext? 利用MessageSource實(shí)現(xiàn)國(guó)際化 事件 底層資源的訪問(wèn) ApplicationContext在WEB應(yīng)用中的實(shí)例化 粘合代碼和可怕的singleton 以J2EE RAR文件的形式部署Spring ApplicationContext 基于注解(Annotation-based)的配置 @Autowired 基于注解的自動(dòng)連接微調(diào) CustomAutowireConfigurer @Resource @PostConstruct 與 @PreDestroy 對(duì)受管組件的Classpath掃描 @Component和更多典型化注解 自動(dòng)檢測(cè)組件 使用過(guò)濾器自定義掃描 自動(dòng)檢測(cè)組件的命名 為自動(dòng)檢測(cè)的組件提供一個(gè)作用域 用注解提供限定符元數(shù)據(jù) 注冊(cè)一個(gè)LoadTimeWeaver 資源 簡(jiǎn)介 Resource接口 內(nèi)置 Resource 實(shí)現(xiàn) UrlResource ClassPathResource FileSystemResource ServletContextResource InputStreamResource ByteArrayResource ResourceLoader接口 ResourceLoaderAware 接口 把Resource作為屬性來(lái)配置 Application context 和Resource 路徑 構(gòu)造application context 創(chuàng)建 ClassPathXmlApplicationContext 實(shí)例 - 簡(jiǎn)介 Application context構(gòu)造器中資源路徑的通配符 Ant風(fēng)格的pattern 潛在的可移植性 classpath*: 前綴 其他關(guān)于通配符的說(shuō)明 FileSystemResource 說(shuō)明 校驗(yàn),數(shù)據(jù)綁定,BeanWrapper,與屬性編輯器 簡(jiǎn)介 使用Spring的Validator接口進(jìn)行校驗(yàn) 從錯(cuò)誤代碼到錯(cuò)誤信息 Bean處理和BeanWrapper 設(shè)置和獲取屬性值以及嵌套屬性 內(nèi)建的PropertyEditor實(shí)現(xiàn) 注冊(cè)用戶(hù)自定義的PropertyEditor 使用PropertyEditorRegistrars 使用Spring進(jìn)行面向切面編程(AOP) 簡(jiǎn)介 AOP概念 Spring AOP的功能和目標(biāo) AOP代理 @AspectJ支持 啟用@AspectJ支持 聲明一個(gè)切面 聲明一個(gè)切入點(diǎn)(pointcut) 切入點(diǎn)指示符(PCD)的支持 組合切入點(diǎn)表達(dá)式 共享通用切入點(diǎn)定義 示例 聲明通知 前置通知 后置通知(After returning advice) 異常通知(After throwing advice) 最終通知(After (finally) advice) 環(huán)繞通知 通知參數(shù)(Advice parameters) 訪問(wèn)當(dāng)前的連接點(diǎn) 傳遞參數(shù)給通知 確定參數(shù)名 處理參數(shù) 通知順序 引入(Introduction) 切面實(shí)例化模型 例子 基于Schema的AOP支持 聲明一個(gè)切面 聲明一個(gè)切入點(diǎn) 聲明通知 前置通知 后置通知 異常通知 最終通知 環(huán)繞通知 通知參數(shù) 通知順序 引入 切面實(shí)例化模型 Advisor 例子 AOP聲明風(fēng)格的選擇 Spring AOP還是完全用AspectJ? Spring AOP中使用@AspectJ還是XML? 混合切面類(lèi)型 代理機(jī)制 理解AOP代理 以編程方式創(chuàng)建@AspectJ代理 在Spring應(yīng)用中使用AspectJ 在Spring中使用AspectJ進(jìn)行domain object的依賴(lài)注入 @Configurable對(duì)象的單元測(cè)試 Working with multiple application contexts Spring中其他的AspectJ切面 使用Spring IoC來(lái)配置AspectJ的切面 在Spring應(yīng)用中使用AspectJ加載時(shí)織入(LTW) 第一個(gè)例子 切面 'META-INF/aop.xml' 相關(guān)類(lèi)庫(kù)(JARS) Spring配置 特定環(huán)境的配置 通用Java應(yīng)用 Tomcat WebLogic 更多資源 Spring AOP APIs 簡(jiǎn)介 Spring中的切入點(diǎn)API 概念 切入點(diǎn)運(yùn)算 AspectJ切入點(diǎn)表達(dá)式 便利的切入點(diǎn)實(shí)現(xiàn) 靜態(tài)切入點(diǎn) 正則表達(dá)式切入點(diǎn) 屬性驅(qū)動(dòng)的切入點(diǎn) 動(dòng)態(tài)切入點(diǎn) 控制流切入點(diǎn) 切入點(diǎn)的超類(lèi) 自定義切入點(diǎn) Spring的通知API 通知的生命周期 Spring里的通知類(lèi)型 攔截環(huán)繞通知 前置通知 異常通知 后置通知 引入通知 Spring里的Advisor API 使用ProxyFactoryBean創(chuàng)建AOP代理 基礎(chǔ) JavaBean屬性 基于JDK和CGLIB的代理 對(duì)接口進(jìn)行代理 對(duì)類(lèi)進(jìn)行代理 使用“全局”通知器 簡(jiǎn)化代理定義 使用ProxyFactory通過(guò)編程創(chuàng)建AOP代理 操作被通知對(duì)象 使用“自動(dòng)代理(autoproxy)”功能 自動(dòng)代理bean定義 BeanNameAutoProxyCreator DefaultAdvisorAutoProxyCreator AbstractAdvisorAutoProxyCreator 使用元數(shù)據(jù)驅(qū)動(dòng)的自動(dòng)代理 使用TargetSource 熱交換目標(biāo)源 池化目標(biāo)源 原型目標(biāo)源 ThreadLocal目標(biāo)源 定義新的Advice類(lèi)型 更多資源 測(cè)試 簡(jiǎn)介 單元測(cè)試 Mock對(duì)象 JNDI Servlet API Portlet API 單元測(cè)試支持類(lèi) 通用工具類(lèi) Spring MVC 集成測(cè)試 概覽 使用哪個(gè)支持框架 通用目標(biāo) 上下文管理及緩存 測(cè)試fixtures依賴(lài)注入 事務(wù)管理 集成測(cè)試支持類(lèi) JDBC測(cè)試支持 常用注解 JUnit 3.8遺留支持 上下文管理及緩存 測(cè)試fixture依賴(lài)注入 字段級(jí)別(Field Level)注入 事務(wù)管理 JUnit 3.8 遺留支持類(lèi) Java 5+ 專(zhuān)有支持 使用注解的事務(wù)相關(guān)測(cè)試 JPA支持類(lèi) Spring TestContext Framework 主要的抽象 上下文管理和緩存 測(cè)試fixture的依賴(lài)注入 事務(wù)管理 TestContext支持類(lèi) JUnit 3.8支持類(lèi) JUnit 4.4支持類(lèi) 定制JUnit 4.4運(yùn)行器 TestNG支持類(lèi) TestContext框架注解支持 PetClinic示例 更多資源 中間層數(shù)據(jù)訪問(wèn) 事務(wù)管理 簡(jiǎn)介 動(dòng)機(jī) 關(guān)鍵抽象 使用資源同步的事務(wù) 高層次方案 低層次方案 TransactionAwareDataSourceProxy 聲明式事務(wù)管理 理解Spring的聲明式事務(wù)管理實(shí)現(xiàn) 第一個(gè)例子 回滾 為不同的bean配置不同的事務(wù)語(yǔ)義 <tx:advice/> 有關(guān)的設(shè)置 使用 @Transactional @Transactional 有關(guān)的設(shè)置 事務(wù)傳播 required RequiresNew Nested 通知事務(wù)操作 結(jié)合AspectJ使用 @Transactional 編程式事務(wù)管理 使用TransactionTemplate 指定事務(wù)設(shè)置 使用PlatformTransactionManager 選擇編程式事務(wù)管理還是聲明式事務(wù)管理 與特定應(yīng)用服務(wù)器集成 IBM WebSphere BEA WebLogic Oracle OC4J 常見(jiàn)問(wèn)題的解決方法 對(duì)一個(gè)特定的 DataSource 使用了錯(cuò)誤的事務(wù)管理器 更多的資源 DAO支持 簡(jiǎn)介 一致的異常層次 一致的DAO支持抽象類(lèi) 使用JDBC進(jìn)行數(shù)據(jù)訪問(wèn) 簡(jiǎn)介 選擇一種工作模式 Spring JDBC包結(jié)構(gòu) 利用JDBC核心類(lèi)控制JDBC的基本操作和錯(cuò)誤處理 JdbcTemplate類(lèi) 一些示例 查詢(xún)(SELECT) 更新(INSERT/UPDATE/DELETE) 其他操作 JdbcTemplate 的最佳實(shí)踐 NamedParameterJdbcTemplate類(lèi) SimpleJdbcTemplate類(lèi) DataSource接口 SQLExceptionTranslator接口 執(zhí)行SQL語(yǔ)句 執(zhí)行查詢(xún) 更新數(shù)據(jù)庫(kù) 獲取自動(dòng)生成的主鍵 控制數(shù)據(jù)庫(kù)連接 DataSourceUtils類(lèi) SmartDataSource接口 AbstractDataSource類(lèi) SingleConnectionDataSource類(lèi) DriverManagerDataSource類(lèi) TransactionAwareDataSourceProxy類(lèi) DataSourceTransactionManager類(lèi) NativeJdbcExtractor JDBC批量操作 使用JdbcTemplate進(jìn)行批量操作 使用SimpleJdbcTemplate進(jìn)行批量操作 通過(guò)使用SimpleJdbc類(lèi)簡(jiǎn)化JDBC操作 使用SimpleJdbcInsert插入數(shù)據(jù) 使用SimpleJdbcInsert來(lái)獲取自動(dòng)生成的主鍵 指定SimpleJdbcInsert所使用的字段 使用SqlParameterSource提供參數(shù)值 使用SimpleJdbcCall調(diào)用存儲(chǔ)過(guò)程 聲明SimpleJdbcCall使用的參數(shù) 如何定義SqlParameters 使用SimpleJdbcCall調(diào)用內(nèi)置函數(shù) 使用SimpleJdbcCall返回的ResultSet/REF Cursor 用Java對(duì)象來(lái)表達(dá)JDBC操作 SqlQuery類(lèi) MappingSqlQuery類(lèi) SqlUpdate類(lèi) StoredProcedure類(lèi) SqlFunction類(lèi) 參數(shù)和數(shù)據(jù)處理的基本原則 為參數(shù)設(shè)置SQL類(lèi)型信息 處理BLOB 和 CLOB對(duì)象 在IN語(yǔ)句中傳入一組參數(shù)值 處理復(fù)雜類(lèi)型的存儲(chǔ)過(guò)程調(diào)用 使用ORM工具進(jìn)行數(shù)據(jù)訪問(wèn) 簡(jiǎn)介 Hibernate 資源管理 在Spring容器中創(chuàng)建 SessionFactory The HibernateTemplate 不使用回調(diào)的基于Spring的DAO實(shí)現(xiàn) 基于Hibernate3的原生API實(shí)現(xiàn)DAO 編程式的事務(wù)劃分 聲明式的事務(wù)劃分 事務(wù)管理策略 容器資源 vs 本地資源 在應(yīng)用服務(wù)器中使用Hibernate的注意事項(xiàng) JDO 建立PersistenceManagerFactory JdoTemplate和JdoDaoSupport 基于原生的JDO API實(shí)現(xiàn)DAO 事務(wù)管理 JdoDialect Oracle TopLink SessionFactory 抽象層 TopLinkTemplate and TopLinkDaoSupport 基于原生的TopLink API的DAO實(shí)現(xiàn) 事務(wù)管理 iBATIS SQL Maps 創(chuàng)建SqlMapClient 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 基于原生的iBATIS API的DAO實(shí)現(xiàn) JPA 在Spring環(huán)境中建立JPA LocalEntityManagerFactoryBean 從JNDI中獲取 EntityManagerFactory LocalContainerEntityManagerFactoryBean Tomcat(5.0以上)加載時(shí)的織入配置 使用VM代理的全局加載時(shí)織入 上下文范圍內(nèi)的加載時(shí)織入配置 處理多持久化單元 JpaTemplate 和 JpaDaoSupport 基于原生的JPA實(shí)現(xiàn)DAO 異常轉(zhuǎn)化 事務(wù)管理 JpaDialect The Web Web MVC framework Web框架 概述 與其他MVC實(shí)現(xiàn)框架的集成 Spring Web MVC框架的特點(diǎn) DispatcherServlet 控制器 AbstractController 和 WebContentGenerator 其它的簡(jiǎn)單控制器 MultiActionController 命令控制器 處理器映射(handler mapping) BeanNameUrlHandlerMapping SimpleUrlHandlerMapping 攔截器(HandlerInterceptor) 視圖與視圖解析 視圖解析器(ViewResolver) 視圖解析鏈 重定向(Rediret)到另一個(gè)視圖 RedirectView redirect:前綴 forward:前綴 本地化解析器 AcceptHeaderLocaleResolver CookieLocaleResolver SessionLocaleResolver LocaleChangeInterceptor 使用主題 簡(jiǎn)介 如何定義主題 主題解析器 Spring對(duì)分段文件上傳(multipart file upload)的支持 介紹 使用MultipartResolver 在表單中處理分段文件上傳 使用Spring的表單標(biāo)簽庫(kù) 配置 form標(biāo)簽 input標(biāo)簽 checkbox標(biāo)簽 checkboxes標(biāo)簽 radiobutton標(biāo)簽 radiobuttons標(biāo)簽 password標(biāo)簽 select標(biāo)簽 option標(biāo)簽 options標(biāo)簽 textarea標(biāo)簽 hidden標(biāo)簽 errors標(biāo)簽 處理異常 慣例優(yōu)先原則(convention over configuration) 對(duì)控制器的支持:ControllerClassNameHandlerMapping 對(duì)模型的支持:ModelMap(ModelAndView) 對(duì)視圖的支持:RequestToViewNameTranslator 基于注解的控制器配置 建立dispatcher實(shí)現(xiàn)注解支持 使用@Controller定義一個(gè)控制器 使用@RequestMapping映射請(qǐng)求 使用@RequestParam綁定請(qǐng)求參數(shù)到方法參數(shù) 使用@ModelAttribute提供一個(gè)從模型到數(shù)據(jù)的鏈接 使用@SessionAttributes指定存儲(chǔ)在會(huì)話中的屬性 自定義WebDataBinder初始化 使用@InitBinder自定義數(shù)據(jù)綁定 配置一個(gè)定制的WebBindingInitializer 更多資源 集成視圖技術(shù) 簡(jiǎn)介 JSP和JSTL 視圖解析器 'Plain-old' JSPs versus JSTL 'Plain-old' JSP與JSTL 幫助簡(jiǎn)化開(kāi)發(fā)的額外的標(biāo)簽 Tiles 需要的資源 如何集成Tiles UrlBasedViewResolver類(lèi) ResourceBundleViewResolver類(lèi) SimpleSpringPreparerFactory 和 SpringBeanPreparerFactory Velocity和FreeMarker 需要的資源 Context 配置 創(chuàng)建模板 高級(jí)配置 velocity.properties FreeMarker 綁定支持和表單處理 用于綁定的宏 簡(jiǎn)單綁定 表單輸入生成宏 輸入域 選擇輸入域 重載HTML轉(zhuǎn)碼行為并使你的標(biāo)簽符合XHTML XSLT 寫(xiě)在段首 Bean 定義 標(biāo)準(zhǔn)MVC控制器代碼 把模型數(shù)據(jù)轉(zhuǎn)化為XML 定義視圖屬性 文檔轉(zhuǎn)換 小結(jié) 文檔視圖(PDF/Excel) 簡(jiǎn)介 配置和安裝 文檔視圖定義 Controller 代碼 Excel視圖子類(lèi) PDF視圖子類(lèi) JasperReports 依賴(lài)的資源 配置 配置ViewResolver 配置View 關(guān)于報(bào)表文件 使用 JasperReportsMultiFormatView 構(gòu)造ModelAndView 使用子報(bào)表 配置子報(bào)表文件 配置子報(bào)表數(shù)據(jù)源 配置Exporter的參數(shù) 集成其它Web框架 簡(jiǎn)介 通用配置 JavaServer Faces DelegatingVariableResolver FacesContextUtils Struts ContextLoaderPlugin DelegatingRequestProcessor DelegatingActionProxy ActionSupport Classes Tapestry 注入 Spring 托管的 beans 將 Spring Beans 注入到 Tapestry 頁(yè)面中 組件定義文件 添加抽象訪問(wèn)方法 將 Spring Beans 注入到 Tapestry 頁(yè)面中 - Tapestry 4.0+ 風(fēng)格 WebWork 更多資源 Portlet MVC框架 介紹 控制器 - MVC中的C 視圖 - MVC中的V Web作用范圍的Bean DispatcherPortlet ViewRendererServlet 控制器 AbstractController 和 PortletContentGenerator 其它簡(jiǎn)單的控制器 Command控制器 PortletWrappingController 處理器映射 PortletModeHandlerMapping ParameterHandlerMapping PortletModeParameterHandlerMapping 增加 HandlerInterceptors HandlerInterceptorAdapter ParameterMappingInterceptor 視圖和它們的解析 Multipart文件上傳支持 使用 PortletMultipartResolver 處理表單里的文件上傳 異常處理 Portlet應(yīng)用的部署 整合 使用Spring進(jìn)行遠(yuǎn)程訪問(wèn)與Web服務(wù) 簡(jiǎn)介 使用RMI暴露服務(wù) 使用RmiServiceExporter暴露服務(wù) 在客戶(hù)端鏈接服務(wù) 使用Hessian或者Burlap通過(guò)HTTP遠(yuǎn)程調(diào)用服務(wù) 為Hessian和co.配置DispatcherServlet 使用HessianServiceExporter暴露你的bean 在客戶(hù)端連接服務(wù) 使用Burlap 對(duì)通過(guò)Hessian或Burlap暴露的服務(wù)使用HTTP Basic認(rèn)證 使用HTTP調(diào)用器暴露服務(wù) Exposing the service object 在客戶(hù)端連接服務(wù) Web Services 使用JAX-RPC暴露基于servlet的web服務(wù) 使用JAX-RPC訪問(wèn)web服務(wù) 注冊(cè)JAX-RPC Bean映射 注冊(cè)自己的JAX-RPC 處理器 使用JAX-WS暴露基于servlet的web服務(wù) 使用JAX-WS暴露單獨(dú)web服務(wù) 使用Spring支持的JAX-WS RI來(lái)暴露服務(wù) 使用JAX-WS訪問(wèn)web服務(wù) 使用XFire來(lái)暴露Web服務(wù) JMS 服務(wù)端配置 客戶(hù)端配置 對(duì)遠(yuǎn)程接口不提供自動(dòng)探測(cè)實(shí)現(xiàn) 在選擇這些技術(shù)時(shí)的一些考慮 Enterprise Java Beans (EJB) 集成 簡(jiǎn)介 訪問(wèn)EJB 概念 訪問(wèn)本地的無(wú)狀態(tài)Session Bean(SLSB) 訪問(wèn)遠(yuǎn)程SLSB Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 使用Spring提供的輔助類(lèi)實(shí)現(xiàn)EJB組件 EJB 2.x base classes EJB 3 注入攔截 JMS (Java Message Service) 簡(jiǎn)介 使用Spring JMS JmsTemplate 連接工廠 目的地管理 消息偵聽(tīng)容器 SimpleMessageListenerContainer DefaultMessageListenerContainer ServerSessionMessageListenerContainer 事務(wù)管理 發(fā)送消息 使用消息轉(zhuǎn)換器 SessionCallback 和 ProducerCallback 接收消息 同步接收 異步接收 - 消息驅(qū)動(dòng)的POJO SessionAwareMessageListener接口 MessageListenerAdapter 事務(wù)中的消息處理 JCA消息端點(diǎn)的支持 JMS命名空間支持 JMX 介紹 將Bean暴露為JMX 創(chuàng)建MBeanServer 重用原有的MBeanServer 延遲初始化的MBean MBean的自動(dòng)注冊(cè) 控制注冊(cè)行為 控制Bean的管理接口 MBeanInfoAssembler接口 使用源碼級(jí)元數(shù)據(jù) 使用JDK 5.0的注解 源代碼級(jí)的元數(shù)據(jù)類(lèi)型 AutodetectCapableMBeanInfoAssembler接口 用Java接口定義管理接口 使用MethodNameBasedMBeanInfoAssembler 控制Bean的ObjectName 從Properties讀取Properties 使用MetadataNamingStrategy <context:mbean-export/>元素 JSR-160連接器 服務(wù)器端連接器 客戶(hù)端連接器 基于Burlap/Hessian/SOAP的JMX 通過(guò)代理訪問(wèn)MBean 通知 為通知注冊(cè)監(jiān)聽(tīng)器 發(fā)布通知 更多資源 JCA CCI 簡(jiǎn)介 配置CCI 連接器配置 在Spring中配置ConnectionFactory 配置CCI連接 使用一個(gè) CCI 單連接 使用Spring的 CCI訪問(wèn)支持 記錄轉(zhuǎn)換 CciTemplate類(lèi) DAO支持 自動(dòng)輸出記錄生成 總結(jié) 直接使用一個(gè)CCI Connection接口和Interaction接口 CciTemplate 使用示例 建模CCI訪問(wèn)為操作對(duì)象 MappingRecordOperation MappingCommAreaOperation 自動(dòng)生成輸出記錄 總結(jié) MappingRecordOperation 使用示例 MappingCommAreaOperation 使用示例 事務(wù) Spring郵件抽象層 簡(jiǎn)介 使用Spring郵件抽象 MailSender 和 SimpleMailMessage 的基本用法 使用 JavaMailSender 和 MimeMessagePreparator 使用MimeMessageHelper 發(fā)送附件和嵌入式資源(inline resources) 附件 內(nèi)嵌資源 使用模板來(lái)創(chuàng)建郵件內(nèi)容 一個(gè)基于Velocity的示例 Spring中的定時(shí)調(diào)度(Scheduling)和線程池(Thread Pooling) 簡(jiǎn)介 使用OpenSymphony Quartz 調(diào)度器 使用JobDetailBean 使用 MethodInvokingJobDetailFactoryBean 使用triggers和SchedulerFactoryBean來(lái)包裝任務(wù) 使用JDK Timer支持類(lèi) 創(chuàng)建定制的timers 使用 MethodInvokingTimerTaskFactoryBean類(lèi) 最后:使用TimerFactoryBean來(lái)設(shè)置任務(wù) SpringTaskExecutor抽象 TaskExecutor接口 TaskExecutor類(lèi)型 使用TaskExecutor 動(dòng)態(tài)語(yǔ)言支持 介紹 第一個(gè)示例 定義動(dòng)態(tài)語(yǔ)言支持的bean 公共概念 <lang:language/> 元素 Refreshable bean 內(nèi)置動(dòng)態(tài)語(yǔ)言源文件 理解dynamic-language-backed bean上下文中的構(gòu)造器注入 JRuby beans Groovy beans 通過(guò)回調(diào)定制Groovy對(duì)象 BeanShell beans 場(chǎng)景 Spring MVC控制器的腳本化 Validator的腳本化 Bits and bobs AOP - 通知腳本化bean 作用域 更多的資源 注解和源代碼級(jí)的元數(shù)據(jù)支持 簡(jiǎn)介 Spring的元數(shù)據(jù)支持 注解 @Required Spring中的其它@Annotations Jakarta Commons Attributes集成 元數(shù)據(jù)和Spring AOP自動(dòng)代理 基本原理 聲明式事務(wù)管理 示例程序 演示案例 介紹 使用動(dòng)態(tài)語(yǔ)言實(shí)現(xiàn)的Spring MVC控制器 構(gòu)建與部署 使用SimpleJdbcTemplate和@Repository實(shí)現(xiàn)DAO 域?qū)ο?/a> Data Access Object 構(gòu)建 XML Schema-based configuration Introduction XML Schema-based configuration Referencing the schemas The util schema <util:constant/> Setting a bean property or constructor arg from a field value <util:property-path/> Using <util:property-path/> to set a bean property or constructor-argument <util:properties/> <util:list/> <util:map/> <util:set/> The jee schema <jee:jndi-lookup/> (simple) <jee:jndi-lookup/> (with single JNDI environment setting) <jee:jndi-lookup/> (with multiple JNDI environment settings) <jee:jndi-lookup/> (complex) <jee:local-slsb/> (simple) <jee:local-slsb/> (complex) <jee:remote-slsb/> The lang schema The jms schema The tx (transaction) schema The aop schema The context schema <property-placeholder/> <annotation-config/> <component-scan/> <load-time-weaver/> <spring-configured/> <mbean-export/> The tool schema The beans schema Setting up your IDE Setting up Eclipse Setting up IntelliJ IDEA Integration issues XML parsing errors in the Resin v.3 application server Extensible XML authoring Introduction Authoring the schema Coding a NamespaceHandler Coding a BeanDefinitionParser Registering the handler and the schema 'META-INF/spring.handlers' 'META-INF/spring.schemas' Using a custom extension in your Spring XML configuration Meatier examples Nesting custom tags within custom tags Custom attributes on 'normal' elements Further Resources spring-beans-2.0.dtd spring.tld Introduction The bind tag The escapeBody tag The hasBindErrors tag The htmlEscape tag The message tag The nestedPath tag The theme tag The transform tag spring-form.tld Introduction The checkbox tag The checkboxes tag The errors tag The form tag The hidden tag The input tag The label tag The option tag The options tag The password tag The radiobutton tag The radiobuttons tag The select tag The textarea tag Spring 2.5開(kāi)發(fā)手冊(cè)中文化項(xiàng)目 聲明 致謝 參與人員 項(xiàng)目歷程
characters

12.2.?Hibernate

我們將首先從Hibernate3 (http://www.hibernate.org/)開(kāi)始,通過(guò)講解Hibernate在Spring環(huán)境中的使用來(lái)闡述Spring框架對(duì)于O/R Mapping工具的整合方式。 本章節(jié)將涉及到許多細(xì)節(jié)問(wèn)題,并向你展示各種不同的DAO實(shí)現(xiàn)方式和事務(wù)劃分。這其中的絕大多數(shù)模式能夠被Spring支持的其他O/R Mapping工具所使用。 這一章節(jié)的其他部分將為你講述其他的O/R Mapping技術(shù),并給出一些簡(jiǎn)短的例子。

注意:Spring2.5版本需要Hibernate3.1或更高版本,不再提供對(duì)Hibernate2.1與Hibernate3.0版本的支持。

12.2.1.?資源管理

典型的業(yè)務(wù)程序經(jīng)常會(huì)被重復(fù)的資源管理代碼搞得混亂。很多項(xiàng)目都試圖創(chuàng)建自己的方案來(lái)解決這個(gè)問(wèn)題,有時(shí)會(huì)為了編程方便而犧牲恰當(dāng)?shù)腻e(cuò)誤處理。 對(duì)于恰當(dāng)?shù)馁Y源管理,Spring提倡一種矚目而又簡(jiǎn)潔的解決方案:使用模板化的IoC,諸如基礎(chǔ)構(gòu)建類(lèi)、回調(diào)接口以及使用AOP攔截器。 基礎(chǔ)構(gòu)建類(lèi)負(fù)責(zé)恰當(dāng)?shù)馁Y源處理,以及將特定的異常代碼轉(zhuǎn)換為unchecked exception體系。Spring引進(jìn)了DAO異常體系,可適用于任何數(shù)據(jù)訪問(wèn)策略。 對(duì)于直接使用JDBC的情況,前面章節(jié)提到的 JdbcTemplate 類(lèi)負(fù)責(zé)處理connection,并正確地把 SQLException 轉(zhuǎn)換為 DataAccessException 體系,包括將與數(shù)據(jù)庫(kù)相關(guān)的SQL錯(cuò)誤代碼變成有意義的異常類(lèi)。 Spring同時(shí)通過(guò)它們各自的事務(wù)管理器支持JTA和JDBC事務(wù)。

Spring同樣也提供了對(duì)Hibernate和JDO的支持,包括 HibernateTemplate / JdoTemplate 類(lèi)似于 JdbcTemplateHibernateInterceptor / JdoInterceptor 以及一個(gè) Hibernate / JDO 事務(wù)管理器。 這樣做的主要目的是為了能夠清晰地劃分應(yīng)用程序?qū)哟味还苁褂煤畏N數(shù)據(jù)訪問(wèn)和事務(wù)管理技術(shù),從而降低各個(gè)應(yīng)用程序?qū)ο笾g的耦合。 業(yè)務(wù)邏輯不再依賴(lài)于特定的數(shù)據(jù)訪問(wèn)與事務(wù)策略;不再有硬編碼的資源查找、不再有難以替換的singletons、不再有用戶(hù)自定義的服務(wù)注冊(cè)。 Spring提供了一個(gè)簡(jiǎn)單且穩(wěn)固的方案使得各種應(yīng)用邏輯對(duì)象連接在一起,使這些對(duì)象可重用,并盡可能不依賴(lài)容器。 所有的數(shù)據(jù)訪問(wèn)技術(shù)都能獨(dú)立使用,但是他們?cè)赟pring提供的基于XML配置且無(wú)需依賴(lài)Spring的普通JavaBean下會(huì)與application Context整合的更好。 在典型的Spring應(yīng)用程序中,很多重要的對(duì)象都是JavaBeans:數(shù)據(jù)訪問(wèn)template、數(shù)據(jù)訪問(wèn)對(duì)象(使用template)、事務(wù)管理器、業(yè)務(wù)邏輯對(duì)象(使用數(shù)據(jù)訪問(wèn)對(duì)象和事務(wù)管理器)、web視圖解析器、web控制器(使用業(yè)務(wù)服務(wù))等等。

12.2.2.?在Spring容器中創(chuàng)建 SessionFactory

為了避免硬編碼的資源查找與應(yīng)用程序?qū)ο缶o密耦合,Spring允許你在Spring容器中以bean的方式定義諸如JDBC DataSource或者Hibernate SessionFactory 的數(shù)據(jù)訪問(wèn)資源。 任何需要進(jìn)行資源訪問(wèn)的應(yīng)用程序?qū)ο笾恍枰钟羞@些事先定義好的實(shí)例的引用(DAO定義在下一章節(jié)介紹),下面的代碼演示如何創(chuàng)建一個(gè)JDBC DataSource 和Hibernate SessionFactory

<beans>

  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
    <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
    <property name="username" value="sa"/>
    <property name="password" value=""/>
  </bean>

  <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="mappingResources">
      <list>
        <value>product.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
      </value>
    </property>
  </bean>

</beans>

將一個(gè)本地定義的,如Jakarta Commons DBCP的 BasicDataSource 切換為一個(gè)JNDI定位的DataSource(通常由應(yīng)用程序服務(wù)器管理),僅僅需要改變配置:

<beans>

  <bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/myds"/>
  </bean>

</beans>

通過(guò)使用Spring的 JndiObjectFactoryBean 來(lái)暴露和獲,你也可以訪問(wèn)一個(gè)JNDI定位的Hibernate SessionFactory。 當(dāng)然,如果在EJB上下文之外,這是不必要的。

12.2.3.?The HibernateTemplate

對(duì)于特定的數(shù)據(jù)訪問(wèn)對(duì)象或業(yè)務(wù)對(duì)象的方法,基本的模板編程模型看起來(lái)像下面所示的代碼那樣。 對(duì)于這些外部對(duì)象來(lái)說(shuō),沒(méi)有任何實(shí)現(xiàn)特定接口的約束,僅僅要求提供一個(gè)Hibernate SessionFactory。 它可以從任何地方得到,不過(guò)比較適宜的方法是從Spring的IoC容器中取得bean的引用:通過(guò)簡(jiǎn)單的 setSessionFactory(..) 這個(gè)bean的setter方法。 下面的代碼片段展示了在Spring容器中一個(gè)DAO的定義,它引用了上面定義的 SessionFactory,同時(shí)展示了一個(gè)DAO方法的具體實(shí)現(xiàn)。

<beans>

  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

</beans>
public class ProductDaoImpl implements ProductDao {

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public Collection loadProductsByCategory(String category) throws DataAccessException {
    	return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
    }
}

除了很多類(lèi)似上例中易用的方法外,HibernateTemplate類(lèi)提供了大量方法對(duì)應(yīng)Hibernate Session接口中暴露的方法。當(dāng)你需要使用的Session方法沒(méi)有在HibernateTemplate中提供時(shí),可以通過(guò)下面提供的基于回調(diào)的方案來(lái)實(shí)現(xiàn)。

public class ProductDaoImpl implements ProductDao {

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public Collection loadProductsByCategory(final String category) throws DataAccessException {
        return this.hibernateTemplate.execute(new HibernateCallback() {

            public Object doInHibernate(Session session) {
                Criteria criteria = session.createCriteria(Product.class);
                criteria.add(Expression.eq("category", category));
                criteria.setMaxResults(6);
                return criteria.list();
            }
        };
    }
}

一個(gè)回調(diào)實(shí)現(xiàn)能夠有效地在任何Hibernate數(shù)據(jù)訪問(wèn)中使用。HibernateTemplate 會(huì)確保當(dāng)前Hibernate的 Session 實(shí)例的正確打開(kāi)和關(guān)閉,并直接參與到事務(wù)管理中去。 Template實(shí)例不僅是線程安全的,同時(shí)它也是可重用的。因而他們可以作為外部對(duì)象的實(shí)例變量而被持有。對(duì)于那些簡(jiǎn)單的諸如find、load、saveOrUpdate或者delete操作的調(diào)用,HibernateTemplate 提供可選擇的快捷函數(shù)來(lái)替換這種回調(diào)的實(shí)現(xiàn)。 不僅如此,Spring還提供了一個(gè)簡(jiǎn)便的 HibernateDaoSupport 基類(lèi),這個(gè)類(lèi)提供了 setSessionFactory(..) 方法來(lái)接受一個(gè) SessionFactory 對(duì)象,同時(shí)提供了 getSessionFactory()getHibernateTemplate() 方法給子類(lèi)使用。 綜合了這些,對(duì)于那些典型的業(yè)務(wù)需求,就有了一個(gè)非常簡(jiǎn)單的DAO實(shí)現(xiàn):

public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {

    public Collection loadProductsByCategory(String category) throws DataAccessException {
        return this.getHibernateTemplate().find(
            "from test.Product product where product.category=?", category);
    }
}

12.2.4.?不使用回調(diào)的基于Spring的DAO實(shí)現(xiàn)

作為不使用Spring的 HibernateTemplate 來(lái)實(shí)現(xiàn)DAO的替代解決方案,你依然可以用傳統(tǒng)的編程風(fēng)格來(lái)編寫(xiě)你的數(shù)據(jù)訪問(wèn)代碼。 無(wú)需將你的Hibernate訪問(wèn)代碼包裝在一個(gè)回調(diào)中,只需符合Spring的通用的 DataAccessException 異常體系。 HibernateDaoSupport 基類(lèi)提供了訪問(wèn)與當(dāng)前事務(wù)綁定的 Session 對(duì)象的函數(shù),因而能保證在這種情況下異常的正確轉(zhuǎn)化。 類(lèi)似的函數(shù)同樣可以在 SessionFactoryUtils 類(lèi)中找到,但他們以靜態(tài)方法的形式出現(xiàn)。 值得注意的是,通常將 'false' 作為參數(shù)值(表示是否允許創(chuàng)建)傳遞給 getSession(..) 方法進(jìn)行調(diào)用。 此時(shí),整個(gè)調(diào)用將在同一個(gè)事務(wù)內(nèi)完成(它的整個(gè)生命周期由事務(wù)控制,避免了關(guān)閉返回的 Session 的需要)。

public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {

    public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
        Session session = getSession(false);
        try {
            Query query = session.createQuery("from test.Product product where product.category=?");
            query.setString(0, category);
            List result = query.list();
            if (result == null) {
                throw new MyException("No search results.");
            }
            return result;
        }
        catch (HibernateException ex) {
            throw convertHibernateAccessException(ex);
        }
    }
}

這種直接使用Hibernate訪問(wèn)代碼的好處在于它允許你在數(shù)據(jù)訪問(wèn)代碼中拋出 任何 checked exception,而 HibernateTemplate 卻受限于回調(diào)中的unchecked exception。 注意,你通常可以將這些應(yīng)用程序的異常處理推遲到回調(diào)函數(shù)之后,這樣,你依然可以正常使用 HibernateTemplate。 一般來(lái)說(shuō),HibernateTemplate 類(lèi)所提供的許多方法在許多情況下看上去更簡(jiǎn)單和便捷。

12.2.5.?基于Hibernate3的原生API實(shí)現(xiàn)DAO

Hibernate3 引入了一個(gè)新的特性:“帶上下文環(huán)境的Session”。 這一特性使得Hibernate自身具備了每個(gè)事務(wù)綁定當(dāng)前 Session 對(duì)象的功能。 這與Spring中每個(gè)Hibernate的 Session 與事務(wù)同步的功能大致相同。一個(gè)相應(yīng)的基于原生的Hibernate API的DAO實(shí)現(xiàn)正如下例所示:

public class ProductDaoImpl implements ProductDao {

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Collection loadProductsByCategory(String category) {
        return this.sessionFactory.getCurrentSession()
                .createQuery("from test.Product product where product.category=?")
                .setParameter(0, category)
                .list();
    }
}

這種風(fēng)格與你在Hibernate文檔和示例中見(jiàn)到的非常類(lèi)似,除了DAO實(shí)現(xiàn)類(lèi)中持有了一個(gè) SessionFactory 的實(shí)例變量。 我們強(qiáng)烈推薦這種基于實(shí)例變量的DAO構(gòu)建方式,而不是使用那種過(guò)去由Hibernate的示例程序中提到的 靜態(tài)的 HibernateUtil 類(lèi)。 (通常來(lái)說(shuō),不要在靜態(tài)變量中保存任何資源信息除非 確實(shí) 有這個(gè)必要)。

上述DAO遵循依賴(lài)注入模式:它如同使用Spring的 HibernateTemplate 進(jìn)行編程那樣,適合在Spring IoC容器中進(jìn)行配置。 當(dāng)然,這樣的DAO還可以建立在一個(gè)普通的Java類(lèi)中(諸如在Unit Test中): 僅僅需要初始化這個(gè)類(lèi), 調(diào)用 setSessionFactory(..) 方法設(shè)置你所期望的工廠資源。 以Spring的bean的定義方式,它看上去就像這樣:

<beans>

  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

</beans>

這種DAO訪問(wèn)方式的主要優(yōu)勢(shì)在于它僅僅依賴(lài)于Hibernate API本身而無(wú)需引入任何Spring的類(lèi)。 從無(wú)入侵性的角度來(lái)看,這一點(diǎn)非常吸引人。對(duì)于Hibernate開(kāi)發(fā)人員來(lái)說(shuō)也無(wú)疑更加自然。

然而,這樣的DAO訪問(wèn)方式會(huì)拋出原生 HibernateException (這是一個(gè)無(wú)需聲明或捕獲的unchecked exception), 這意味著,DAO的調(diào)用者只能以致命的錯(cuò)誤來(lái)處理這些異常,除非完全依賴(lài)Hibernate自身的異常體系。 因而,除非你將DAO的調(diào)用者綁定到具體的實(shí)現(xiàn)策略上去,否則你將無(wú)法捕獲特定的異常原因,諸如樂(lè)觀鎖異常。 這種折中平衡或許可以被接受,如果你的應(yīng)用完全基于Hibernate或者無(wú)需進(jìn)行特殊的異常處理。

幸運(yùn)的是,Spring的 LocalSessionFactoryBean 可以在任何Spring的事務(wù)管理策略下, 提供對(duì)Hibernate的 SessionFactory.getCurrentSession() 方法的支持,它將返回當(dāng)前受Spring事務(wù)管理(甚至是 HibernateTransactionManager 管理的)的 Session 對(duì)象。 當(dāng)然,該函數(shù)的標(biāo)準(zhǔn)行為依然有效:返回當(dāng)前與正在進(jìn)行的JTA事務(wù)(無(wú)論是Spring的 JtaTransactionManager、EJB CMT或者普通的JTA)綁定的 Session 對(duì)象。

總體來(lái)說(shuō),DAO可以基于Hibernate3的原生API實(shí)現(xiàn),同時(shí),它依舊需要能夠參與到Spring的事務(wù)管理中。

12.2.6.?編程式的事務(wù)劃分

我們可以在這些低層次的數(shù)據(jù)訪問(wèn)服務(wù)之上的應(yīng)用程序進(jìn)行更高層次的事務(wù)劃分,從而讓事務(wù)能夠橫跨多個(gè)操作。 這里對(duì)于相關(guān)的業(yè)務(wù)邏輯對(duì)象同樣沒(méi)有實(shí)現(xiàn)接口的限制,它只需要一個(gè)Spring的 PlatformTransactionManager。 同SessionFactory一樣,它可以來(lái)自任何地方,但是最好是一個(gè)經(jīng)由 setTransactionManager(..) 方法注入的bean的引用,正如使用 setProductDao 方法來(lái)設(shè)置 productDAO 一樣。 下面演示了在Spring的application context中定義一個(gè)事務(wù)管理器和一個(gè)業(yè)務(wù)對(duì)象,以及具體的業(yè)務(wù)方法實(shí)現(xiàn):

<beans>

  <bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

  <bean id="myProductService" class="product.ProductServiceImpl">
    <property name="transactionManager" ref="myTxManager"/>
    <property name="productDao" ref="myProductDao"/>
  </bean>

</beans>
public class ProductServiceImpl implements ProductService {

    private TransactionTemplate transactionTemplate;
    private ProductDao productDao;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void increasePriceOfAllProductsInCategory(final String category) {
        this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {

                public void doInTransactionWithoutResult(TransactionStatus status) {
                    List productsToChange = this.productDao.loadProductsByCategory(category);
                    // do the price increase...
                }
            }
        );
    }
}

12.2.7.?聲明式的事務(wù)劃分

作為可選方案,我們可以使用Spring聲明式的事務(wù)支持。聲明式的事務(wù)支持通過(guò)配置Spring容器中的AOP Transaction Interceptor來(lái)替換事務(wù)劃分的硬編碼。 這將使你可以從每個(gè)業(yè)務(wù)方法中重復(fù)的事務(wù)劃分代碼中解放出來(lái),真正專(zhuān)注于為你的應(yīng)用添加有價(jià)值的業(yè)務(wù)邏輯代碼。此外,類(lèi)似傳播行為和隔離級(jí)別等事務(wù)語(yǔ)義能夠在配置文件中改變,而不會(huì)影響具體的業(yè)務(wù)對(duì)象實(shí)現(xiàn)。

<beans>

  <bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

  <bean id="myProductService" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces" value="product.ProductService"/>
    <property name="target">
        <bean class="product.DefaultProductService">
            <property name="productDao" ref="myProductDao"/>
        </bean>
    </property>
    <property name="interceptorNames">
      <list>
        <value>myTxInterceptor</value> <!-- the transaction interceptor (configured elsewhere) -->
      </list>
    </property>
  </bean>

</beans>
public class ProductServiceImpl implements ProductService {

    private ProductDao productDao;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    // notice the absence of transaction demarcation code in this method
    // Spring's declarative transaction infrastructure will be demarcating transactions on your behalf 
    public void increasePriceOfAllProductsInCategory(final String category) {
        List productsToChange = this.productDao.loadProductsByCategory(category);
        // ...
    }
}

Spring的 TransactionInterceptor 允許任何應(yīng)用程序的checked exception在回調(diào)代碼中拋出,而 TransactionTemplate 在回調(diào)中則嚴(yán)格要求被封裝成unchecked exception。 TransactionTemplate 會(huì)在一個(gè)unchecked exception拋出時(shí),或者當(dāng)事務(wù)被應(yīng)用程序通過(guò) TransactionStatus 標(biāo)記為rollback-only時(shí)觸發(fā)一個(gè)數(shù)據(jù)庫(kù)回滾操作。 TransactionInterceptor 默認(rèn)進(jìn)行同樣的操作,但是它允許對(duì)每個(gè)方法配置自己的rollback策略。

下面列出的高級(jí)別的聲明式的事務(wù)管理方案并沒(méi)有使用 ProxyFactoryBean,它將使那些大量的業(yè)務(wù)對(duì)象需要被納入到事務(wù)管理中時(shí)的配置變得非常簡(jiǎn)單。

注意

在你打算繼續(xù)閱讀下一部分之前,我們 強(qiáng)烈 推薦你想去閱讀 第?9.5?節(jié) “聲明式事務(wù)管理” 這一章節(jié)。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

  <!-- SessionFactory, DataSource, etc. omitted -->

  <bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>
  
  <aop:config>
    <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
  </aop:config>

  <tx:advice id="txAdvice" transaction-manager="myTxManager">
    <tx:attributes>
      <tx:method name="increasePrice*" propagation="REQUIRED"/>
      <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
      <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
  </tx:advice>

  <bean id="myProductService" class="product.SimpleProductService">
    <property name="productDao" ref="myProductDao"/>
  </bean>

</beans>

12.2.8.?事務(wù)管理策略

TransactionTemplateTransactionInterceptor 都將真正的事務(wù)處理委托給一個(gè) PlatformTransactionManager 實(shí)例來(lái)處理。 在Hibernate應(yīng)用中,它可以是一個(gè) HibernateTransactionManager(對(duì)于單獨(dú)一個(gè)的Hibernate SessionFactory 使用一個(gè) ThreadLocalSession)或一個(gè) JtaTransactionManager(代理給容器的JTA子系統(tǒng))。 你甚至可以使用自定義的 PlatformTransactionManager 的實(shí)現(xiàn)。因而,在你的應(yīng)用碰到了特定的分布式事務(wù)的部署需求時(shí)(類(lèi)似將原來(lái)的Hibernate事務(wù)管理轉(zhuǎn)變?yōu)镴TA),僅僅需要改變配置而已:簡(jiǎn)單將Hibernate的事務(wù)管理器替換成JTA事務(wù)實(shí)現(xiàn)。 任何的事務(wù)劃分和數(shù)據(jù)訪問(wèn)的代碼都無(wú)需因此而改變,因?yàn)樗麄儍H僅使用了通用的事務(wù)管理API。

對(duì)于橫跨多個(gè)Hibernate SessionFacotry的分布式事務(wù),只需簡(jiǎn)單地將 JtaTransactionManager 同多個(gè) LocalSessionFactoryBean 的定義結(jié)合起來(lái)作為事務(wù)策略。 你的每一個(gè)DAO通過(guò)bean屬性得到各自的 SessionFactory 引用。如果所有的底層JDBC數(shù)據(jù)源都是支持事務(wù)的容器,那么只要業(yè)務(wù)對(duì)象使用了 JtaTransactionManager 作為事務(wù)策略,它就可以橫跨多個(gè)DAO和多個(gè)session factories來(lái)劃分事務(wù),而不需要做任何特殊處理。

<beans>

  <bean id="myDataSource1" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName value="java:comp/env/jdbc/myds1"/>
  </bean>

  <bean id="myDataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/myds2"/>
  </bean>

  <bean id="mySessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource1"/>
    <property name="mappingResources">
      <list>
        <value>product.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.MySQLDialect
        hibernate.show_sql=true
      </value>
    </property>
  </bean>

  <bean id="mySessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource2"/>
    <property name="mappingResources">
      <list>
        <value>inventory.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.OracleDialect
      </value>
    </property>
  </bean>

  <bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory1"/>
  </bean>

  <bean id="myInventoryDao" class="product.InventoryDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory2"/>
  </bean>

  <!-- this shows the Spring 1.x style of declarative transaction configuration -->
  <!-- it is totally supported, 100% legal in Spring 2.x, but see also above for the sleeker, Spring 2.0 style -->
  <bean id="myProductService"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="myTxManager"/>
    <property name="target">
      <bean class="product.ProductServiceImpl">
        <property name="productDao" ref="myProductDao"/>
        <property name="inventoryDao" ref="myInventoryDao"/>
      </bean>
    </property>
    <property name="transactionAttributes">
      <props>
        <prop key="increasePrice*">PROPAGATION_REQUIRED</prop>
        <prop key="someOtherBusinessMethod">PROPAGATION_REQUIRES_NEW</prop>
        <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
      </props>
    </property>
  </bean>

</beans>

HibernateTransactionManagerJtaTransactionManager 都允許恰當(dāng)?shù)腏VM級(jí)別的Hibernate緩存處理,而無(wú)需使用與容器相關(guān)的事務(wù)管理器或JCA連接器。(只要不是由EJB發(fā)起的事務(wù))

對(duì)于特定的 DataSource,HibernateTransactionManager 能夠?yàn)槠胀ǖ腏DBC訪問(wèn)代碼提供Hibernate所使用的 Connection。 這一功能允許你可以完全混和使用Hibernate/JDBC進(jìn)行數(shù)據(jù)訪問(wèn)而無(wú)需依賴(lài)JTA在高層次代碼中進(jìn)行事務(wù)劃分,只要你依然訪問(wèn)的是同一個(gè)數(shù)據(jù)庫(kù)! HibernateTransactionManager 能夠自動(dòng)地將Hibernate事務(wù)暴露為JDBC事務(wù),如果你通過(guò)設(shè)置 DataSource來(lái)建立SessionFactory 對(duì)象(通過(guò)設(shè)置 LocalSessionFactoryBean 中的“dataSource”屬性)。 另外一種配置方法是通過(guò)設(shè)置 HibernateTransactionManager 的“dataSource”屬性,明確指定事務(wù)需要暴露的 DataSource。

12.2.9.?容器資源 vs 本地資源

Spring的資源管理允許你簡(jiǎn)單地在一個(gè)JNDI的 SessionFactory 和一個(gè)本地的 SessionFactory 之間切換而無(wú)需更改任何一行應(yīng)用程序代碼。 把資源定義放在容器中還是放在應(yīng)用程序本地中主要是由使用的事務(wù)策略決定的。與Spring定義的本地 SessionFactory 相比,一個(gè)手工注冊(cè)的JNDI SessionFactory 并沒(méi)有體現(xiàn)出多大的優(yōu)勢(shì)。 通過(guò)Hibernate的JCA連接器來(lái)部署一個(gè) SessionFactory 提供了能使之參與到J2EE服務(wù)器管理架構(gòu)的增值服務(wù),不過(guò)除此之外也并沒(méi)有增加實(shí)際的價(jià)值。

Spring對(duì)事務(wù)管理的支持有一個(gè)非常重要的好處:它不依賴(lài)于任何容器。使用非JTA的任何其他事務(wù)策略的配置,程序也能在獨(dú)立的測(cè)試環(huán)境下正常工作。 尤其對(duì)于那些典型的單數(shù)據(jù)庫(kù)事務(wù)情況下,這將是一個(gè)非常輕量級(jí)而又強(qiáng)大的JTA替代方案。當(dāng)你使用一個(gè)本地的EJB SLSB來(lái)驅(qū)動(dòng)事務(wù)時(shí),即時(shí)你可能只訪問(wèn)一個(gè)數(shù)據(jù)庫(kù)而且僅僅通過(guò)CMT使用SLSB的聲明性事務(wù),你仍然要依賴(lài)于EJB容器和JTA。 使用編程式JTA替換方案依然需要J2EE環(huán)境,JTA不僅對(duì)于JTA本身,還對(duì)于JNDI的 DataSource 實(shí)例引入了容器依賴(lài)。 對(duì)于非Spring環(huán)境的JTA驅(qū)動(dòng)的Hibernate事務(wù),你必須使用Hibernate JCA連接器或者額外的Hibernate事務(wù)代碼及 TransactionManagerLookup 配置,來(lái)恰當(dāng)?shù)靥幚鞪VM級(jí)別的緩存。

Spring驅(qū)動(dòng)的事務(wù)管理與本地定義的 SessionFactory 能夠工作得非常好,就像使用本地的JDBC DataSource 一樣,當(dāng)然前提必須是訪問(wèn)單個(gè)數(shù)據(jù)庫(kù)。 因此當(dāng)你真正面對(duì)分布式事務(wù)的需求時(shí),可以馬上回到Spring的JTA事務(wù)。必須要注意,一個(gè)JCA連接器需要特定容器的部署步驟,而且首先容器要支持JCA。 這要比使用本地資源定義和Spring驅(qū)動(dòng)事務(wù)來(lái)部署一個(gè)簡(jiǎn)單的Web應(yīng)用麻煩得多。而且你通常需要特定企業(yè)版本的容器,但是像類(lèi)似WebLogic的Express版本并不提供JCA。 一個(gè)僅使用本地資源并且針對(duì)一個(gè)數(shù)據(jù)庫(kù)的事務(wù)操作的Spring應(yīng)用將可以在任何一種J2EE的Web容器中工作(不需要JTA、JCA或者EJB),比如Tomcat、Resin甚至普通的Jetty。 除此之外,這樣的中間層可以在桌面應(yīng)用或測(cè)試用例中被簡(jiǎn)單地重用。

考慮一下所有的情況:如果你不使用EJB,堅(jiān)持使用本地 SessionFactory 以及Spring的 HibernateTransactionManager 或者 JtaTransactionManager, 你將獲得包括適當(dāng)?shù)腏VM級(jí)別上的緩存以及分布式事務(wù)在內(nèi)的所有好處,而不會(huì)有任何容器部署的麻煩。通過(guò)JCA連接器的Hibernate的 SessionFactory 的JNDI注冊(cè)僅僅在EJB中使用會(huì)帶來(lái)好處。

12.2.10.?在應(yīng)用服務(wù)器中使用Hibernate的注意事項(xiàng)

在一些具有非常嚴(yán)格的 XADataSource 實(shí)現(xiàn)的JTA環(huán)境中(目前來(lái)說(shuō)只是WebLogic和WebSphere的某些版本)當(dāng)你將Hibernate配置成不感知JTA PlatformTransactionManager 對(duì)象時(shí),容器可能會(huì)在應(yīng)用服務(wù)器日志中報(bào)出一些警告和異常。 這些警告和異常通常會(huì)說(shuō):“正在被訪問(wèn)的連接不再有效,或者JDBC連接不再有效,可能由于事務(wù)不再處于激活狀態(tài)”。下面是一個(gè)從WebLogic上拋出的異常:

java.sql.SQLException: The transaction is no longer active - status: 'Committed'.
   No further JDBC access is allowed within this transaction.

這樣的錯(cuò)誤警告很容易解決:只要簡(jiǎn)單的把Hibernate配置成感知到JTA PlatformTransactionManager 實(shí)例的存在即可,同時(shí)將他們進(jìn)行同步(與Spring同步)。可以有兩種方法達(dá)到這種效果:

  • 如果你已經(jīng)在application context中定義并獲取了JTA PlatformTransactionManager 對(duì)象(或許來(lái)自通過(guò) JndiObjectFactoryBean 得到的JNDI)并已經(jīng)將它注入到類(lèi)似Spring的 JtaTransactionManager 中, 那么最簡(jiǎn)單的方式就是指定這個(gè)bean的引用作為 LocalSessionFactoryBeanjtaTransactionManager 屬性。Spring將使這個(gè)對(duì)象被Hibernate所感知。

  • 多數(shù)情況下,你還沒(méi)有得到JTA的 PlatformTransactionManager 實(shí)例(由于Spring的 JtaTransactionManager 能夠自己找到它),所以你需要自行配置Hibernate并直接尋找資源。 正如Hibernate文檔中提到的,這可以通過(guò)在Hibernate配置一個(gè)應(yīng)用服務(wù)器特定的 TransactionManagerLookup 類(lèi)來(lái)完成。

對(duì)于恰當(dāng)?shù)氖褂梅椒ǎ銦o(wú)需了解更多的東西。但是我們?cè)谶@里將描述一下,對(duì)于將Hibernate配置為感知或者不感知JTA的 PlatformTransactionManager 對(duì)象這兩種情況下,整個(gè)事務(wù)的執(zhí)行順序。

Hibernate被配置成不感知JTA PlatformTransactionManager 的情況下,當(dāng)一個(gè)JTA事務(wù)提交時(shí),整個(gè)事件的執(zhí)行順序如下:

  • JTA 事務(wù)提交

  • Spring的 JtaTransactionManager 同步到JTA事務(wù),它被JTA事務(wù)管理器通過(guò)調(diào)用 afterCompletion 執(zhí)行回調(diào)。

  • 在所有其他活動(dòng)中,這將由Spring向Hibernate觸發(fā)一個(gè)回調(diào),通過(guò)Hibernate的 afterTransactionCompletion 回調(diào)(用于清除Hibernate緩存),然后緊跟著一個(gè)明確的Hibernate Session的 close() 調(diào)用。 這將使Hibernate試圖去關(guān)閉JDBC的Connection。

  • 在某些環(huán)境中,Connection.close() 的調(diào)用將會(huì)觸發(fā)一個(gè)警告或者錯(cuò)誤信息。 這是由于特定的應(yīng)用服務(wù)器將不再考慮 Connection 的可用性,因?yàn)榇藭r(shí)事務(wù)已經(jīng)被提交了。

在Hibernate被配置成感知JTA的 PlatformTransactionManager 的情況下,當(dāng)一個(gè)JTA事務(wù)提交時(shí),整個(gè)事件的執(zhí)行順序如下:

  • JTA 事務(wù)準(zhǔn)備提交

  • Spring的 JtaTransactionManager 同步到JTA事務(wù),因而它被JTA事務(wù)管理器通過(guò)調(diào)用 beforeCompletion 執(zhí)行回調(diào)。

  • Spring能感知到Hibernate自身被同步到JTA Transaction,因而表現(xiàn)得與先前那種情況有所不同。 假設(shè)Hibernate的 Session 需要被關(guān)閉,Spring將負(fù)責(zé)關(guān)閉它。

  • JTA 事務(wù)提交

  • Hibernate將與JTA transaction進(jìn)行同步,因而它被JTA事務(wù)管理器通過(guò)調(diào)用 afterCompletion 執(zhí)行回調(diào),并且適時(shí)地清除緩存。

Previous article: Next article: