亚洲国产日韩欧美一区二区三区,精品亚洲国产成人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ì)話(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)和線(xiàn)程池(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

8.3.?集成測(cè)試

8.3.1.?概覽

能夠無(wú)需部署到你的應(yīng)用服務(wù)器上或連接其它企業(yè)架構(gòu)就實(shí)現(xiàn)集成測(cè)試是非常重要的。這可以讓你來(lái)進(jìn)行以下測(cè)試:

  • 正確配置Spring IoC 容器上下文。

  • 使用JDBC或ORM工具的數(shù)據(jù)訪問(wèn)??赡馨ㄈ鏢QL腳本,Hibernate query,JPA 實(shí)體映射等的正確性驗(yàn)證。

Spring框架提供集成測(cè)試的一流支持,相關(guān)類(lèi)打包在spring-test.jar類(lèi)庫(kù)中。在這個(gè)類(lèi)庫(kù)中,你可以找到org.springframework.test包,有很多方便使用Spring容器進(jìn)行集成測(cè)試的類(lèi),而且同時(shí)不依賴(lài)應(yīng)用服務(wù)器或其它部署環(huán)境。這些測(cè)試會(huì)比單元測(cè)試慢,但會(huì)比Cactus(譯者注:Apache測(cè)試服務(wù)端Java代碼的工具h(yuǎn)ttp://jakarta.apache.org/cactus/index.html )測(cè)試或依靠部署到一個(gè)應(yīng)用服務(wù)器上來(lái)進(jìn)行遠(yuǎn)程測(cè)試要快捷的多。

在2.5版本之前,Spring已經(jīng)提供了面向JUnit 3.8的單元測(cè)試支持. 在2.5版本中, Spring 提供了單元和集成測(cè)試支持 Spring TestContext框架。 它是實(shí)際測(cè)試框架的混合體,因此能夠幫助在多個(gè)測(cè)試環(huán)境包括JUnit 3.8,JUnit 4.4, TestNG等中進(jìn)行測(cè)試。 注意Spring TestContext框架需要Java 5+支持.

8.3.2.?使用哪個(gè)支持框架

Spring團(tuán)隊(duì)推薦使用Spring TestContext框架 來(lái)進(jìn)行所有新的單元測(cè)試和集成測(cè)試,以包括ApplicationContext或需要事務(wù)管理的情況。 但如果你開(kāi)發(fā)在Java5之前的環(huán)境上,就需要繼續(xù)使用JUnit 3.8遺留支持. 另外,顯式 JPA集成測(cè)試支持 依賴(lài)于shadow class載入來(lái)進(jìn)行JPA類(lèi)測(cè)試(class instrumentation)目前只能與JUnit 3.8遺留支持相容。 如果你要測(cè)試的JPA提供者不需要class instrumentation,就推薦使用TestContext框架。

8.3.3.?通用目標(biāo)

Spring集成測(cè)試支持框架提供了一些通用目標(biāo),包括:

  • 跨越各個(gè)測(cè)試案例執(zhí)行期的Spring IoC容器緩存。

  • 測(cè)試fixture實(shí)例的依賴(lài)注入 (這很爽)。

  • 適合集成測(cè)試的事務(wù)管理(這更加爽)。

  • Spring特有的支持類(lèi)在編寫(xiě)集成測(cè)試時(shí)真的很有用。

下面的章節(jié)具體描述每一個(gè)目標(biāo)并提供指向特定支持框架的信息的鏈接。

8.3.3.1.?上下文管理及緩存

Spring集成測(cè)試支持框架提供了ApplicationContext的持久化載入和這些上下文的緩存機(jī)制。 對(duì)已載入上下文的緩存是很重要的,因?yàn)槿绻闶窃谝粋€(gè)大型的項(xiàng)目中,啟動(dòng)時(shí)間會(huì)成為一個(gè)問(wèn)題――不是因?yàn)镾pring本身的開(kāi)銷(xiāo), 而是因?yàn)榭縎pring容器來(lái)初始化的對(duì)象需要很長(zhǎng)時(shí)間。比如一個(gè)有50-100 Hibernate映射文件的項(xiàng)目可能需要10-20秒來(lái)載入映射文件, 而每次單一測(cè)試fixture的每個(gè)單一測(cè)試前都要這樣的時(shí)間開(kāi)銷(xiāo),減慢了整體的測(cè)試進(jìn)度進(jìn)而降低效率。

測(cè)試類(lèi)通常會(huì)提供一個(gè)數(shù)組來(lái)包含XML配置元數(shù)據(jù)的資源路徑――通常是classpath――來(lái)配置應(yīng)用。這通常和web.xml或其它部署描述中指定的配置路徑是相同或相近的。

默認(rèn)情況下,一旦載入,ApplicationContext將在每次測(cè)試中重用。 這樣啟動(dòng)的開(kāi)銷(xiāo)將只需要一次(每個(gè)測(cè)試fixture),接下來(lái)的測(cè)試執(zhí)行就會(huì)快得多。 在一些少見(jiàn)的會(huì)“污染”應(yīng)用上下文的案例中需要重新載入―― 例如,改變一個(gè)bean定義或應(yīng)用對(duì)象的狀態(tài)―― Spring的測(cè)試支持提供了在執(zhí)行下一個(gè)測(cè)試前讓測(cè)試fixture重新載入配置并重建應(yīng)用上下文的機(jī)制。

上下文管理和緩存使用:

  • JUnit 3.8遺留支持

  • TestContext框架

8.3.3.2.?測(cè)試fixtures依賴(lài)注入

當(dāng)Spring集成測(cè)試支持框架載入你的應(yīng)用上下文時(shí),它們能通過(guò)依賴(lài)注入選擇性配置測(cè)試類(lèi)實(shí)例。 這提供了一個(gè)方便的機(jī)制來(lái)使用預(yù)先在應(yīng)用上下文中配置的bean來(lái)搭建測(cè)試fixture。 很大的好處就是你可以在各種測(cè)試場(chǎng)景中重用應(yīng)用上下文(例如配置Spring管理的對(duì)象圖, 事務(wù)代理DataSource等),從而能避免為單個(gè)的測(cè)試案例重復(fù)進(jìn)行測(cè)試fixture搭建。

作為例子,考慮一個(gè)場(chǎng)景:我們有一個(gè)HibernateTitleDao類(lèi)來(lái)實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)邏輯,假設(shè)是Title域?qū)ο蟆N覀兿M帉?xiě)測(cè)試所有以下方面的集成測(cè)試:

  • Spring配置: 最基本的,是否所有與HibernateTitleDao bean相關(guān)的配置都是正確和存在的?

  • Hibernate映射配置文件: 是否所有映射都是正確的并且lazy-loading設(shè)置也到位了?

  • HibernateTitleDao邏輯:是否類(lèi)的已配置示例的實(shí)現(xiàn)與預(yù)期相同?

測(cè)試fixtures依賴(lài)注入使用:

  • JUnit 3.8 遺留支持

  • TestContext框架

8.3.3.3.?事務(wù)管理

訪問(wèn)實(shí)際數(shù)據(jù)庫(kù)的測(cè)試的一個(gè)通常問(wèn)題是對(duì)持久化狀態(tài)的影響。 即使你使用開(kāi)發(fā)數(shù)據(jù)庫(kù),狀態(tài)的改變也可能影響后面的測(cè)試。而且很多操作 ―― 如插入或修改持久化數(shù)據(jù) ―― 不能在事務(wù)外完成(或驗(yàn)證)。

Spring集成測(cè)試支持框架滿(mǎn)足了這些需求。默認(rèn)情況下,對(duì)每次測(cè)試它們會(huì)創(chuàng)建并回滾事務(wù)。 你編寫(xiě)代碼可以假定事務(wù)已經(jīng)存在。如果你在測(cè)試中調(diào)用事務(wù)代理對(duì)象,它們將根據(jù)配置的事務(wù)語(yǔ)義正常響應(yīng)。 另外,如果測(cè)試方法在事務(wù)內(nèi)刪除了選定表的數(shù)據(jù),這個(gè)事務(wù)會(huì)默認(rèn)回滾,數(shù)據(jù)庫(kù)也將回到測(cè)試執(zhí)行前的狀態(tài)。 事務(wù)支持通過(guò)在測(cè)試應(yīng)用上下文中定義的PlatformTransactionManager bean提供。

如果你希望事務(wù)被提交 ―― 不常見(jiàn),但可能你希望特定的測(cè)試插入或修改數(shù)據(jù)庫(kù) ―― Spring集成測(cè)試支持框架 可以通過(guò)調(diào)用一個(gè)繼承下來(lái)的鉤子(Hook)方法或聲明特定注解來(lái)讓事務(wù)提交而不是回滾。

事務(wù)管理使用:

  • JUnit 3.8 遺留支持

  • TestContext框架

8.3.3.4.?集成測(cè)試支持類(lèi)

Spring集成測(cè)試支持框架提供了幾個(gè)abstract支持類(lèi)來(lái)簡(jiǎn)化編寫(xiě)集成測(cè)試。 這些測(cè)試基類(lèi)提供了定義良好的測(cè)試框架鉤子,比如方便的變量實(shí)例和方法,來(lái)訪問(wèn)以下對(duì)象:

  • ApplicationContext: 用來(lái)進(jìn)行顯式bean查找或整體測(cè)試上下文狀態(tài)。

  • JdbcTemplateSimpleJdbcTemplate: 用來(lái)查詢(xún)并確認(rèn)狀態(tài)。 例如,你可能需要在創(chuàng)建對(duì)象并通過(guò)ORM工具持久化到數(shù)據(jù)庫(kù)中的測(cè)試案例運(yùn)行前后進(jìn)行查詢(xún),以確認(rèn)數(shù)據(jù)在數(shù)據(jù)庫(kù)中存在了。 (Spring將確保查詢(xún)?cè)谕粋€(gè)事務(wù)范圍內(nèi)運(yùn)行。) 你需要通知ORM工具來(lái)'flush'變化以確保正常工作, 例如使用Hibernate Session接口的flush()方法。

你經(jīng)常會(huì)提供一個(gè)應(yīng)用范圍的超類(lèi)來(lái)為多個(gè)集成測(cè)試提供有用的實(shí)例變量。

支持類(lèi):

  • JUnit 3.8遺留支持

  • TestContext框架

8.3.4.?JDBC測(cè)試支持

org.springframework.test.jdbc包含有SimpleJdbcTestUtils類(lèi),它 是一個(gè)基于Java5的JDBC相關(guān)工具方法集,用來(lái)簡(jiǎn)化標(biāo)準(zhǔn)數(shù)據(jù)庫(kù)測(cè)試場(chǎng)景。注意AbstractTransactionalJUnit38SpringContextTests, AbstractTransactionalJUnit4SpringContextTests, 和AbstractTransactionalTestNGSpringContextTests 提供了簡(jiǎn)便的方法來(lái)內(nèi)部代理到SimpleJdbcTestUtils。

8.3.5.?常用注解

Spring框架在org.springframework.test.annotation 包中提供了常用的Spring特定的注解集,如果你在Java5或以上版本開(kāi)發(fā),可以在測(cè)試中使用它。

  • @IfProfileValue

    提示一下,注解測(cè)試只針對(duì)特定的測(cè)試環(huán)境。 如果配置的ProfileValueSource類(lèi)返回對(duì)應(yīng)的提供者的名稱(chēng), 這個(gè)測(cè)試就可以啟動(dòng)。這個(gè)注解可以應(yīng)用到一個(gè)類(lèi)或者單獨(dú)的方法。

    @IfProfileValue(name="java.vendor", value="Sun Microsystems Inc.")
    public void testProcessWhichRunsOnlyOnSunJvm() {
        // some logic that should run only on Java VMs from Sun Microsystems
    }

    同時(shí)@IfProfileValue可配置一個(gè)列表 (使用OR 語(yǔ)義) 來(lái)在JUnit環(huán)境中獲得TestNG的測(cè)試組支持。 看下面的例子:

    @IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"})
    public void testProcessWhichRunsForUnitOrIntegrationTestGroups() {
        // some logic that should run only for unit and integration test groups
    }
  • @ProfileValueSourceConfiguration

    類(lèi)級(jí)別注解用來(lái)指定當(dāng)通過(guò)@IfProfileValue注解獲取已配置的profile值時(shí)使用何種ProfileValueSource。 如果@ProfileValueSourceConfiguration沒(méi)有在測(cè)試中聲明,將默認(rèn)使用SystemProfileValueSource

    @ProfileValueSourceConfiguration(CustomProfileValueSource.class)
    public class CustomProfileValueSourceTests {
        // class body...
    }
  • @DirtiesContext

    在測(cè)試方法上出現(xiàn)這個(gè)注解時(shí),表明底層Spring容器在該方法的執(zhí)行中被“污染”,從而必須在方法執(zhí)行結(jié)束后重新創(chuàng)建(無(wú)論該測(cè)試是否通過(guò))。

    @DirtiesContext
    public void testProcessWhichDirtiesAppCtx() {
        // some logic that results in the Spring container being dirtied
    }
  • @ExpectedException

    表明被注解方法預(yù)期在執(zhí)行中拋出一個(gè)異常。預(yù)期異常的類(lèi)型在注解中給定。如果該異常的實(shí)例在測(cè)試方法執(zhí)行中被拋出, 則測(cè)試通過(guò)。同樣的如果該異常實(shí)例沒(méi)有在測(cè)試方法執(zhí)行時(shí)拋出,則測(cè)試失敗。

    @ExpectedException(SomeBusinessException.class)
    public void testProcessRainyDayScenario() {
        // some logic that should result in an Exception being thrown
    }
  • @Timed

    表明被注解的測(cè)試方法必須在規(guī)定的時(shí)間區(qū)間內(nèi)執(zhí)行完成(以毫秒記)。如果測(cè)試執(zhí)行時(shí)間超過(guò)了規(guī)定的時(shí)間區(qū)間,測(cè)試就失敗了。

    注意該時(shí)間區(qū)間包括測(cè)試方法本身的執(zhí)行,任何重復(fù)測(cè)試(參見(jiàn) @Repeat),還有任何測(cè)試fixture的set uptear down時(shí)間。

    @Timed(millis=1000)
    public void testProcessWithOneSecondTimeout() {
        // some logic that should not take longer than 1 second to execute
    }
  • @Repeat

    表明被注解的測(cè)試方法必須重復(fù)執(zhí)行。執(zhí)行的次數(shù)在注解中聲明。

    注意重復(fù)執(zhí)行范圍包括包括測(cè)試方法本身的執(zhí)行,以及任何測(cè)試fixture的set uptear down。

    @Repeat(10)
    public void testProcessRepeatedly() {
        // ...
    }
  • @Rollback

    表明被注解方法的事務(wù)在完成后是否需要被回滾。 如果true,事務(wù)將被回滾,否則事務(wù)將被提交。 使用@Rollback接口來(lái)在類(lèi)級(jí)別覆寫(xiě)配置的默認(rèn)回滾標(biāo)志。

    @Rollback(false)
    public void testProcessWithoutRollback() {
        // ...
    }
  • @NotTransactional

    出現(xiàn)該注解表明測(cè)試方法必須在事務(wù)中執(zhí)行。

    @NotTransactional 
    public void testProcessWithoutTransaction() {
        // ...
    }

注解支持:

  • JUnit 3.8遺留支持: 所有上面列舉的注解都被支持,但必須AbstractAnnotationAwareTransactionalTests類(lèi)聯(lián)合使用,以保證這些注解能起作用。

  • TestContext框架: 支持上面列舉的所有注解,而且提供了額外的TestContext特定注解 (例如@ContextConfiguration@BeforeTransaction等等)。 注意,但是一些注解只有與JUnit聯(lián)合使用時(shí)(例如,基于SpringJUnit4ClassRunner 或JUnit 3.8以及JUnit 4.4的測(cè)試類(lèi))。 詳細(xì)內(nèi)容參見(jiàn)TestContext框架章節(jié)。

8.3.6.?JUnit 3.8遺留支持

Spring JUnit 3.8 遺留支持類(lèi)打包在org.springframework.test包中。 這個(gè)包提供了有用的JUnit TestCase超類(lèi), 擴(kuò)展它可以在容器外集成測(cè)試中引入Spring ApplicationContext類(lèi)或在測(cè)試方法級(jí)別獲得事務(wù)支持。

8.3.6.1.?上下文管理及緩存

AbstractSingleSpringContextTests為基于JUnit 3.8的測(cè)試案例提供了上下文管理和緩存支持。 它暴露了一個(gè)protected方法來(lái)給子類(lèi)覆寫(xiě)以提供上下文定義文件的路徑:

protected String[] getConfigLocations()

這個(gè)方法的實(shí)現(xiàn)必須提供包含XML配置元數(shù)據(jù)的資源路徑 ―― 通常是類(lèi)路徑 ―― 的一個(gè)數(shù)組。 這和在web.xml或其它部署配置中的資源路徑是相同的或基本相同的。 作為可選方案,你也可以覆寫(xiě)下面的方法。詳細(xì)內(nèi)容參見(jiàn)相關(guān)JavaDoc。

protected String[] getConfigPaths()
protected String getConfigPath()

默認(rèn)情況下,一旦配置文件被載入就會(huì)在每個(gè)測(cè)試案例中重用。 這樣構(gòu)建的開(kāi)銷(xiāo)只會(huì)產(chǎn)生一次(每個(gè)測(cè)試fixture),然后后面的測(cè)試執(zhí)行會(huì)快速的多。 在較少的情況下測(cè)試可能“污染”應(yīng)用上下文,需要重新載入 ―― 例如, 改變一個(gè)bean定義或應(yīng)用對(duì)象狀態(tài) ―― 你可以調(diào)用AbstractSingleSpringContextTests類(lèi)中的 setDirty()方法來(lái)讓測(cè)試fixture在執(zhí)行下一個(gè)測(cè)試案例時(shí)重新載 AbstractAnnotationAwareTransactionalTests類(lèi), 你可以使用@DirtiesContext來(lái)對(duì)測(cè)試方法進(jìn)行注解以達(dá)到同樣的效果。

8.3.6.2.?測(cè)試fixture依賴(lài)注入

當(dāng)AbstractDependencyInjectionSpringContextTests類(lèi)(及其子類(lèi))載入你的應(yīng)用上下文時(shí), 它們可以通過(guò)Setter注入選擇性配置你的測(cè)試類(lèi)實(shí)例。你需要做的僅僅是定義實(shí)例變量和相應(yīng)的setter方法。 AbstractDependencyInjectionSpringContextTests將在getConfigLocations()方法定義的配置文件集中自動(dòng)查找相應(yīng)對(duì)象。

假定這樣一個(gè)場(chǎng)景,我們有一個(gè)HibernateTitleDao類(lèi)(在通常目標(biāo)章節(jié)詳述)。 讓我們看基于JUnit 3.8 的測(cè)試類(lèi)實(shí)現(xiàn)本身(我們很快將看看配置本身)。

public final class HibernateTitleDaoTests extends AbstractDependencyInjectionSpringContextTests  {

    // this instance will be (automatically) dependency injected    
    private HibernateTitleDao titleDao;

    // a setter method to enable DI of the 'titleDao' instance variable
    public void setTitleDao(HibernateTitleDao titleDao) {
        this.titleDao = titleDao;
    }

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }

    // specifies the Spring configuration to load for this test fixture
    protected String[] getConfigLocations() {
        return new String[] { "classpath:com/foo/daos.xml" };
    }

}

這個(gè)文件被getConfigLocations()方法指定(比如,"classpath:com/foo/daos.xml") 像這樣:

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

    <!-- this bean will be injected into the HibernateTitleDaoTests class -->
    <bean id="titleDao" class="com.foo.dao.hibernate.HibernateTitleDao">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <!-- dependencies elided for clarity -->
    </bean>

</beans>

AbstractDependencyInjectionSpringContextTests類(lèi)使用按類(lèi)型自動(dòng)裝配。 因此如果你有多個(gè)bean定義是相同的類(lèi)型,就不能在這些bean中使用這種方法。 這種情況下,你可以使用繼承的applicationContext實(shí)例變量并實(shí)現(xiàn)顯式的查找(比如), 調(diào)用applicationContext.getBean("titleDao")方法。

如果你不希望在測(cè)試案例中使用依賴(lài)注入,只要不聲明任何public setter方法就可以簡(jiǎn)單實(shí)現(xiàn)。 作為替代的,你可以擴(kuò)展AbstractSpringContextTests - 在org.springframework.test 包中的JUnit 3.8集成測(cè)試支持類(lèi)層次的根 - 它僅僅包含了一些載入Spring上下文的簡(jiǎn)單方法,而且不在測(cè)試fixture中使用依賴(lài)注入。

8.3.6.2.1.?字段級(jí)別(Field Level)注入

如果不管何種原因,你的測(cè)試fixture中沒(méi)有setter方法,Spring可以對(duì)protected字段進(jìn)行依賴(lài)注入。 下面是前面使用字段級(jí)注入示例的新版本(Spring XML文件無(wú)需改變,僅僅需要改變測(cè)試fixture)。

public final class HibernateTitleDaoTests extends AbstractDependencyInjectionSpringContextTests  {

    public HibernateTitleDaoTests() {
        // switch on field level injection
        setPopulateProtectedVariables(true);
    }

    // this instance will be (automatically) dependency injected
    protected HibernateTitleDao titleDao;

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }

    // specifies the Spring configuration to load for this test fixture
    protected String[] getConfigLocations() {
        return new String[] { "classpath:com/foo/daos.xml" };
    }

}

在字段注入的情況下,不能使用自動(dòng)裝配:protected 實(shí)例變量被作為已配置的Spring容器的bean 查找名。

8.3.6.3.?事務(wù)管理

AbstractTransactionalSpringContextTests類(lèi) 依賴(lài)于應(yīng)用上下文中定義的PlatformTransactionManager bean。 名字是無(wú)關(guān)緊要的,因?yàn)槭褂昧?span id="wjcelcm34c" class="emphasis">按類(lèi)型自動(dòng)裝配.

通常你會(huì)擴(kuò)展其子類(lèi)AbstractTransactionalDataSourceSpringContextTests。 這個(gè)類(lèi)也需要在應(yīng)用上下文中有一個(gè)DataSource bean定義(同樣可以是任意名稱(chēng))。 它創(chuàng)建一個(gè)JdbcTemplate實(shí)例變量,可以用來(lái)方便的查詢(xún)和刪除選定表的內(nèi)容( 請(qǐng)記住默認(rèn)情況下事務(wù)將被回滾,因而這樣做是安全的)。

如果你希望編程式提交事務(wù) ―― 不常見(jiàn)但對(duì)于特殊的插入數(shù)據(jù)庫(kù)的測(cè)試很有用 ―― 你可以調(diào)用繼承自AbstractTransactionalSpringContextTests類(lèi)的setComplete() 方法。 這將使事務(wù)提交而不是回滾。作為可替代的,如果你在Java 5或更高環(huán)境中開(kāi)發(fā)擴(kuò)展AbstractAnnotationAwareTransactionalTests類(lèi), 你可以使用@Rollback(false)來(lái)注解測(cè)試方法,以通過(guò)配置獲得相同的效果。

通過(guò)調(diào)用endTransaction()方法,這里可以在測(cè)試案例完成時(shí)中止一個(gè)事務(wù)。 默認(rèn)將回滾事務(wù),除非前面調(diào)用了setComplete()方法。 這個(gè)特性當(dāng)你希望測(cè)試‘?dāng)噙B接’的 數(shù)據(jù)對(duì)象行為是很有用,比如事務(wù)外的web或遠(yuǎn)程使用的Hibernate映射實(shí)體。 通常懶加載錯(cuò)誤只有通過(guò)UI測(cè)試發(fā)現(xiàn)。如果你調(diào)用endTransaction()方法 可以保證JUnit測(cè)試時(shí)UI操作的正確性。

8.3.6.4.?JUnit 3.8 遺留支持類(lèi)

當(dāng)你擴(kuò)展 AbstractTransactionalDataSourceSpringContextTests類(lèi)時(shí),你將需要訪問(wèn)下面protected 實(shí)例變量:

  • applicationContext(ConfigurableApplicationContext): 繼承自AbstractSingleSpringContextTests類(lèi)。使用它可以進(jìn)行顯式bean查找或測(cè)試整個(gè)的上下文狀態(tài)。

  • jdbcTemplate: 繼承自AbstractTransactionalDataSourceSpringContextTests類(lèi),用于查詢(xún)已確認(rèn)狀態(tài)。 例如,應(yīng)用代碼要?jiǎng)?chuàng)建一個(gè)對(duì)象,然后使用ORM工具將其持久化,這時(shí)你想在測(cè)試代碼執(zhí)行前后對(duì)其進(jìn)行查詢(xún),以確定數(shù)據(jù)是否插入到數(shù)據(jù)庫(kù)中(Spring會(huì)保證該查詢(xún)運(yùn)行在相同事務(wù)內(nèi))。你需要告訴你的ORM工具‘清空’其改變以正確完成任務(wù),例如,使用HibernateSession接口的flush()方法。

8.3.6.5.?Java 5+ 專(zhuān)有支持

8.3.6.5.1.?使用注解的事務(wù)相關(guān)測(cè)試

在上述常用注解之外, org.springframework.test.annotation包也有一個(gè)抽象 JUnit TestCase類(lèi)來(lái)提供注解驅(qū)動(dòng)的集成測(cè)試支持。

AbstractAnnotationAwareTransactionalTests類(lèi)擴(kuò)展了AbstractTransactionalDataSourceSpringContextTests類(lèi), 并通過(guò)擴(kuò)展fixture引入一些(Spring專(zhuān)有)的注解。AbstractAnnotationAwareTransactionalTests 支持所有常用注解章節(jié)中列舉的注解, 而且包括Spring的@Transactional注解,以顯式配置事務(wù)語(yǔ)義。

8.3.6.5.2.?JPA支持類(lèi)

org.springframework.test.jpa包提供了基于Java 持久化API(JPA)的測(cè)試支持類(lèi)。

  • AbstractJpaTests是一個(gè)方便的JPA相關(guān)測(cè)試的支持類(lèi), 它提供了和AbstractTransactionalDataSourceSpringContextTests相同的功能和即使在進(jìn)行JPA規(guī)范需要的性能測(cè)試時(shí)也相同的性能。 它暴露了一個(gè)EntityManagerFactory接口和一個(gè)共享的EntityManager接口。 需要注入一個(gè)EntityManagerFactory接口, 以及通過(guò)超類(lèi)獲得DataSource接口和JpaTransactionManager接口。

  • AbstractAspectjJpaTests類(lèi)是AbstractJpaTests的子類(lèi), 它激活了AspectJ 的裝載期織入并能夠讓AspectJ指定一個(gè)自定義的aop.xml文件路徑。

8.3.7.?Spring TestContext Framework

Spring TestContext Framework (在org.springframework.test.context包中) 提供了一般的、注解驅(qū)動(dòng)的單元和集成測(cè)試支持,它對(duì)使用的測(cè)試框架不做要求,可以使用JUnit 3.8、JUnit 4.4, TestNG 5.5等等。 TestContext框架也強(qiáng)調(diào)了約定優(yōu)于配置的重要性,它提供了合理的默認(rèn)值,同時(shí)也可以通過(guò)基于注解的配置進(jìn)行改寫(xiě)。

除了一般的測(cè)試基礎(chǔ)設(shè)施外,TestContext框架還以抽象支持類(lèi)的形式對(duì)JUnit 3.8、JUnit 4.4和TestNG 5.5提供了顯式的支持。 針對(duì)JUnit 4.4,該框架還提供了一個(gè)自定義的Runner,這使得用戶(hù)無(wú)需繼承特定的類(lèi)就可以編寫(xiě)測(cè)試類(lèi)了。

以下章節(jié)給出了TestContext框架的內(nèi)部概覽。 如果你僅僅關(guān)注如何使用該框架而不是使用你自己的監(jiān)聽(tīng)器去擴(kuò)展它,那么請(qǐng)直接跳到配置(上下文管理和緩存、 依賴(lài)注入、事務(wù)管理)、 支持類(lèi)及注解支持章節(jié)。

8.3.7.1.?主要的抽象

框架的核心包括TestContextTestContextManager類(lèi)以及TestExecutionListener接口。 每次測(cè)試都會(huì)創(chuàng)建TestContextManagerTestContextManager管理了一個(gè)TestContext, 它負(fù)責(zé)持有當(dāng)前測(cè)試的上下文。TestContextManager還負(fù)責(zé)在測(cè)試執(zhí)行過(guò)程中更新TestContext的狀態(tài)并代理到TestExecutionListener, 它用來(lái)監(jiān)測(cè)測(cè)試實(shí)際的執(zhí)行(如提供依賴(lài)注入、管理事務(wù)等等)。請(qǐng)查看JavaDoc及Spring測(cè)試套件以獲得進(jìn)一步的信息和各種配置示例。

  • TestContext:封裝測(cè)試執(zhí)行的上下文,與當(dāng)前使用的測(cè)試框架無(wú)關(guān)。

  • TestContextManagerSpring TestContext Framework的主入口點(diǎn), 負(fù)責(zé)管理單獨(dú)的TestContext并在定義好的執(zhí)行點(diǎn)上向所有注冊(cè)的TestExecutionListener發(fā)出事件通知: 測(cè)試實(shí)例的準(zhǔn)備,先于特定的測(cè)試框架的前置方法,遲于后置方法。

  • TestExecutionListener:定義了一個(gè)監(jiān)聽(tīng)器API與TestContextManager發(fā)布的測(cè)試執(zhí)行事件進(jìn)行交互, 而該監(jiān)聽(tīng)器就是注冊(cè)到這個(gè)TestContextManager上的。

    Spring提供了TestExecutionListener的三個(gè)實(shí)現(xiàn), 他們都是使用默認(rèn)值進(jìn)行配置的(通過(guò)@TestExecutionListeners注解): DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListenerTransactionalTestExecutionListener, 他們對(duì)測(cè)試實(shí)例提供了依賴(lài)注入支持,處理@DirtiesContext注解,并分別使用默認(rèn)的回滾語(yǔ)義對(duì)測(cè)試提供事務(wù)支持。

以下三個(gè)章節(jié)講述了如何通過(guò)注解配置TestContext框架并提供了使用該框架編寫(xiě)真實(shí)的單元和集成測(cè)試的示例。

8.3.7.2.?上下文管理和緩存

每個(gè)TestContext都會(huì)為其所負(fù)責(zé)的測(cè)試實(shí)例提供上下文和緩存管理。 測(cè)試實(shí)例不會(huì)自動(dòng)訪問(wèn)配置好的ApplicationContext;然而,如果一個(gè)測(cè)試類(lèi)實(shí)現(xiàn)了ApplicationContextAware接口, 那么測(cè)試實(shí)例就會(huì)擁有一個(gè)對(duì)ApplicationContext的引用(假如默認(rèn)已經(jīng)配置好了DependencyInjectionTestExecutionListener)。 AbstractJUnit38SpringContextTests、 AbstractJUnit4SpringContextTestsAbstractTestNGSpringContextTests已經(jīng)實(shí)現(xiàn)了ApplicationContextAware, 因此自帶了上述功能。

與JUnit 3.8遺留支持不同,使用TestContext框架的測(cè)試類(lèi)無(wú)需重寫(xiě)任何protected成員方法來(lái)配置應(yīng)用上下文。 只需在類(lèi)層次上聲明@ContextConfiguration注解就可以完成配置。 如果你的測(cè)試類(lèi)沒(méi)有顯式聲明任何應(yīng)用上下文資源的位置,那么配置好的ContextLoader就會(huì)決定如何以及是否從默認(rèn)的集合位置上加載一個(gè)上下文。 例如,GenericXmlContextLoader - 默認(rèn)的ContextLoader - 會(huì)基于測(cè)試類(lèi)的名字產(chǎn)生一個(gè)默認(rèn)的位置。 如果類(lèi)名叫做com.example.MyTest,那么GenericXmlContextLoader就會(huì)從"classpath:/com/example/MyTest-context.xml"加載應(yīng)用上下文。

package com.example;

@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "classpath:/com/example/MyTest-context.xml"
@ContextConfiguration
public class MyTest {
    // class body...
}

如果默認(rèn)位置不適合你的需求,你可以使用一個(gè)包含了XML配置元數(shù)據(jù)的資源位置的數(shù)組來(lái)配置@ContextConfigurationlocations屬性 (假如已經(jīng)配置好了一個(gè)可以使用XML的ContextLoader)- 一般在classpath上,該屬性被用來(lái)配置應(yīng)用程序。 這就和在web.xml或者其他部署配置中指定配置列表時(shí),方法完全一樣,或者幾乎一樣。 作為另外一種選擇,你可以實(shí)現(xiàn)并配置自己的ContextLoader

@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "/applicationContext.xml" and "/applicationContext-test.xml"
// in the root of the classpath
@ContextConfiguration(locations={"/applicationContext.xml", "/applicationContext-test.xml"})
public class MyTest {
    // class body...
}

@ContextConfiguration還提供了一個(gè)boolean類(lèi)型的inheritLocations屬性以表明是否繼承父類(lèi)的locations。 其默認(rèn)值是true,表明一個(gè)被注解的類(lèi)會(huì)繼承被注解的父類(lèi)中定義的資源位置。 特別地,一個(gè)被注解的類(lèi)的資源位置會(huì)附加到其被注解的父類(lèi)中的資源位置列表上。這樣子類(lèi)就可以繼承資源位置列表。 在下面的例子中,將按順序從"/base-context.xml""/extended-context.xml"中加載針對(duì)ExtendedTestApplicationContext。 所以定義在"/extended-context.xml"中的Beans會(huì)覆蓋掉定義在"/base-context.xml"中的Beans。

@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "/base-context.xml" in the root of the classpath
@ContextConfiguration(locations={"/base-context.xml"})
public class BaseTest {
    // class body...
}

// ApplicationContext will be loaded from "/base-context.xml" and "/extended-context.xml"
// in the root of the classpath
@ContextConfiguration(locations={"/extended-context.xml"})
public class ExtendedTest extends BaseTest {
    // class body...
}

如果將inheritLocations設(shè)為false,那么就會(huì)屏蔽掉父類(lèi)的資源位置,然后可以替換父類(lèi)中定義的任何資源位置。

默認(rèn)情況下, 配置好的ApplicationContext一旦被加載就會(huì)重用到每個(gè)測(cè)試上。這樣設(shè)置的成本僅產(chǎn)生一次(每個(gè)測(cè)試fixture), 隨后測(cè)試的執(zhí)行就會(huì)很快了。在某些不太可能發(fā)生的情況下,一個(gè)測(cè)試可能會(huì)破壞應(yīng)用上下文, 這時(shí)它需要重新加載 - 例如,通過(guò)改變應(yīng)用對(duì)象的bean定義或者狀態(tài) - 你可以使用@DirtiesContext (假設(shè)默認(rèn)已經(jīng)配置了DirtiesContextTestExecutionListener)來(lái)注解測(cè)試方法使得測(cè)試fixture重新加載配置文件并在測(cè)試下次執(zhí)行前重新構(gòu)建應(yīng)用上下文。

8.3.7.3.?測(cè)試fixture的依賴(lài)注入

當(dāng)你配置DependencyInjectionTestExecutionListener時(shí) - 它會(huì)被默認(rèn)配置 - 通過(guò)@TestExecutionListeners注解, 你的測(cè)試實(shí)例依賴(lài)的bean會(huì)被注入,而這些bean是通過(guò)@ContextConfiguration使用Setter注入、Field注入或者兩者都有來(lái)注入的, 到底使用哪種方式取決于你選擇的注解以及你將它們放到setter方法中還是屬性中。為了與Spring 2.5的注解保持一致, 你可以選擇Spring的@Autowired注解或者JSR 250中的@Resource注解。其語(yǔ)義對(duì)于Spring框架來(lái)說(shuō)都是一致的。 例如, 如果你喜歡 按類(lèi)型自動(dòng)織入, 那么請(qǐng)使用@Autowired來(lái)注解你的settter方法或者屬性。另一方面,如果你喜歡按名字注入, 那么請(qǐng)使用@Resource來(lái)注解你的settter方法或者屬性。

提示

TestContext框架沒(méi)有監(jiān)測(cè)測(cè)試實(shí)例的實(shí)例化方式。所以對(duì)構(gòu)造方法使用@Autowired將毫無(wú)意義。

既然@Autowired執(zhí)行按類(lèi)型自動(dòng)編織, 那么如果你有相同類(lèi)型的多個(gè)bean定義的話(huà),對(duì)那些特定的bean就不能使用該方式。在這種情況下, 你可以使用@Resource按名字注入。另外,如果你的測(cè)試類(lèi)實(shí)現(xiàn)了ApplicationContextAware, 就可以直接訪問(wèn)ApplicationContext并調(diào)用applicationContext.getBean("titleDao")執(zhí)行一個(gè)顯式的查找。

如果你不想讓你的測(cè)試實(shí)例使用依賴(lài)注入,只要不將@Autowired或者@Resource注解到任何屬性或者setter方法上就行了。 另一種方式,你可以使用@TestExecutionListeners并忽略掉監(jiān)聽(tīng)器列表中的DependencyInjectionTestExecutionListener.class就可以完全禁用依賴(lài)注入。

考慮如下場(chǎng)景:我們有一個(gè)類(lèi),名字叫HibernateTitleDao(通用目標(biāo)章節(jié)已經(jīng)進(jìn)行了介紹)。 首先,讓我們看看基于JUnit 4.4的測(cè)試類(lèi)的實(shí)現(xiàn),它使用@Autowired進(jìn)行屬性注入(在所有示例代碼之后我們會(huì)查看應(yīng)用上下文的配置)。 注意:下面代碼的依賴(lài)注入行為并不是特定于JUnit 4.4的。同樣的依賴(lài)注入技術(shù)可以使用在任何測(cè)試框架中。

@RunWith(SpringJUnit4ClassRunner.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration(locations={"daos.xml"})
public final class HibernateTitleDaoTests {

    // this instance will be dependency injected by type
    @Autowired    
    private HibernateTitleDao titleDao;

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }
}

此外,我們可以使用@Autowired進(jìn)行setter注入。

@RunWith(SpringJUnit4ClassRunner.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration(locations={"daos.xml"})
public final class HibernateTitleDaoTests {

    // this instance will be dependency injected by type
    private HibernateTitleDao titleDao;

    @Autowired
    public void setTitleDao(HibernateTitleDao titleDao) {
        this.titleDao = titleDao;
    }

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }
}

現(xiàn)在讓我們看看使用@Resource進(jìn)行屬性注入的一個(gè)示例。

@RunWith(SpringJUnit4ClassRunner.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration(locations={"daos.xml"})
public final class HibernateTitleDaoTests {

    // this instance will be dependency injected by name
    @Resource
    private HibernateTitleDao titleDao;

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }
}

最后,這是使用@Resource進(jìn)行setter注入的一個(gè)示例。

@RunWith(SpringJUnit4ClassRunner.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration(locations={"daos.xml"})
public final class HibernateTitleDaoTests {

    // this instance will be dependency injected by name
    private HibernateTitleDao titleDao;
    
    @Resource
    public void setTitleDao(HibernateTitleDao titleDao) {
        this.titleDao = titleDao;
    }

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }
}

上面的代碼使用了相同的XML上下文文件,@ContextConfiguration注解使用了這些信息(如 "daos.xml"),它是這樣的:

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

    <!-- this bean will be injected into the HibernateTitleDaoTests class -->
    <bean id="titleDao" class="com.foo.dao.hibernate.HibernateTitleDao">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <!-- dependencies elided for clarity -->
    </bean>

</beans>

8.3.7.4.?事務(wù)管理

在TestContext框架中,事務(wù)是由TransactionalTestExecutionListener進(jìn)行管理的, 默認(rèn)情況下這是通過(guò)@TestExecutionListeners注解進(jìn)行配置的, 即使你沒(méi)有在測(cè)試類(lèi)中顯式聲明 @TestExecutionListeners注解。 為了支持事務(wù),你必須通過(guò)@ContextConfiguration在應(yīng)用上下文中加載一個(gè)PlatformTransactionManager bean。 此外,你必須在類(lèi)或方法層次上聲明一個(gè)@Transactional。

請(qǐng)參考TestContext框架的注解支持中的@TransactionConfiguration以了解類(lèi)層次的事務(wù)配置(例如為事務(wù)管理器設(shè)置bean名稱(chēng)以及默認(rèn)的回滾標(biāo)志)。

為每個(gè)測(cè)試方法配置事務(wù)時(shí)有幾種選項(xiàng)。如果對(duì)于整個(gè)類(lèi)來(lái)說(shuō)事務(wù)不可用,那么可以使用@Transactional來(lái)顯式注解方法。 與此類(lèi)似,如果對(duì)于整個(gè)類(lèi)來(lái)說(shuō)事務(wù)可用,那么可以使用@NotTransactional來(lái)注解方法表明不為該方法增加事務(wù)。 你可以使用@Rollback注解覆蓋類(lèi)級(jí)別的默認(rèn)的回滾設(shè)置進(jìn)而針對(duì)一個(gè)特定的測(cè)試方法控制其事務(wù)的提交。

請(qǐng)注意,AbstractTransactionalJUnit38SpringContextTestsAbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests已經(jīng)在類(lèi)級(jí)別預(yù)先配置好了事務(wù)支持。

偶爾你需要在一個(gè)事務(wù)性測(cè)試方法前、后執(zhí)行某些代碼,而這些代碼是處在事務(wù)上下文之外的,例如, 在測(cè)試執(zhí)行前去驗(yàn)證初始的數(shù)據(jù)庫(kù)狀態(tài)或者在測(cè)試執(zhí)行后驗(yàn)證期待的事務(wù)提交行為(舉例來(lái)說(shuō),該測(cè)試被配置為不進(jìn)行回滾的)。 支持@BeforeTransaction@AfterTransaction注解的TransactionalTestExecutionListener正好適用于這種情況。 使用這些注解之一來(lái)注解測(cè)試類(lèi)中任何的public void方法, 同時(shí)TransactionalTestExecutionListener會(huì)保證你的事務(wù)方法之前的代碼或者事務(wù)方法之后的代碼會(huì)在正確的時(shí)間執(zhí)行。

提示

任意前置方法 (如使用JUnit 4的@Before所注解的方法)和后置方法 (如使用JUnit 4的@After所注解的方法)都會(huì)一個(gè)事務(wù)中得到執(zhí)行。 此外,使用 @NotTransactional注解的測(cè)試不會(huì)執(zhí)行@BeforeTransaction@AfterTransaction所注解的方法。

下面的基于JUnit 4的示例展示了一個(gè)假想的集成測(cè)試場(chǎng)景,重點(diǎn)闡述了事務(wù)相關(guān)的注解。請(qǐng)查看參考手冊(cè)的TestContext框架注解支持章節(jié)以了解進(jìn)一步的信息和配置示例。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
public class FictitiousTransactionalTest {

	@BeforeTransaction
	public void verifyInitialDatabaseState() {
		// logic to verify the initial state before a transaction is started
	}

	@Before
	public void setUpTestDataWithinTransaction() {
		// set up test data within the transaction
	}

	@Test
	// overrides the class-level defaultRollback setting
	@Rollback(true)
	public void modifyDatabaseWithinTransaction() {
		// logic which uses the test data and modifies database state
	}

	@After
	public void tearDownWithinTransaction() {
		// execute "tear down" logic within the transaction
	}

	@AfterTransaction
	public void verifyFinalDatabaseState() {
		// logic to verify the final state after transaction has rolled back
	}

	@Test
	@NotTransactional
	public void performNonDatabaseRelatedAction() {
		// logic which does not modify database state
	}
}

8.3.7.5.?TestContext支持類(lèi)

8.3.7.5.1.?JUnit 3.8支持類(lèi)

org.springframework.test.context.junit38包為基于JUnit 3.8的測(cè)試用例提供了支持類(lèi)。

  • AbstractJUnit38SpringContextTests

    對(duì)集成了Spring TestContext Framework與JUnit 3.8環(huán)境中的ApplicationContext測(cè)試支持的TestCase進(jìn)行了抽象。 當(dāng)你繼承AbstractJUnit38SpringContextTests類(lèi)時(shí),你就可以訪問(wèn)到protected的成員變量:

    • applicationContext:使用它進(jìn)行顯式的bean查找或者測(cè)試整個(gè)上下文的狀態(tài)。

  • AbstractTransactionalJUnit38SpringContextTests

    對(duì)為JDBC訪問(wèn)增加便捷功能的AbstractJUnit38SpringContextTests事務(wù)擴(kuò)展進(jìn)行抽象。 需要在ApplicationContext中定義一個(gè)javax.sql.DataSource bean和一個(gè)PlatformTransactionManager bean。 當(dāng)你繼承AbstractTransactionalJUnit38SpringContextTests類(lèi)時(shí),你就可以訪問(wèn)到protected的成員變量:

    • applicationContext:從AbstractJUnit38SpringContextTests父類(lèi)繼承。使用它執(zhí)行bean的查找或者測(cè)試整個(gè)上下文的狀態(tài)

    • simpleJdbcTemplate:在查詢(xún)以確認(rèn)狀態(tài)時(shí)非常有用。例如,應(yīng)用代碼要?jiǎng)?chuàng)建一個(gè)對(duì)象,然后使用ORM工具將其持久化, 這時(shí)你想在測(cè)試代碼執(zhí)行前后對(duì)其進(jìn)行查詢(xún),以確定數(shù)據(jù)是否插入到數(shù)據(jù)庫(kù)中(Spring會(huì)保證該查詢(xún)運(yùn)行在相同事務(wù)內(nèi))。 你需要告訴你的ORM工具‘flush’其改變以正確完成任務(wù),例如,使用HibernateSession接口的flush()方法。

8.3.7.5.2.?JUnit 4.4支持類(lèi)

org.springframework.test.context.junit4包為基于JUnit 4.4的測(cè)試用例提供了支持類(lèi)。

  • AbstractJUnit4SpringContextTests

    對(duì)集成了Spring TestContext Framework與JUnit 4.4環(huán)境中的ApplicationContext測(cè)試支持的基本測(cè)試類(lèi)進(jìn)行了抽取。

    當(dāng)你繼承AbstractJUnit4SpringContextTests時(shí),你就可以訪問(wèn)到protected的成員變量:

    • applicationContext:使用它進(jìn)行顯式的bean查找或者測(cè)試整個(gè)上下文的狀態(tài)。

  • AbstractTransactionalJUnit4SpringContextTests

    對(duì)為JDBC訪問(wèn)增加便捷功能的AbstractJUnit4SpringContextTests事務(wù)擴(kuò)展進(jìn)行抽象。 需要在ApplicationContext中定義一個(gè)javax.sql.DataSource bean和一個(gè)PlatformTransactionManager bean。

    當(dāng)你繼承AbstractTransactionalJUnit4SpringContextTests類(lèi)時(shí),你就可以訪問(wèn)到下列protected的成員變量:

    • applicationContext:繼承自父類(lèi)AbstractJUnit4SpringContextTests。 使用它執(zhí)行bean的查找或者測(cè)試整個(gè)上下文的狀態(tài)

    • simpleJdbcTemplate:當(dāng)通過(guò)查詢(xún)來(lái)確認(rèn)狀態(tài)時(shí)非常有用。例如,應(yīng)用代碼要?jiǎng)?chuàng)建一個(gè)對(duì)象, 然后使用ORM工具將其持久化,這時(shí)你想在測(cè)試代碼執(zhí)行前后對(duì)其進(jìn)行查詢(xún),以確定數(shù)據(jù)是否插入到數(shù)據(jù)庫(kù)中。 (Spring會(huì)保證該查詢(xún)運(yùn)行在相同事務(wù)內(nèi)。)你需要告訴你的ORM工具‘flush’其改變以正確完成任務(wù),例如, 使用HibernateSession接口的flush()方法。

提示

這些類(lèi)僅僅為擴(kuò)展提供了方便。 如果你不想將你的測(cè)試類(lèi)綁定到Spring的類(lèi)上 - 例如,如果你要直接擴(kuò)展你想測(cè)試的類(lèi) - 只需要通過(guò)@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration、@TestExecutionListeners等注解來(lái)配置你自己的測(cè)試類(lèi)就可以了。

8.3.7.5.3.?定制JUnit 4.4運(yùn)行器

Spring TestContext Framework通過(guò)一個(gè)可定制的運(yùn)行器提供了與JUnit 4.4的完全集成。 通過(guò)使用@Runwith(SpringJUnit4ClassRunner.class)來(lái)注解測(cè)試類(lèi),開(kāi)發(fā)者可以實(shí)現(xiàn)標(biāo)準(zhǔn)的JUnit 4.4單元和集成測(cè)試, 同時(shí)還能獲得TestContext框架的好處,如對(duì)加載應(yīng)用上下文的支持,測(cè)試實(shí)例的依賴(lài)注入,執(zhí)行事務(wù)性測(cè)試方法等等。 下面的代碼清單顯示了使用定制的Spring Runner來(lái)配置一個(gè)測(cè)試類(lèi)的最小需求。 注意,我們使用一個(gè)空的列表來(lái)配置@TestExecutionListeners以便禁用默認(rèn)的監(jiān)聽(tīng)器, 否則需要通過(guò)@ContextConfiguration配置一個(gè) ApplicationContext。

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({})
public class SimpleTest {

	@Test
	public void testMethod() {
		// execute test logic...
	}
}
8.3.7.5.4.?TestNG支持類(lèi)

org.springframework.test.context.testng包為基于TestNG的測(cè)試用例提供了支持類(lèi)。

  • AbstractTestNGSpringContextTests

    對(duì)集成了Spring TestContext Framework與TestNG環(huán)境中的ApplicationContext測(cè)試支持的基礎(chǔ)測(cè)試類(lèi)進(jìn)行了抽象。

    當(dāng)你繼承AbstractTestNGSpringContextTests時(shí),就可以訪問(wèn)到下列protected的成員變量:

    • applicationContext:使用它進(jìn)行顯式的bean查找或者測(cè)試整個(gè)上下文的狀態(tài)。

  • AbstractTransactionalTestNGSpringContextTests

    對(duì)為JDBC訪問(wèn)增加便捷功能的AbstractTestNGSpringContextTests事務(wù)擴(kuò)展進(jìn)行抽象。 需要在ApplicationContext中定義一個(gè)javax.sql.DataSource bean和一個(gè)PlatformTransactionManager bean。

    當(dāng)你繼承AbstractTransactionalTestNGSpringContextTests類(lèi)時(shí),就可以訪問(wèn)下列protected的成員變量:

    • applicationContext:繼承自父類(lèi)AbstractTestNGSpringContextTests。使用它執(zhí)行bean的查找或者測(cè)試整個(gè)上下文的狀態(tài)。

    • simpleJdbcTemplate:當(dāng)通過(guò)查詢(xún)來(lái)確認(rèn)狀態(tài)時(shí)非常有用。例如,應(yīng)用代碼要?jiǎng)?chuàng)建一個(gè)對(duì)象, 然后使用ORM工具將其持久化,這時(shí)你想在測(cè)試代碼執(zhí)行前后對(duì)其進(jìn)行查詢(xún),以確定數(shù)據(jù)是否插入到數(shù)據(jù)庫(kù)中。(Spring會(huì)保證該查詢(xún)運(yùn)行在相同事務(wù)內(nèi)。) 你需要告訴你的ORM工具‘flush’其改變以正確完成任務(wù),例如,使用HibernateSession接口的flush()方法。

提示

這些類(lèi)僅僅為擴(kuò)展提供了方便。 如果你不想將你的測(cè)試類(lèi)綁定到Spring的類(lèi)上 - 例如,如果你要直接擴(kuò)展你想測(cè)試的類(lèi) - 只需要通過(guò) @ContextConfiguration、@TestExecutionListeners等注解來(lái)配置你自己的測(cè)試類(lèi)就可以了。 并使用TestContextManager來(lái)手工監(jiān)測(cè)你的測(cè)試類(lèi)。 請(qǐng)查看AbstractTestNGSpringContextTests的源代碼以了解如何檢測(cè)你自己的測(cè)試類(lèi)。

8.3.7.6.?TestContext框架注解支持

Spring TestContext Framework支持通用注解章節(jié)提到的所有注解。 然而下面的這些注解只有配合JUnit才能使用(比如搭配SpringJUnit4ClassRunner或者 JUnit 3.8及JUnit 4.4支持類(lèi))。

  • @IfProfileValue

  • @ProfileValueSourceConfiguration

  • @ExpectedException

    協(xié)同使用Spring的@ExpectedException注解與JUnit 4的@Test(expected=...)會(huì)導(dǎo)致一個(gè)不可避免的沖突。 因此當(dāng)與JUnit 4集成時(shí),開(kāi)發(fā)者必須選擇其中一個(gè),在這種情況下建議使用顯式的JUnit 4配置。

  • @Timed

    Spring的@Timed注解與JUnit 4的@Test(timeout=...)支持具有不同的語(yǔ)義。 特別地,鑒于JUnit 4處理測(cè)試執(zhí)行超時(shí)(如通過(guò)在一個(gè)單獨(dú)的線(xiàn)程中執(zhí)行測(cè)試方法)的方式, 我們不可能在一個(gè)事務(wù)上下文中的測(cè)試方法上使用JUnit的@Test(timeout=...)配置。因此, 如果你想將一個(gè)測(cè)試方法配置成計(jì)時(shí)具事務(wù)性的, 你就必須聯(lián)合使用Spring的@Timed@Transactional注解。 還值得注意的是@Test(timeout=...)只管測(cè)試方法本身執(zhí)行的次數(shù),如果超出的話(huà)立刻就會(huì)失??; 然而,@Timed關(guān)注的是測(cè)試執(zhí)行的總時(shí)間(包括建立和銷(xiāo)毀操作以及重復(fù)),并且不會(huì)令測(cè)試失敗。

  • @Repeat

Spring TestContext Framework還支持下面這些非特定于測(cè)試的注解,并且保持其語(yǔ)義不變。

  • @Autowired

  • @Qualifier

  • @Resource (javax.annotation)如果JSR-250可用

  • @PersistenceContext (javax.persistence)如果JPA可用

  • @PersistenceUnit (javax.persistence)如果JPA可用

  • @Required

  • @Transactional

下面的列表包含了特定于Spring TestContext Framework的所有注解。請(qǐng)查看相應(yīng)的JavaDoc以了解進(jìn)一步的信息,包括默認(rèn)的屬性值等等。

  • @ContextConfiguration

    定義類(lèi)級(jí)別的元數(shù)據(jù)以決定如何加載和配置ApplicationContext。特別地, @ContextConfiguration定義了要加載的應(yīng)用上下文資源位置以及用來(lái)加載上下文的ContextLoader策略。

    @ContextConfiguration(locations={"example/test-context.xml"}, loader=CustomContextLoader.class)
    public class CustomConfiguredApplicationContextTests {
        // class body...
    }

    注意:@ContextConfiguration默認(rèn)情況下為繼承的資源位置提供了支持。 查看上下文管理和緩存章節(jié)及JavaDoc來(lái)了解更多的示例和細(xì)節(jié)信息。

  • @TestExecutionListeners

    定義類(lèi)級(jí)別的元數(shù)據(jù),TestExecutionListeners會(huì)使用TestContextManager進(jìn)行注冊(cè)。 通常,@TestExecutionListeners@ContextConfiguration會(huì)搭配使用。

    @ContextConfiguration
    @TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListener.class})
    public class CustomTestExecutionListenerTests {
        // class body...
    }

    注意:@TestExecutionListeners默認(rèn)情況下為繼承的監(jiān)聽(tīng)器提供了支持。查看JavaDoc來(lái)了解更多的示例和細(xì)節(jié)信息。

  • @TransactionConfiguration

    為配置事務(wù)性測(cè)試定義了類(lèi)級(jí)別的元數(shù)據(jù)。特別地,如果需要的PlatformTransactionManager不是“transactionManager”的話(huà), 那么可以顯式配置驅(qū)動(dòng)事務(wù)的PlatformTransactionManager的bean名字。此外, 可以將defaultRollback標(biāo)志改為false。通常, @TransactionConfiguration@ContextConfiguration搭配使用。

    @ContextConfiguration
    @TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
    public class CustomConfiguredTransactionalTests {
        // class body...
    }
  • @BeforeTransaction

    表明被注解的public void方法應(yīng)該在測(cè)試方法的事務(wù)開(kāi)始之前執(zhí)行, 該事務(wù)是通過(guò)@Transactional注解來(lái)配置的。

    @BeforeTransaction
    public void beforeTransaction() {
        // logic to be executed before a transaction is started
    }
  • @AfterTransaction

    表明被注解的public void方法應(yīng)該在測(cè)試方法的事務(wù)結(jié)束之后執(zhí)行, 該事務(wù)是通過(guò)@Transactional注解來(lái)配置的。

    @AfterTransaction
    public void afterTransaction() {
        // logic to be executed after a transaction has ended
    }

8.3.8.?PetClinic示例

在Spring的完整發(fā)行包里包含了PetClinic示例應(yīng)用,它以JUnit 4.4環(huán)境闡述了Spring TestContext Framework的幾個(gè)特性。 大多數(shù)功能包含在AbstractClinicTests里,部分內(nèi)容列舉如下:

@ContextConfiguration
public abstract class AbstractClinicTests extends AbstractTransactionalJUnit4SpringContextTests {

	@Autowired
	protected Clinic clinic;

	@Test
	public void getVets() {
		Collection<Vet> vets = this.clinic.getVets();
		assertEquals("JDBC query must show the same number of vets",
			super.countRowsInTable("VETS"), vets.size());
		Vet v1 = EntityUtils.getById(vets, Vet.class, 2);
		assertEquals("Leary", v1.getLastName());
		assertEquals(1, v1.getNrOfSpecialties());
		assertEquals("radiology", (v1.getSpecialties().get(0)).getName());
		// ...
	}
	
	// ...
}

注意:

  • 該測(cè)試用例繼承了AbstractTransactionalJUnit4SpringContextTests類(lèi), 從這里它繼承了針對(duì)依賴(lài)注入的配置(通過(guò)DependencyInjectionTestExecutionListener)和事務(wù)性行為(通過(guò)TransactionalTestExecutionListener)。

  • clinic成員變量 - 要測(cè)試的應(yīng)用程序?qū)ο?- 是通過(guò)@Autowired進(jìn)行依賴(lài)注入的。

  • testGetVets()方法說(shuō)明如何使用繼承下來(lái)的countRowsInTable()方法來(lái)輕松驗(yàn)證表中的行數(shù), 進(jìn)而測(cè)試應(yīng)用代碼的正確行為。這點(diǎn)允許實(shí)現(xiàn)更強(qiáng)大的測(cè)試,減少了對(duì)確切測(cè)試數(shù)據(jù)的依賴(lài)。例如,無(wú)需打斷測(cè)試就可以向數(shù)據(jù)庫(kù)中增加新行。

  • 像很多使用數(shù)據(jù)庫(kù)的集成測(cè)試一樣,AbstractClinicTests中的大多數(shù)測(cè)試依賴(lài)于測(cè)試運(yùn)行前數(shù)據(jù)庫(kù)中已有的最小量的數(shù)據(jù)。 但是你可能在測(cè)試用例中改變數(shù)據(jù)庫(kù)――當(dāng)然,在同一個(gè)事務(wù)中。

PetClinic應(yīng)用支持三種數(shù)據(jù)訪問(wèn)技術(shù) - JDBC、Hibernate及JPA。無(wú)需任何特定的資源位置, 只要聲明了@ContextConfiguration,那么AbstractClinicTests類(lèi)就會(huì)從默認(rèn)位置加載其應(yīng)用上下文, 該默認(rèn)位置為"AbstractClinicTests-context.xml",這里聲明了一個(gè)通用的DataSource。 子類(lèi)指定了額外的上下文位置,這就要求它必須聲明一個(gè)PlatformTransactionManagerClinic的一個(gè)具體實(shí)現(xiàn)。

例如,PetClinic測(cè)試的Hibernate實(shí)現(xiàn)包含以下實(shí)現(xiàn)。針對(duì)這個(gè)例子請(qǐng)注意,HibernateClinicTests沒(méi)有包含一行代碼: 我們只需聲明@ContextConfiguration并且測(cè)試?yán)^承于AbstractClinicTests。 既然無(wú)需任何特定的資源位置就可以聲明@ContextConfiguration, 那么Spring TestContext Framework就會(huì)從"AbstractClinicTests-context.xml" (例如繼承的位置)和 "HibernateClinicTests-context.xml"中加載應(yīng)用上下文, 同時(shí)"HibernateClinicTests-context.xml" 中定義的bean會(huì)覆蓋掉"AbstractClinicTests-context.xml"中定義的bean。

@ContextConfiguration
public class HibernateClinicTests extends AbstractClinicTests { }

正如你在PetClinic應(yīng)用中所看到的,Spring配置文件被劃分成多個(gè)文件。對(duì)于大型應(yīng)用來(lái)說(shuō)都是這樣做的, 配置位置通常被指定在一個(gè)針對(duì)該應(yīng)用程序集成測(cè)試的通用基類(lèi)中。 這樣的基類(lèi)還可以增加有用的實(shí)例變量 - 很自然地由依賴(lài)注入組裝 - 例如使用Hibernate的應(yīng)用中的HibernateTemplate。

從長(zhǎng)遠(yuǎn)來(lái)看,集成測(cè)試中的Spring配置文件應(yīng)該與部署環(huán)境中的一樣。一個(gè)可能的不同點(diǎn)是數(shù)據(jù)庫(kù)連接池和事務(wù)基礎(chǔ)設(shè)施。 如果你正部署到一個(gè)完整的應(yīng)用服務(wù)器上,那你可能會(huì)使用其連接池(通過(guò)JNDI訪問(wèn))和JTA實(shí)現(xiàn)。 這樣依賴(lài),在生產(chǎn)階段你會(huì)使用JndiObjectFactoryBean來(lái)獲得DataSourceJtaTransactionManager。 在容器外的集成測(cè)試中無(wú)法使用JNDI和JTA,因此你應(yīng)該為他們使用一個(gè)替代的組合, 如Commons DBCP BasicDataSourceDataSourceTransactionManager或者HibernateTransactionManager。 你可以將這種不同的行為放到一個(gè)單獨(dú)的XML文件中,在應(yīng)用服務(wù)器和獨(dú)立于其他配置的'本地'配置中自由選擇,這不會(huì)在測(cè)試和產(chǎn)品環(huán)境中造成差異。 此外,建議使用屬性文件來(lái)存放連接信息:請(qǐng)查看PetClinic應(yīng)用以了解這些。

Previous article: Next article: