参考文档 3.1 Ver 1.6.1(build on ) 南磊译 本文档的拷贝适用于您自己使用或是分发给他人, 您不能从中收取任何费用并且任何拷贝必 须含有这个版权声明, 无论是分发打印版还是电子版 版权说明 : Spring 中文版参考文档由南磊翻译, 您可以自由使用或分发他人,

Size: px
Start display at page:

Download "参考文档 3.1 Ver 1.6.1(build on ) 南磊译 本文档的拷贝适用于您自己使用或是分发给他人, 您不能从中收取任何费用并且任何拷贝必 须含有这个版权声明, 无论是分发打印版还是电子版 版权说明 : Spring 中文版参考文档由南磊翻译, 您可以自由使用或分发他人,"

Transcription

1 参考文档 3.1 Ver 1.6.1(build on ) 南磊译 本文档的拷贝适用于您自己使用或是分发给他人, 您不能从中收取任何费用并且任何拷贝必 须含有这个版权声明, 无论是分发打印版还是电子版 版权说明 : Spring 中文版参考文档由南磊翻译, 您可以自由使用或分发他人, 但是您不能从中收取任何费用, 任何拷贝必须有版权声明 如有商业用途倾向, 必须联系原作者和译者 翻译文档支持网站为 : ( 翻译期间, 每周五在此更新 ) 译者联系方式如下, 有对翻译的任何意见和建议, 不要犹豫, 请点击 : 电子邮件 :nanlei1987@gmail.com 微博 :

2 第一部分 Spring framework 概述...6 第 1 章 Spring Framework 介绍 依赖注入和控制反转 模块 核心容器 数据访问 / 整合 Web AOP 和基础组件 测试 使用方案 依赖管理和命名规约 Spring 依赖和基于 Spring Maven 依赖管理 Ivy 依赖管理 日志 不使用 Commons Logging 使用 SLF4J 使用 Log4J 第二部分 Spring 3 的新特性 第 2 章 Spring 3.0 的新特性和增强 Java 改进的文档 新的文章和教程 新的模块组织方式和系统构建方式 新特性概述 为 Java 5 更新的核心 API Spring 表达式语言 控制反转 (IoC) 容器 基于 Java 的 bean 元数据 使用组件定义 bean 的元数据 通用的类型转换系统和字段格式化系统 数据层 Web 层 全面的 REST 支持 的增加 声明式的模型验证 先期对 Java EE 6 的支持 嵌入式数据库的支持 第 3 章 Spring 3.1 的新特性和增强 新特性概述 第三部分核心技术... 29

3 第 4 章 IoC 容器 Spring IoC 容器和 bean 的介绍 容器概述 配置元数据 实例化容器 处理基于 XML 的配置元数据 使用容器 Bean 概述 命名 bean 在 bean 定义外面起别名 实例化 bean 使用构造方法实例化 使用静态工厂方法来实例化 使用实例工厂方法来实例化 依赖 依赖注入 基于构造方法的依赖注入 基于 setter 方法的依赖注入 解决依赖过程 依赖注入示例 深入依赖和配置 直接值 ( 原生类型,String, 等 ) 引用其它 bean( 协作者 ) 内部 bean 集合 null 和空字符串 使用 p- 命名空间的 XML 快捷方式 使用 c- 命名空间的 XML 快捷方式 复合属性名称 使用 depends-on 延迟初始化 bean 自动装配协作者 自动装配的限制和缺点 从自动装配中排除 bean 方法注入 查找方法注入 任意方法的替代 Bean 的范围 单例范围 原型范围 单例 bean 和原型 bean 依赖 请求, 会话和全局会话范围 初始化 Web 配置 请求范围... 65

4 会话范围 全局会话范围 各种范围的 bean 作为依赖 自定义范围 创建自定义范围 使用自定义范围 自定义 bean 的性质 生命周期回调 初始化回调 销毁回调 默认的初始化和销毁方法 组合生命周期机制 启动和关闭回调 在非 Web 应用中, 优雅地关闭 Spring IoC 容器 ApplicationContextAware 和 BeanNameAware 其它 Aware 接口 Bean 定义的继承 容器扩展点 使用 BeanPostProcessor 来自定义 bean 示例 :BeanPostProcessor 风格的 Hello World 示例 :RequiredAnnotationBeanPostProcessor 使用 BeanFactoryPostProcessor 自定义配置元数据 示例 :PropertyPlaceholderConfigurer 示例 :PropertyOverrideConfigurer 使用 FactoryBean 来自定义实例化逻辑 基于注解的容器配置 使用限定符来微调基于注解的自动装配 CustomAutowireConfigurer 类路径扫描和管理的组件 和更多典型注解 自动检测类和 bean 的注册 使用过滤器来自定义扫描 使用组件定义 bean 的元数据 命名自动检测组件 为自动检测组件提供范围 使用注解提供限定符元数据 使用 JSR 330 标准注解 进行依赖注入 注解的标准等同 标准方法的限制

5 4.12 基于 Java 的容器配置 基本概念 使用 AnnotationConfigApplicationContext 实例化 Spring 容器 简单构造 使用 register(class<?>...) 来编程构建容器 使用 scan(string..) 开启组件扫描 支持 Web 应用的 AnnotationConfigWebApplicationContext 构成基于 Java 的配置 注解 结合 Java 和 XML 配置

6 第一部分 Spring framework 概述 Spring framework 是一个轻量级的解决方案, 在构建一站式企业级应用程序上有很大的 潜能 Spring 是模块化的, 允许你使用仅需要的部分, 而不需要引入其余部分 你可以使用 IoC 容器, 和 Struts 一起使用, 而且你也可以仅仅使用 Hibernate 整合代码或者是 JDBC 抽象层 Spring framework 支持声明式的事务管理, 通过 RMI 或 Web Service 远程访问业务逻辑 代码, 并且提供多种持久化数据的选择 它提供饿了一个全功能的 MVC 框架, 允许你显式 地整合 AOP 到软件中 Spring 被设计成非侵入式的, 也就是说你的业务逻辑代码通常是不会对 Spring 框架本身 产生依赖的 在你的整合层面 ( 比如数据访问层 ), 一些依赖于数据访问技术和 Spring 的类库是会存在的 但是, 也很容易将这些依赖从你剩余的代码中分离出来 本文档是 Spring 框架特性的参考指南 如果你有任何想法, 建议或是对本文档的疑问, 请发送到用户邮件列表中或者是在线论坛中, 论坛地址是

7 第 1 章 Spring Framework 介绍 Spring Framework 是一个 Java 平台, 它提供了对用 Java 语言开发应用程序的一种广泛的 基础支持 Spring 本身来控制这个基础, 那么你就可以集中精力于应用程序的开发了 Spring 允许你从 普通 Java 对象 (POJO) 来构建应用程序, 并且将非侵入地企业级服务应用于 POJO 中 这种能力不仅适用于 Java SE 编程模型, 也适用于全部或部分的 Java EE 作为应用程序的开发人员, 下面就是可以使用 Spring 平台所含优点的例子 : 编写 Java 方法来执行数据库事务而不需要处理相关的事务 API 编写本地的 Java 方法来访问远程程序而不需要处理远程访问 API 编写本地的 Java 方法来执行管理操作而不需要处理 JMX 的 API 编写本地的 Java 方法来处理消息操作而不需要处理 JMS 的 API 1.1 依赖注入和控制反转 背景 问题是,[ 它们 ] 反向控制哪一方面?,2004 年,Martin Fowler 在他个人站点提出 了这个关于控制反转 (IoC) 的问题 Fowler 建议重命名这个原则, 使得它更好地自我解释, 同时提出了依赖注入 要深入了解 IoC 和 DI, 可以参考 Fowler 的文章, 地址是 : Java 应用程序 -- 一个宽松的术语, 囊括了从被限制的 applet 到 n 层服务器端的企业级 应用程序的全部 典型的应用是, 包含了组成独特应用程序的合作对象 那么在应用程序 中的这些对象就会有相互依赖关系 尽管 Java 平台提供了丰富的应用程序开发功能, 但是它也缺乏组织基本模块到整体的 方式, 而是把这个任务留给了系统架构师和开发人员去解决 也就是说, 你可以设计如工厂, 抽象工厂, 构建者, 装饰者和服务定位器等设计模式来组合各个类, 以及构成该应用程序的 对象的实例 然而, 这些模式都是最简单的 : 最佳的做法是给定一个名称, 并且描述这个模 式做了些什么, 在哪里可以应用它, 它所强调的问题是什么等等 模式可以使得你必须自己实现的最佳实践形式化 Spring Framework 的控制反转 (Inversion of Control,IoC) 组件提供了组合不同的组件到 完整可用的应用程序的形式化方法 Spring Framework 编写了形式化的设计模式作为顶级对 象, 你可以用来整合到你自己的应用程序中 很多组织和研究机构使用 Spring Framework 的 这个方式来设计健壮的, 可维护的应用程序 1.2 模块 Spring Framework 包含了很多特性, 并且组织成 20 个模块 这些模块分为核心容器, 数据访问 / 整合,Web,AOP(Aspect Oriented Programming, 面向切面编程 ), 基础组件和测 试, 在下图中来展示这些模块

8 Spring 框架概要 核心容器 核心容器 (4.1 节 ) 包含了核心 (Core), Bean 组件 (Beans), 上下文 (Context) 和表 达式语言 (Expression Language) 模块 核心和 Bean(4.1 节 ) 模块提供了框架部分的基础, 包含 IoC 和依赖注入特性 BeanFactory 是工厂模式的精密实现 它去掉了编程实现单例的需要, 并允许你解除配置信息, 以及实际程序逻辑的特定依赖之间的耦合 上下文 (4.14 节 ) 模块构建了由核心和 Bean(4.1 节 ) 模块提供的坚实基础 : 它可以让 你以框架中的风格来访问对象, 这和 JNDI 的注册是相似的 上下文模块集成了来自 Bean 模 块的特性, 并且加入了对国际化 ( 比如使用资源束 ) 的支持, 事件传播, 资源加载和 Servlet 容器显式创建上下文 上下文模块也支持 Java EE 特性, 比如 EJB,JMX 和基本的远程调用 ApplicationContext 接口是上下文模块的焦点 表达式语言 ( 第 7 章 ) 模块提供了强大的表达式语言, 在运行时查询和操作对象图 这 是 JSP 2.1 规范中的统一表达式语言 (Unified EL) 的一个扩展 该表达式语言支持设置和获 取属性值, 属性定义, 方法调用, 访问数组, 集合以及索引的上下文 支持逻辑和数字运算, 命名变量 还支持从 Spring 的 IoC 容器中以名称来获取对象 它也支持 list 的投影和选择操作, 还有普通的 list 聚集

9 1.2.2 数据访问 / 整合 数据访问 / 整合层由 JDBC,ORM,OXM,JMS 和事务模块组成 JDBC(13.1 节 ) 模块提供了 JDBC 抽象层, 它移除了冗长的 JDBC 编码, 但解析了数据库 提供商定义的特定错误代码 ORM(14.1 节 ) 模块提供了对流行的对象 - 实体映射 API 的整合层, 包含 JPA(14.5 节 ), JDO(14.4 节 ),Hibernate(14.3 节 ) 和 ibatis(14.6 节 ) 使用 ORM 包你就可以使用全部的 O/R- 映射框架并联合其它 Spring 提供的特性, 比如之前所提到的简单声明式的事务管理特性 OXM( 第 15 章 ) 模块提供了支持 JAXB,Castor,XMLBeans,JiBX, 以及 Xstream 对对象 /XML 映射实现的抽象层 Java 消息服务 (JMS, 第 22 章 ) 模块包含生成和处理消息的特性 事务 ( 第 11 章 ) 模块支持对实现特定接口的类和所有 POJO( 普通 Java 对象 ) 的编程 式和声明式的事务管理 Web Web 层由 Web,Web-Servlet,Web-Struts 和 Web-Portlet 模块组成 Spring 的 Web 模块提供了基本的面向 Web 整合的特性, 比如文件上传功能,IoC 容器 的初始化使用了 Servlet 的监听器和变形的 Web 应用上下文 它还包含了和 Web 相关的 Spring 远程调用支持的部分 Web-Servlet 模块包含了 Spring 对 Web 应用的模型 - 视图 - 控制器 (MVC,16.1 节 ) 模式的实现 Spring 的 MVC 框架提供了一个在领域模型代码和 Web 表单之间的整洁分离, 并且 整合了其它所有 Spring 框架的特性 Web-Struts 模块包含了使用 Spring 应用程序整合经典的 Strtus Web 层的支持类 要注意 这个支持从 Spring 3.0 开始就废弃了 那么可以考虑迁移应用程序到 Struts 2.0 和 Spring 的整 合或者是单纯的 Spring MVC 方案 Web-Portlet 模块提供用于 portlet 环境和 Web-Servlet 模块功能镜像的 MVC 实现 AOP 和基础组件 Spring 的 AOP(8.1 节 ) 模块提供了 AOP 联盟 - 允许的的面向切面的编程实现, 允许你定 义如方法 - 拦截器和横切点来整洁地解耦应该被分离的功能实现代码 使用源代码级的元数据功能, 也可以混合行为信息到代码中, 这个方式和.NET 的属性很相似 分离的 Aspects 模块提供对 AspectJ 的整合 基础组件模块提供了对类的基础支持, 还有类加载器的实现来用于特定的应用服务器 测试 测试模块支持 Spring 组件,Junit 或 Test NG 的测试 它提供了 Spring 应用上下文的一致 加载并缓存这些上下文内容 它也提供 mock 对象, 你可以用来孤立地测试代码

10 1.3 使用方案 前面描述的模块使得 Spring 可以在很多方案中作为业务逻辑实现的选择, 从 applet 到 使用了 Spring 的事务管理功能和 Web 框架整合, 功能完善的企业级应用程序 典型地功能完善的 Spring Web 应用 Spring 的声明式事务管理特性 (11.5 节 ) 使得 Web 应用程序可以全部事务化, 就好像 使用了 EJB 容器管理的事务 全部的自定义业务逻辑可以使用简单的 POJO 来实现并且被 Spring 的 IoC 容器来管理 其它的服务包含对发送邮件的支持, 验证对 Web 层独立, 这可以 让你选择在哪里执行验证规则 Spring 的 ORM 支持对 JPA,Hibernate,JDO 和 ibatis 进行了整 合 ; 比如, 当使用 Hibernate 时, 你可以继续使用已有的映射文件和标准的 Hibernate 的 SessionFactory 配置 表单控制器无缝地整合了 Web 层和领域模型, 也去除了 ActionForm 或其它为领域模型转换 HTTP 参数的类的需要

11 使用了第三方 Web 框架的 Spring 中间层 有时, 开发和运行环境并不允许你完全转换到一个不同的框架中 Spring Framework 不强制你使用其中的部分 ; 它并不是一个所有或没有的方案 已有使用了 WebWork,Struts, Tapestry 或其它 UI 框架构建的前端应用程序也可以使用基于 Spring 的中间层来进行整合, 这就允许你去使用 Spring 的事务特性 你仅仅需要做的是给业务逻辑装上 ApplicationContext, 对整合的 Web 层使用 WebApplicationContext

12 远程调用使用方案 当你需要通过 Web Service 访问已有的代码时, 你可以使用 Spring 的 Hessian-, Burlap-,Rmi- 或 JaxPpcProxyFactory 类 对已有的应用程序开启远程访问并不困难 EJB 包装已有的 POJO Spring Framework 也提供了对企业级 Java Bean(EJB, 译者注 ) 的访问和抽象层 ( 第 21 章 ), 这就可以重用已有的 POJO, 可以扩展 包装它们到无状态会话 bean, 不安全的 Web 应用程序可能也需要声明式安全

13 1.3.1 依赖管理和命名规约 依赖管理和依赖注入是不同的概念 要在应用程序中添加 Spring 的优雅特性 ( 比如依 赖注入 ), 你需要放置所需的类库 (jar 文件 ), 并且添加到运行时环境的类路径中, 通常在 编译时也是需要这些类库文件的 这些依赖不是注入的虚拟组件, 而是文件系统 ( 通常来说是这样 ) 上的物理资源 依赖管理的过程包括定位资源, 存储它们, 并将它们添加到类路径 中 依赖可以是直接的 ( 比如应用程序在运行时需要 Spring), 或者是间接的 ( 比如应用程 序需要的 commons-dbcp 组件还依赖于 commons-pool 组件 ) 间接的依赖也被认为是 过 度的, 而且那些依赖本身就难以识别和管理 如果你决定使用 Spring, 那么你需要获得 Spring 的 jar 包, 其中要包括你所需要使用的 Spring 的模块 为了使用的便捷,Spring 被打包成各个模块的集合, 尽可能地分离其中的相 互依赖, 那么如果你不想编写 Web 应用程序, 就不需要添加 spring-web 模块的 jar 包 要参 考 Spring 模块的库, 本指南使用了一个可以速记的命名规约, spring-* 或者 spring-*.jar, 这里的 * 代表了各模块的短名称 ( 比如, spring-core, spring-webmvc,spring-jms 等 ) 实际上 jar 文件命名或许就是这种形式的 ( 参考下面的示例 ), 但也有可能不是这种情况, 通常它的文件名中还包含一个版本号 ( 比如, spring-core release.jar) 通常,Spring 在四个不同的地方发布组件 : 在社区下载点 在这儿你可以找到所 有的 Spring jar 包, 它们被压缩到一个 zip 文件中, 可以自由下载 这里 jar 包的命名从 3.0 版本开始, 都以 org.springframework.*-<version>.jar 格式进行 Maven 的中央库, 也是 Maven 默认检索的资源库, 它并不会检索特殊的配置来使用 很多 Spring 所依赖的常用类库也可以从 Maven 的中央库中获得, 同时 Spring 社区的绝 大多数用户都使用 Maven 作为依赖管理工具, 这对于他们来说是很方便的 这里的 jar 包的命名规则是 spring-*-<version>.jar 格式的, 并且 Maven 里的 groupid 是 org.springframework 企业级资源库 (Enterprise Bundle Repository,EBR), 这是由 SpringSource 组织运营的, 同时也提供了和 Spring 整合的所有类库 对于所有 Spring 的 jar 包及其依赖, 这里也有 Maven 和 Ivy 的资源库, 同时这里还有很多开发人员在使用 Spring 编写应用程序时能用 到的其它大量常用类库 而且, 发布的版本, 里程碑版本和开发版本也都部署在这里 这里 jar 文件的命名规则和从社区下载的 (org.springframework.*-<version>.jar) 一致, 并且所依赖的外部类库 ( 不 是来自 SpringSource 的 ) 也是使用的这种 长命名 的形式, 并以 com.springsource 作为前缀 可以参考 FAQ 部分获取更多信息 在 Amazon S3 为开发和里程碑版本发布 ( 最终发布的版本这里也会有 ) 而设置的公共 Maven 资源库 Jar 文件的名称和 Maven 中央库是一样的, 那么这里是获取 Spring 开发 版本的地方, 其它的类库是部署于 Maven 中央库的 那么, 首先你要决定的事情是如何管理这些依赖 : 很多人使用自动化的系统, 比如 Maven 和 Ivy, 但是你也可以手动下载所有的 jar 文件 当使用 Maven 或 Ivy 获取 Spring 时, 之后你 就需要决定从哪里来获取它们 通常来说, 如果你关注 OSGi 的话, 那么就使用 EBR, 因为它对所有的 Spring 依赖兼容 OSGi, 比如 Hibernate 和 Freemarker 如果对 OSGi 不感兴趣, 那么使用哪个下载都是可以的, 但是他们也各有利弊 通常来讲, 为你的项目选择一个或者 备用的一个 ; 但是请不要混用 因为相对于 Maven 中央库而言,EBR 组件非常需要一个不

14 同的命名规则, 那么这就特别重要了 表 1.1 Maven 中央库和 SpringSource EBR 资源库的比较 特性 Maven 中央库 EBR OSGi 的兼容不明确是 组件数量成千上万 ; 所有种类几百个 ; 是 Spring 整合中会用到的 一致的命名规约没有有 命名规约 :GroupId 命名规约 :ArtifactId 命名规约 :Version 发布 质量保证 主机 相异 新组件通常使用域 名, 比如 org.slf4j 老组件 通常仅仅使用组件名, 比 如 log4j 相异 通常是项目或模块 名, 使用连字符 - 分隔, 比如 spring-core,log4j 相异 很多新的组件使用 m.m.m 或 m.m.m.x(m 是 数字,X 是文本 ) 老的使 用 m.m 有一些也不是 顺序是确定的但通常并不 可靠, 所以不是严格的可靠 通常是自动通过 rsync 或 源码控制更新 项目作者 可以上传独立的 jar 文件到 JIRA 根据政策 精确度是作者 的责任 Contegix 提供 由 Sonatype 和一些镜像构成 原始的域名或主包的根路径, 比如 org.springframework 捆绑符号名称, 从主包的路径分离, 比 如 org.springframework.beans 如果 jar 需要修补以保证兼容 OSGi, 那么就附加 com.springsource, 比如 com.springsource.org.apache.log4j OSGi 版本数字 m.m.m.x, 比如 RC3 文本标识符使用相同的数字值规定版本 的字母顺序 手动 ( 由 SpringSource 控制的 JIRA) 宽泛的 OSGi 清单,Maven POM 和 Ivy 元 数据 QA 由 Spring 团队执行 由 SpringSource 的 S3 构成 搜索工具很多 和 SpringSource 工具 整合 通过和 Maven 依赖管理的 STS 来整合 通过 Maven,Roo,CloudFoundry 的 STS 进行宽泛整合 Spring 依赖和基于 Spring 尽管 Spring 提供对整合的支持, 以及对大量企业级应用及其外部工具的支持, 那么它也有心保持它的强制依赖在一个绝对小的数目上 : 你不需要为了简单的使用去定位并下载 ( 甚至是自动地 ) 大量的 jar 来使用 Spring 对于基本的依赖注入那只需要一个必须的外部 依赖, 就是日志 ( 可以参考下面关于日志的深入介绍 ) 下面, 我们来概述一下配置一个基于 Spring 的应用程序所需的基本配置, 首先使用 Maven 和 Ivy 在所有的示例中, 如果有哪一点不清楚, 可以参考你所使用的依赖管理系统的相关文档, 或者参考一些示例代码 Spring 本身在构建时使用了 Ivy 来管理依赖, 而我们

15 大多数的示例却使用 Maven Maven 依赖管理 如果你正使用 Maven 来进行依赖管理, 那么你就不需要明确地提供日志依赖 比如, 要为应用程序配置创建应用上下文并使用依赖注入特性, 那么, 你的 Maven 依赖配置文件 可以是这样的 : <dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>3.0.0.release</version> <scope>runtime</scope> </dependency> </dependencies> 就是这么简单 要注意的是, 如果你在编译代码时不需要使用 Spring 的 API, 那么 scope 元素可以声明为 runtime, 这就可以用于典型的依赖注入用例 在上面的示例中, 我们使用了 Maven 中央库中的命名规约, 那么它就可以在 Maven 中央库或 SpringSource S3 的 Maven 资源库中起作用 要使用 S3 的 Maven 资源库 ( 比如里程碑 版本或开发快照 ) 版本, 那就需要在 Maven 的配置文件中明确地指定资源库的位置 对于 完整发布版, 配置如下 : <repositories> <repository> <id>com.springsource.repository.maven.release</id> <url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories> 对于里程碑版本配置如下 : <repositories> <repository> <id>com.springsource.repository.maven.milestone</id> <url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories> 对于开发快照版本配置如下 :

16 <repositories> <repository> 要使用 SrpingSource 的 EBR 的话, 你还需要一个对依赖不同的命名规约 名称通常很容 易去猜测, 比如这个示例中, 就是 : 你也可能需要明确地声明资源库的位置 ( 仅仅 URL 是重要的 ): 如果你要手动地去管理依赖, 在上面这个声明的资源库 URL 是不可以浏览的, 但是它 也有一个用户界面, 地址是 这可以用来搜索和下 载依赖 它也有 Maven 和 Ivy 配置的代码片段, 你可以复制下来并粘贴到你所使用的工具中, 很方便使用 <id>com.springsource.repository.maven.snapshot</id> <url> <snapshots><enabled>true</enabled></snapshots> </repository> </repositories> <dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>org.springframework.context</artifactid> <version>3.0.0.release</version> <scope>runtime</scope> </dependency> </dependencies> <repositories> <repository> <id>com.springsource.repository.bundles.release</id> <url> e/</url> </repository> </repositories> Ivy 依赖管理 如果你使用 Ivy 来管理依赖, 那么有一些简单的命名规约和配置选项 要配置 Ivy 定位到 SpringSource EBR 中, 需要添加如下的解析器元素到你的配置文件 ivysettings.xml 中 : <resolvers> <url name="com.springsource.repository.bundles.release"> <ivy pattern=" /

17 [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern=" / [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> <url name="com.springsource.repository.bundles.external"> <ivy pattern=" l/ [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> <artifact pattern=" l/ [organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /> </url> </resolvers> 上面的 XML 并不是合法的格式, 因为行太长了 如果你要复制粘贴, 那么要移除中部 url 模式部分结尾额外的行 ( 本文档中已经去除 ) 一旦 Ivy 配置好去查看 EBR, 那么添加依赖就很简单了 只要拉起在资源库浏览器中的 捆绑详细信息页面, 你就会发现为你准备好的 Ivy 代码片段, 那么就可以将它包含到你的依 赖部分中了 比如 ( 在 ivy.xml 中 ): <dependency org="org.springframework" name="org.springframework.core" conf="compile->runtime"/> rev="3.0.0.release" 日志 对于 Spring 来说, 日志是一个非常重要的依赖, 因为 a) 这是唯一强制的外部依赖,b) 开发人员都会想看到他们所使用的工具的一些输出内容, 而且 c)spring 整合了多种实用工具, 它们都会选择一种日志依赖包 应用程序开发人员的目标之一就是在核心位置对整个应用程 序有一个统一的日志配置, 包括对所有的外部组件 因为日志框架有多种选择, 那么这就可 能有些难以确定了 Spring 中强制的日志依赖包是 Jakarta 的 Commons Logging API(JCL) 我们对 Spring 的 编译是基于 JCL 的, 而且我们使扩展了 Spring Framework 的类对 JCL 包的 Log 对象都是可见 的 对于用户来说, 所有 Spring 的版本都使用相同的日志包也是很重要的 : 因为保留了向 后兼容的特性, 那么迁移是很容易进行的, 同理, 扩展 Spring 的应用程序也是这样 我们

18 这样做就是使得 Spring 中的模块明确地使用基于 commons-logging(jcl 的典型实现 ) 的 日志实现, 在编译时也使得其它模块都基于这个日志包 如果你正在使用 Maven 的话, 同 时想知道在哪儿获取到的 commons-logging 依赖, 那就是从 Spring 中被称作是 spring-core 的核心模块中获取的 关于 commons-logging 比较好的做法是你不需要做其它的步骤就可以使应用程序运 行起来 它有一个运行时的查找算法, 在我们都知道的类路径下寻找其它的日志框架, 并且 使用 Spring 认为是比较合适的 ( 或者告诉 Spring 你需要使用的具体是哪一个 ) 一个 如果 没有找到可用的, 那么你会得到一个来自 JDK(java.util.logging 或者简称为 JUL) 本身看起来还不错的日志依赖 那么, 你会发现在很多时候,Spring 应用程序运行中会有日志信息打印 到控制台上, 这点是很重要的 不使用 Commons Logging 不幸的是,commons-logging 的运行时查找算法对最终用户方便是有些问题的 如果我们可以让时光倒流并让 Spring 从现在开始作为一个新的项目进行, 那么我们会使用不 同的日志依赖 首选的日志依赖可能就是 Java 简单的日志门面 (SLF4J), SLF4J 也被 Spring 的开发人员在他们其它应用程序中的很多工具所使用 关闭 commons-logging 也很简单 : 仅仅要确认在运行时, 它的包不在类路径下就可 以了 在 Maven 中要去掉这个依赖, 因为 Spring 依赖声明的时候会带进来, 那么就需要这么来进行 <dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>3.0.0.release</version> <scope>runtime</scope> <exclusions> <exclusion> <groupid>commons-logging</groupid> <artifactid>commons-logging</artifactid> </exclusion> </exclusions> </dependency> </dependencies> 目前这个应用程序可能就不能运行了, 因为在类路径中已经没有了 JCL API 的实现了, 所以要修复这个问题的话, 就要提供另外一种日志的实现了 在下一节中, 我们来说明如何 提供一个其它的 JCL 的实现, 这里, 我们使用 SLF4J 作为示例 使用 SLF4J SLF4J 是一个整洁的日志依赖, 在运行时的效率也比 commons-logging 更高, 因为 SLF4J 使用了编译时构建, 而不是运行时去查找其它整合的日志框架 这也就意味着你可以

19 更明确地在运行时去做些什么, 并且去声明或配置 SLF4J 为很多通用的日志框架提供的绑 定, 所以通常你可以选择已有的一个, 并去绑定配置或管理 SLF4J 为很多通用日志框架提供绑定, 包括 JCL, 并且也可以反向进行 : 桥接其它的日志框架和 SLF4J 本身 所以如果要在 Spring 中使用 SLF4J, 那么就需要使用 SLF4J-JCL 桥来代替 commons-logging 依赖 只要配置好了, 那么来自 Spring 的日志调用就会被翻译成调用 SLF4J 的 API 了, 如果在应用程序中的其它类库使用了原有的 API, 那么会有一个单独的地方 来进行配置和管理的日志 一个常用的选择就是桥接 Spring 到 SLF4J API, 之后提供从 SLF4J 到 Log4J 的明确绑定 你需要提供 4 种依赖 ( 并排除已经存在的 commons-logging 依赖 ): 桥接工具,SLF4J 的 API, 绑定到 Log4J 的工具, 还有 Log4J 本身的实现 那么在 Maven 的配置文件中, 你就可 以这样来做 : <dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>3.0.0.release</version> <scope>runtime</scope> <exclusions> <exclusion> <groupid>commons-logging</groupid> <artifactid>commons-logging</artifactid> </exclusion> </exclusions> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>jcl-over-slf4j</artifactid> <version>1.5.8</version> <scope>runtime</scope> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-api</artifactid> <version>1.5.8</version> <scope>runtime</scope> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-log4j12</artifactid> <version>1.5.8</version> <scope>runtime</scope> </dependency> <dependency> <groupid>log4j</groupid>

20 这样, 看起来好像很多依赖都需要日志了 情况确实是这样, 但 SLF4J 是可选的, 而且 它的性能要比含有类加载器问题的 commons-logging 依赖好很多, 尤其是如果你使用了一个严格限制的容器, 比如 OSGi 平台 据称那也会有性能优势, 因为绑定是编译时进行的, 而不是在运行时 另外, 在 SLF4J 的用户中一个较为常见的选择是使用很少步骤, 同时产生更少的依赖, 那也就是直接绑定到 Logback 上 这会去掉很多额外的绑定步骤, 因为 Logback 本身直接实 现了 SLF4J, 这样的话, 你就仅需要两个依赖的类库, 而不原先的是四个了 ( 就是 jcl-over-slf4j 和 logback) 如果你也确实那么来做了, 你可能还需要从其它外部依 赖 ( 而不是 Spring) 中去掉 slf4j-api 的依赖, 因为在类路径中只保留一个 API 的一个版本就 行了 <artifactid>log4j</artifactid> <version>1.2.14</version> <scope>runtime</scope> </dependency> </dependencies> 使用 Log4J 很多用户出于配置和管理的目的而使用 Log4j 作为日志框架 这样也同样很有效率并且 易于创建, 而且,Log4j 也是我们事实上在构建和测试 Spring 时, 和运行时环境中使用的日 志框架 Spring 本身也提供一些工具来配置和初始化 Log4j, 所以, 在某些模块中它也提供 了可选的在编译时对 Log4j 框架的依赖 要让 Log4j 框架和默认的 JCL 依赖 (commons-logging) 同时起作用, 你所要做的就是要将 Log4j 的类库放到类路径下, 并且提供配置文件 ( 在类路径的根路径下放置 log4j.properties 或 log4j.xml 为名的文件 ) 而对于使用 Maven 的用户来说, 下面 的代码可以是对依赖的声明 : <dependencies> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-context</artifactid> <version>3.0.0.release</version> <scope>runtime</scope> </dependency> <dependency> <groupid>log4j</groupid> <artifactid>log4j</artifactid> <version>1.2.14</version> <scope>runtime</scope> </dependency> </dependencies> 下面是 log4j.properties 打印到控制台的日志的配置示例 :

21 log4j.rootcategory=info, stdout log4j.appender.stdout=org.apache.log4j.consoleappender log4j.appender.stdout.layout=org.apache.log4j.patternlayout log4j.appender.stdout.layout.conversionpattern=%d{absolute %5p %t %c{2:%l - %m%n log4j.category.org.springframework.beans.factory=debug 运行时容器和本地的 JCL 很多用户在容器中运行 Spring 的应用程序, 而该容器本身也提供了 JCL 的实现 比如 IBM 的 Webshphere 应用服务器 (WAS) 就是这种类型的 这通常就会引起问题, 而不幸的是没 有什么解决的方法 ; 很多情况下仅仅从应用程序中去掉 commons-logging 依赖是不够的 我们要清楚地认识这一点 : 这个问题通常和 JCL 本身一同报告出来, 或者是和 commons-logging: 而不是绑定 commons-logging 到另外的框架 ( 这里, 通常是 Log4J) 这就可能会引发问题, 因为 commons-logging 改变了它们在运行时环境里, 在一些容器 中查找老版本 (1.0) 的方式, 而现在很多人使用的是新版本 (1.1) Spring 不会使用任何不 通用的 JCL API 部分, 所以这里不会有问题, 但是 Spring 本身或应用程序尝试去进行日志记录, 你可以发现绑定到 Log4J 是不起作用的 这种在 WAS 上的情况, 最简单的做法就是颠倒类加载器的层次 (IBM 称之为 parent last ), 那么就是使应用程序来控制, 而不是容器来控制 JCL 的依赖 这种选择并不总是开 放的, 但是在公共领域中的替代方法也有其它的建议, 根据确切的版本和容器的特性集, 您 所要求的效果可能会有不同

22 第二部分 Spring 3 的新特性 第 2 章 Spring 3.0 的新特性和增强 如果你使用 Spring Framework, 那么你会看到 Spring 现在主要有两个修订版本 : 一个是 在 2006 年 12 月发布的 Spring 2.0, 还有一个是在 2007 年 11 月发布的 Spring 2.5 而现在是 第三个版本 Spring 3.0 了 Java SE 和 Java EE 支持 Spring Framework 现在完全是基于 Java 5 和 Java 6 版本的 此外,Spring 还兼容 J2EE 1.4 和 Java EE5, 同时也会介绍一些对 Java EE6 的先期支持 2.1 Java 5 框架的整体代码都已经修订到支持 Java 5 的新特性了, 比如泛型, 可变参数和其它的语 言方面的改进 我们也尽最大努力来保持代码的向后兼容性 现在我们也有一致的泛型集合和 Map 的使用, 一致的泛型 FactoryBean 使用, 还有在 Spring AOP 的 API 中对桥接方法的一 致性解决方案 泛型的上下文监听器仅仅自动接收特定的事件类型 所有的比如 TransactionCallback 和 HibernateCallback 回调接口现在也都声明为泛型返回值 总之,Spring 核心代码库都已经为 Java 5 而进行修订和优化了 Spring 的 TaskExecutor 抽象也已经为和 Java 5 的 java.util.concurrent 的紧密整合而更新了 我们现在为可调用特性提供顶级的类的支持, 还有 ExecutorService 适配器,ThreadFactory 的整合等 这和 JSR-236(Java EE6 的并发工具 ) 尽可能是一致的 此外, 我们还提供对使 注解 ( 或者 EJB 3.1 注解 ) 的异步方法调用的支持 2.2 改进的文档 Spring 参考文档也有很大的更新, 并反映出对 Spring 3.0 的改进和新特性 而每一项努力都是来保证在文档中没有错误, 但是多多少少还会存在一些错误 如果你确实发现了任意的错字或者是严重的错误, 你可以在午餐时间把它们画上圈, 然后将这些错误报告给 Spring 的开发团队, 你可以在 JIRA 上打开一个问题 2.3 新的文章和教程 有很多优秀的文章和教程来展示如何开始使用 Spring 3 的新特性 您可以在 Spring 文档页面来阅读它们 示例代码也已经更新采用了 Spring 3 的新特性 此外, 示例代码也已经从源码树中移入 到了专用的 SVN 资源库中 SVN 资源库的访问地址是 : 因此, 这些示例代码就不会跟在 Spring 3 的发布包中了, 需要你从上面提到的资源库中

23 分别去下载 而本文档会继续引用一些示例 ( 特别是 Petclinic) 来说明各种特性 注意 要获取关于 Subversion( 简称为 SVN) 的更多信息, 可以参考 SVN 的项目主页, 地址是 : 2.4 新的模块组织方式和系统构建方式 框架的模块已经被重新修订了, 现在的组织结构是 : 一个源码分支是一个 jar 文件 : org.springframework.aop org.springframework.beans org.springframework.context org.springframework.context.support org.springframework.expression org.springframework.instrument org.springframework.jdbc org.springframework.jms org.springframework.orm org.springframework.oxm org.springframework.test org.springframework.transaction org.springframework.web org.springframework.web.portlet org.springframework.web.servlet org.springframework.web.struts 注意 : 原来的 Spring.jar 文件包含了几乎所有框架内容, 而现在不再提供了 现在我们使用新的 Spring 构建系统, 从熟知的 Spring Web Flow 2.0 中而来, 它给了我们 如下的特性 : 基于 Ivy 的 Spring 构建 系统 一致的开发过程 一致的依赖管理 一致的 OSGi 清单生成 2.5 新特性概述 下面列出的是 Spring 3.0 的新特性, 我们在后面章节的详细讲述中会覆盖到这些特性 Spring 表达式语言 IoC 增加 / 基于对 Java 的 bean 元数据的支持 通用的类型转换和字段格式化系统 对象转 XML 映射功能 (OXM), 这是从 Spring Web Service 项目中迁出的 全面的 REST 支持

24 声明式的模型验证 先期对 Java EE 6 的支持 嵌入式数据库的支持 为 Java 5 更新的核心 API BeanFactory 接口尽可能地返回该类型 bean 的实例 : T getbean(class<t> requiredtype) T getbean(string name, Class<T> requiredtype) Map<String, T> getbeansoftype(class<t> type) 现在,Spring 的 TaskExecutor 接口扩展了 java.util.concurrent.executor 扩展的 AsyncTaskExecutor 支持标准的可调用特性 新的基于 Java 5 的转换 API 和 SPI: 无状态的 ConversionService 和转换器 取代标准 JDK 的 PropertyEditors 泛型 ApplicationListener<E> Spring 表达式语言 Spring 引入了一种表达式语言, 这和统一的 EL 在语法上很相似, 但是提供了很多新特性 这种表达式语言可以用于定义基于 XML 和注解的 bean, 也可以作为表达式语言的基础, 支持贯穿整个 Spring 框架的组合 这些新功能的详细内容可以在第 7 章 Spring 表达式语言 (SpEL) 中看到 Spring 表达式语言被用来为 Spring 社区提供一个单一的, 支持良好的表达式语言, 可以 用于 Spring 系列的所有产品中 它的语言特性由 Spring 系列产品的所有项目的需求来共同驱动, 包括基于 Eclipse 的 SpringSource Tool Suite(SpringSource 组织开发的工具套件, 译者 注 ) 代码完成支持工具的需求 下面是表达式语言如何被用于配置数据库属性设置的示例代码 : <bean class="mycompany.rewardstestdatabase"> <property name="databasename" value="#{systemproperties.databasename"/> <property name="keygenerator" value="#{strategybean.databasekeygenerator"/> 如果你使用注解来配置组件, 那么这个功能也是可用的 public class RewardsTestDatabase public void setdatabasename(string dbname) public void setkeygenerator(keygenerator kg) {

25 2.5.3 控制反转 (IoC) 容器 基于 Java 的 bean 元数据 从 Java Config 项目中引入的一些核心特性现在也被加入到 Spring Framework 中了 下面是一个 Java 类提供基本配置信息的示例, 使用了新的 Java Config 特性 : package public class AppConfig { String jdbcurl; String username; String public FooService fooservice() { return new public FooRepository foorepository() return new HibernateFooRepository(sessionFactory()); public SessionFactory sessionfactory() { // 装配一个 session factory AnnotationSessionFactoryBean asfactorybean = new AnnotationSessionFactoryBean(); asfactorybean.setdatasource(datasource()); // 其它配置 return public DataSource datasource() { return new DriverManagerDataSource(jdbcUrl, username, password);

26 要让它发挥作用, 你需要在应用上下文的 XML 文件中添加如下的组件扫描项 <context:component-scan base-package="org.example.config"/> <util:properties id="jdbcproperties" location="classpath:org/example/config/jdbc.properties"/> 或者你可以直接使用 AnnotationConfigApplicationContext 注解的类 : public static void main(string[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); FooService fooservice = ctx.getbean(fooservice.class); fooservice.dostuff(); 参考 节 使用 AnnotationConfigApplicationContext 实例化 Spring 容器 来参考关 于 AnnotationConfigApplicationContext 的全部内容 使用组件定义 bean 注解的方法也可以支持内部的 Spring 组件 它们贡献工厂 bean 的定义到容器中 参考 节 使用组件定义 bean 的元数据 来获取更多信息 通用的类型转换系统和字段格式化系统 通用的类型转换系统 ( 参考 6.5 节 ) 已经引入了 系统现在被 SpEL 使用来进行类型转换, 当绑定 bean 的属性值时也会被 Spring 容器和数据绑定器使用 此外, 格式化 ( 参考 6.6 节 )SPI 也被引入了, 来格式化字段值 这个 SPI 对 JavaBean 的 PropertyEditors 提供了简单的, 更强壮替代, 在如 Spring MVC 的客户端环境中来使用 数据层 现在, 对象到 XML 映射功能 (OXM) 被从 Spring Web Service 项目中移到 Spring Framework 的核心中 这个功能可以在 org.springframework.oxm 包下找到 关于使用 OXM 模块 的更多信息可以在第 15 章使用 O/X 映射器编组 XML 找到 Web 层 对于 Web 层来说, 最令人兴奋的新特性是对构建 RESTful Web Service 和 Web 应用程序 的支持 也有一些新的注解可以用于任意的 Web 应用程序

27 全面的 REST 支持 对构建 RESTful 应用程序服务器端的支持已经作为已有的注解驱动的 MVC web 框架而提 供了 客户端的支持由 RestTemplate 类来提供, 和其它的模板类是相似的, 比如 JdbcTemplate 和 JmsTemplate 服务器和客户端两者的 REST 功能都使用 HttpConverter 来在对象和它们在 HTTP 请求和响应代表之间方便的转换 MarshallingHttpMessageConverter 使用之前提到的对象到 XML 映射功能 可以参考 MVC( 第 16 章 ) 和 RestTemplate( 节 ) 部分获取更多信息 的增加 mvc 命名空间被引入来大大简化 Spring MVC 的配置 的注解也被加入了 注解映射 cookie 值 ( 节 ) 注解映射请求头部属性 ( 节 ) 来获取更多信息 声明式的模型验证 一些验证增强 (6.7 节 ), 包括 JSR303 支持, 使用 Hibernate 校验器作为默认提供者 先期对 Java EE 6 的支持 注解 ( 或 EJB 3.1 注解 ) 我们提供异步方法调用 JSR 303,JSF 2.0,JPA 2.0 等 嵌入式数据库的支持 现在也提供了对嵌入式 Java 数据库引擎 (13.8 节 ) 的方便支持, 包括 HSQL,H2 和 Derby

28 第 3 章 Spring 3.1 的新特性和增强 在 Spring 3.0 引入的支持之上构建,Spring 3.1 现在还在开发中, 目前 Spring 3.1 M2 才刚 刚发布 3.1 新特性概述 ( 该部分内容待 Spring 3.1 GA 发布后翻译 )

29 第三部分核心技术 参考文档的这一部分涵盖了 Spring Framework 中不可或缺的技术 这些内容最主要的是 Spring Framework 的控制反转 (IoC) 容器 Spring Framework 的 IoC 容器的完全使用是紧跟其后的 Spring 的面向切面编程 (AOP) 技术的完全覆盖 Spring Framework 有它自己的 AOP 框架, 在概念上很容易去理解, 在 Java 企业级编程中, 它成功 地解决了 80% 的 AOP 需求的功能点 也提供了涵盖的 Spring 和 AspectJ( 目前最丰富的 - 在功能方面 当然是在 Java 企业 级空间中最成熟的 AOP 实现 ) 的整合 最终, 通过测试驱动开发 (test-driven-development,tdd) 的软件开发方法, 也是 Spring 团队所主张的, 所以 Spring 对整合测试的支持也涵盖到了 ( 沿袭单元测试的最佳实践 ) Spring 团队也发现了 IoC 的正确使用, 当然, 这会让单元和集成测试更容易 (setter 方法的存在和 类的适当的构造方法可以使得它们很容易的在测试时连接在一起, 而不需要设立服务定位器 注册和诸如此类的方法 ) 这章专门的测试又往说服你 第 4 章,IoC 容器 第 5 章, 资源 第 6 章, 验证, 数据绑定和类型转换 第 7 章,Spring 表达式语言 (SpEL) 第 8 章, 使用 Spring 进行面向切面编程 第 9 章,Spring 的 AOP API 第 10 章, 测试

30 第 4 章 IoC 容器 4.1 Spring IoC 容器和 bean 的介绍 本章涵盖了 Spring Framework 的控制反转容器 (IoC)[ 参考 1.1 节的背景 ] 原则的实现 IoC 也被称为是依赖注入 (DI) 这是一个对象定义它们依赖的过程, 也就是说, 它们使用的其它对象, 仅仅通过构造方法参数, 工厂方法参数或在对象被创建后的实例上设置的属性, 亦或者是从工厂方法返回的参数 之后容器在它创建 bean 的时候注入那些依赖 这个过程 是根本上的反向, 因此名称是控制反转 (IoC), bean 本身控制实例化或直接地使用类的构 造来定位它的依赖, 或者是如服务定位器模式的机制 org.springframework.beans 和 org.springframework.context 包是 Spring Framework 的 IoC 容器的基础 BeanFactory 接口提供高级的配置机制, 可以管理任意类 型的对象 ApplicationContext 是 BeanFactory 的子接口 它添加了和 Spring 的 AOP 特性很简便的整合 ; 消息资源处理 ( 用于国际化 i18n), 事件发布 ; 应用层特定的上下文, 比如用于 Web 应用程序的 WebApplicationContext 总之,BeanFactory 提供了配置框架和基本功能, 而 ApplicationContext 添加了更多企业级开发特定的功能 ApplicationContext 是 BeanFactory 完整的超集, 专门用于本章, 来描述 Spring 的 IoC 容器 对于使用 BeanFactory 而不是 ApplicationContext 的更多信息, 可以参考 4.15 节 BeanFactory 在 Spring 中, 对象构成应用程序的骨感, 它们是由 Spring 的 IoC 容器管理的, 并被称为 bean 一个 bean 就是一个实例化并组装的对象, 由 Spring 的 IoC 容器来管理 否则,bean 就是应用程序中众多对象之一 Bean 和它们之间的依赖, 反射出由容器使用的配置元数据 4.2 容器概述 org.springframework.context.applicationcontext 接口代表了 Spring 的 IoC 容器, 负责实例化, 配置和装配上述的 bean 容器获得指示来实例化某对象, 配置并装 配, 这都是通过读取配置元数据实现的 配置元数据在 XML 中,Java 注解或 Java 代码中来 表示 它允许你表达编写应用程序的对象, 还有对象间丰富的相互依存的关系 ApplicationContext 接口的一些实现使用 Spring 开箱的支持 在独立的应用程序 中, 通常是来创建 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的实例 XML 是定义配置元数据的传统格式, 你 可以指示容器使用 Java 的注解或是代码作为元数据的格式, 提供少量的 XML 配置声明来开 启对这些额外的元数据格式的支持 在很多应用场景中, 明确的用户代码不需要实例化一个或者多个 Spring IoC 容器的实例 比如, 在 Web 应用场景中, 在应用程序的 web.xml 中简单的八 ( 左右 ) 行样板 J2EE 描述符 XML 文件通常就够了 ( 参考 节 对 Web 应用程序方便的应用上下文实例化 ) 如 果你正使用 SpringSource 的工具套件,Eclipse 支持的开发环境或者是 Spring ROO 这样的样板 配置, 就可以容易地被创建, 点几下鼠标或按键就可以了 下图是 Spring 如何工作的高级别视图 你的应用程序类联合配置元数据, 所以在 ApplicationContext 被创建和实例化后, 就得到了一个完全配置的可执行系统或程序

31 Spring 的 IoC 容器 配置元数据 正如上图所示,Spring 的 IoC 容器处理配置元数据的一种形式 ; 这个配置元数据代表了 你作为应用开发人员是如何告诉 Spring 容器在你的应用程序中来实例化, 配置并装配对象 的 配置元数据传统上是以直观的 XML 格式提供的, 这是本章的大部分内容使用它来传达 Spring IoC 容器关键概念和功能 注意 基于 XML 的元数据并不是唯一的配置元数据格式 这种配置元数据真正写入时,Spring 的 IoC 容器本身和这种格式完全脱钩 关于 Spring 容器使用元数据格式的信息, 可以参考 : 基于注解的配置 (4.9 节 ):Spring 2.5 引入了对基于注解元数据的支持 基于 Java 的配置 (4.12 节 ): 从 Spring 3.0 开始, 很多由 Spring JavaConfig 项目提供的特 性称为 Spring Framework 的核心 因此你可以在应用程序外部来定义 bean, 使用 Java 代码而不是 XML 文件 注解 Spring 配置典型的是最少由一个容器必须管理的 bean 定义构成 基于 XML 的配置元数 据展示了这些 bean 的配置是用在顶级 <beans/> 元素中的 <bean/> 元素完成的 这些 bean 的定义对应构成应用程序中真实的对象 比如你定义的服务层的对象, 数据 访问对象 (Data Access Object,DAO), 表示对象比如 Struts 的 Action 实例, 基础设置对象 比如 Hibernate 的 SesstionFactories,JMS 的 Queues 等这些典型的例子 而不用在容器中定义细粒度的领域模型对象, 因为这通常是由 DAO 和业务逻辑负责创建并加载的领域 对象 但是你也可以使用 Spring 和 AspectJ 整合来配置创建在 IoC 容器控制之外的对象 参 考使用在 Spring 中使用 AspectJ 来对领域对象进行依赖注入 (8.8.1 节 ) 下面的示例展示了基本的基于 XML 的配置元数据的结构 :

32 <?xml version="1.0" encoding="utf-8"?> <beans xmlns=" xmlns:xsi=" xsi:schemalocation=" ans <bean id="..." class="..."> <!-- 这个 bean 的合作者和配置在这里编写 --> <bean id="..." class="..."> <!-- 这个 bean 的合作者和配置在这里编写 --> <!-- 更多的 bean 定义在这里编写 --> </beans> id 属性是一个字符串, 用来标识定义的独立的 bean class 属性定义了 bean 的类型, 需要使用类的完全限定名 id 属性的值指的就是协作对象 指写作对象的 XML 在这个示例中没有展示 ; 参考依赖 (4.4 节 ) 来获取更多信息 实例化容器 实例化 Spring 的 IoC 容器是很简单的 定位路径或所有路径提供给 ApplicationContext 的构造方法, 实际上是表示资源的字符串, 它就允许容器从各种外部资源比如本地文件系统,Java 的 CLASSPATH 等来加载配置元数据 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"); 注意 在学习过 Spring 的 IoC 容器之后, 你可能想更多了解 Spring 的 Resource 抽象, 这在 第 5 章, 资源中会描述, 它提供了一个从定义 URI 语法的位置读取输入流的简便机制 特别 是,Resource 路径用来构建应用程序上下文, 这会在 5.7 节 应用上下文和资源路径 中 来描述 下面的示例展示了服务层代码 (services.xml) 的配置文件 : <?xml version="1.0" encoding="utf-8"?> <beans xmlns=" xmlns:xsi=" xsi:schemalocation=" ans.xsd"> <!-- services -->

33 <bean id="petstore" class="org.springframework.samples.jpetstore.services.petstoreserviceimpl"> <property name="accountdao" ref="accountdao"/> <property name="itemdao" ref="itemdao"/> <!-- 这个 bean 的其它合作者和配置在这里编写 --> <!-- 更多的 service bean 的定义在这里编写 --> </beans> 下面的示例展示了数据访问对象的 daos.xml 文件 : <?xml version="1.0" encoding="utf-8"?> <beans xmlns=" ans xmlns:xsi=" xsi:schemalocation=" <bean id="accountdao" class="org.springframework.samples.jpetstore.dao.ibat is.sqlmapaccountdao"> <!-- 这个 bean 的其它合作者和配置在这里编写 --> <bean id="itemdao" class="org.springframework.samples.jpetstore.dao.ibat is.sqlmapitemdao"> <!-- 这个 bean 的其它合作者和配置在这里编写 --> <!-- 更多数据访问对象的定义在这里编写 --> </beans> 在上面的示例中, 服务层代码由类 PetStoreServiceImpl 和两个基于 ibatis(ibatis 现已更名为 MyBatis, 译者注 ) 对象 / 实体映射框架的数据访问对象 SqlMapAccountDao 和 SqlMapItemDao 构成 property 的 name 元素指的是 JavaBean 的属性名, 而 ref 元 素指的是其它 bean 定义的名称 id 和 ref 元素之间的这种联系表示了两个协作对象的依赖 关系 要了解更多配置对象依赖的信息, 可以参考依赖 (4.4 节 ) 处理基于 XML 的配置元数据 跨越多个 XML 文件中定义 bean 是很有用的 通常每个独立的 XML 配置文件代表了一个逻辑层或架构中的一个模块 你可以使用 ApplicationContext 的构造方法从所有的 XML 文件片段中来加载 bean 这个构造方法可以接收多个 Resource 位置, 这在之前的部分都已经看到了 另外, 可以使用一

34 个或多个 <import/> 元素来从另外的一个或多个文件中加载 bean 比如 : <beans> <import resource="services.xml"/> <import resource="resources/messagesource.xml"/> <import resource="/resources/themesource.xml"/> <bean id="bean1" class="..."/> <bean id="bean2" class="..."/> </beans> 在这个示例中, 外部的 bean 通过三个文件来加载, 分别是 services.xml, messagesource.xml 和 themesource.xml 所有的位置路径都是相对于该引用文件的, 所以 service.xml 必须在和引用文件相同路径中或者是类路径下, 而 messagesource.xml 和 themesource.xml 必须是在位于引用文件下一级的 resources 路径下 正如你看到的, 前部的斜杠被忽略了, 这是由于路径都是相对的, 最 好就不用斜线 文件的内容会被引入, 包括顶级的 <beans/> 元素, 根据 Spring 的 Schema 或 DTD, 它必须是有效 bean 定义的 XML 文件 注意 在父目录中使用相对路径../ 来引用文件, 这是可能的, 但是不推荐这么做 这么做了会创建一个文件, 它是当前应用程序之外的一个依赖 特别是, 这种引用对于 classpath: 的 URL( 比如, classpath:../service.xml ) 是不推荐的, 运行时的解析过 程会选择 最近的 类路径根目录并且会查看它的父目录 类路径配置的修改可能会导 致去选择一个不同的, 不正确的目录 你也可以使用资源位置的完全限定名来代替相对路径 : 比如, file:c:/config/services.xml 或 classpath:/config/services.xml 这样的话, 要注意你会耦合应用程序的配置到指定 的绝对路径 对于绝对路径, 一般最好是保持一个间接的使用, 比如通过占位符 ${..., 这会基于运行时环境的 JVM 系统属性来解决 使用容器 ApplicationContext 是能维护不同的 bean 和它们依赖注册的高级工厂接口 使用 T getbean(stringname, Class<T> requiredtype) 方法你可以获取 bean 的实例 ApplicationContext 允许你读取 bean 并且访问它们, 如下所示 : // 创建并配置 bean ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"); // 获取配置的实例 PetStoreServiceImpl service = context.getbean("petstore", PetStoreServiceImpl.class); // 使用配置的实例 List userlist service.getusernamelist(); 使用 getbean() 方法来获取 bean 的实例 ApplicationContext 接口有一些其它

35 方法来获取 bean, 但最好应用程序代码不使用它们 事实上, 应用程序代码应该没有 getbean() 方法的调用, 那么就没有对 Spring API 的依赖了 比如,Spring 和 Web 框架整 合时, 提供了对各种 Web 框架类库的依赖注入, 不如控制器和 JSF 管理的 bean 4.3 Bean 概述 Spring 的 IoC 容器管理一个或多个 bean 这些 bean 通过提供给容器的配置元数据被创建出来, 比如, 在 XML 中的 <bean/> 定义的形式 在容器本身, 这些 bean 代表了 BeanDefinition 对象, 它们包含 ( 在其它信息中 ) 下列元数据 : 打包的类限定名 : 就是这些 bean 的真正实现类 bean 的行为配置元素, 这表示了 bean 在容器中 ( 范围, 生命周期回调等等 ) 应该是怎样的行为 对其它 bean 的引用, 这是该 bean 工作所需要的 ; 这些引用通常被称为合作者或依赖 在新被创建的对象中的其它配置设置, 比如, 管理连接池的 bean 中使用的连接数或连 class name 接池限制的大小 元数据翻译成一组属性集合来构成每一个 bean 的定义 表 4.1 bean 定义 属性 解释章节 节, 实例化 bean 节, 命名 bean scope 4.5 节, bean 的范围 constructor arguments 节, 依赖注入 properties 节, 依赖注入 autowiring mode 节, 装配合作者 lazy-initialization mode 节, 延迟初始化 bean initialization method 节, 初始化回调 descruction method 节, 销毁回调 此外,bean 的定义还包含如何创建特定 bean 的信息,ApplicationContext 的实现类允许用户将容器外部创建的已有对象的注册 这可以通过 getbeanfactory() 方法访问 ApplicationContext 的 BeanFactory 来完成, 它会返回 BeanFactory 的实现类 DefaultListableBeanFactory DefaultListableBeanFactory 通过 registersingleton(..) 和 registerbeandefinition(..) 方法来支持这种注册 而典型的应用程序只和通过元数据定义的 bean 来工作 命名 bean 每个 bean 有一个或者多个标识符 这些标识符必须在托管 bean 的容器内唯一 通常 一个 bean 只有一个标识符, 但如果它需要多个的话, 其它的可以被认为是别名 在基于 XML 的配置元数据中, 你可以使用 id 和 / 或 name 属性来指定 bean 的标识符 id 属性允许你指定一个准确的 id 按照管理这些名称是字母和数字 ( mybean, fooservice 等 ), 但是可能是特殊字符 如果你想为 bean 引入别名, 你也可以在 name 属性中来指定,

36 通过逗号 (,), 分号 (;) 或空格来分隔 作为对历史的说明, 在 Spring 3.1 版之前,id 属性 是 xsd:id 类型, 只限定为字符 在 3.1 版本中, 现在是 xsd:string 类型了 要注意 bean 的 id 的唯一性还是被容器所强制的, 但是对于 XML 处理器却不是 当然你也可以不给 bean 提供 name 或 id 如果没有提供明确的 name 或 id, 那么容器 会为这个 bean 生成一个唯一的名称 然而, 如果你想通过名称来参考这个 bean, 那么可以 使用 ref 元素或者是服务定位器 ( 节 ) 风格的查找, 你必须提供一个名称 不提供 名称的动机是和使用内部 bean( 节 ) 或自动装备合作者 (4.4.5 节 ) 相关的 Bean 的命名约定 该约定是用于当命名 bean 时, 对实例字段名称的标准 Java 约定 也就是说,bean 的名称以小写字母开始, 后面是驼峰形式的 这样的命名可以是 ( 没有引号 ) accountmanager, accountservice, userdao, logincontroller 等 一致的命名 bean 可以使你的配置信息易于阅读和理解, 如果你使用 Spring 的 AOP, 当应用通知到一组相关名称的 bean 时, 它会给你很大的帮助 在 bean 定义外面起别名 在 bean 定义的本身, 你可以为 bean 提供多于一个的名称, 使用一个由 id 属性或 name 属性中的任意名称数指定的名称组合 这些名称对于同一个 bean 来说都是相等的别名, 在 一些情况下, 这是很有用的, 比如在应用程序中允许每个组件参考一个共同的依赖, 可以使 用为组件本身指定的 bean 的名称 然而, 在 bean 定义时指定所有的别名是不够的 有事可能想在任意位置, 为一个 bean 引入一个别名 这在大型系统中是很常见的例子, 其中的配置信息是分在每个子系统中的, 每个子系统都有它自己的对象定义集合 在基于 XML 的配置元数据中, 你可以使用 <alias/> 元素来完成这项工作 <alias name="fromname" alias="toname"/> 在这个示例中, 在相同容器中的名称为 fromname 的 bean, 在使用过这个别名定义后, 也可以使用 toname 来指引 比如, 在子系统的配置元数据中,A 可能要通过名称 subsystema-datasource 来指向 数据源 为子系统 B 的配置元数据可能要通过名称 subsystemb-datasource 来指向数据源 当处理使用了这两个子系统的主程序时, 主程序要通过名称 myapp-datasource 来指向数 据源 那么就需要三个名称指向同一个对象, 那么就要按照下面的别名定义来进行添加 MyApp 的配置元数据 : <alias name="subsystema-datasource" alias="subsystemb-datasource"/> <alias name="subsystema-datasource" alias="myapp-datasource" /> 现在每个组件和主程序都可以通过一个唯一的保证不冲突的名称来还有其它任意定义 ( 更有效地是创建命名空间 ) 来参照数据源了, 当然它们参照的是同一个 bean

37 4.3.2 实例化 bean bean 的定义信息本质上是创建一个或多个对象的方子 当需要一个 bean 时, 容器查找 这些方子来查找命名的 bean, 并且使用由 bean 定义信息封装的配置元数据来创建 ( 或获得 ) 一个真实的对象 如果你使用基于 XML 的配置元数据, 你为要被实例化的对象所指定的类型 ( 或类 ) 是 <bean/> 元素中 class 属性 这个 class 属性, 是 BeanDefinition 实例内部的 class 属性, 通常是强制要有的 ( 对于特例, 可以参考 节, 使用实例的工厂方法来实例 化 和 4.7 节, Bean 定义的继承 ) 你可以以两种方法之一来使用 class 属性 : 典型的是, 指定要被构造的 bean 类, 容器本身直接通过反射调用它的构造方法来创建 bean, 也就是和 Java 代码中使用 new 操作符是相同的 指定包含 static 工厂方法的真实的类, 会被调用来创建对象, 在一些不太常见的情况下, 容器会调用类的 static 工厂方法来创建 bean 从调用 static 工厂方法返回的对象类型可能 是和另外一个类完全相同的类 内部类名称 如果你想为 static 嵌入的类配置 bean, 你需要使用内部类的二进制名称 比如, 如果在 com.example 包下有一个 Foo 类, 而这个 Foo 类有一个 static 的内 部类 Bar, 那么在定义 bean 时 class 属性的值就会是... com.example.foo$bar 请注意名称中 $ 符号的使用, 用来从外部类名中分隔内部类名 使用构造方法实例化 当你使用构造方法来创建 bean 时, 所有普通的类的使用都和 Spring 兼容 也就是说, 开发中的 bean 不需要实现任何特定的接口或以特定的方式来编码 仅简单指定 bean 的类 就足够了 但基于你使用的是什么类型的 IoC, 就可能需要一个默认 ( 空的 ) 构造方法 Spring 的 IoC 容器可以虚拟地管理任意的你想让它管理的类 ; 而不仅仅限于管理真正的 JavaBean 很多 Spring 用户喜欢在容器中使用有默认 ( 无参数 ) 构造方法和在其后有适当 setter 和 getter 方法的真正 JavaBean 你也可以在容器中使用很多异样的, 非 bean 样式的类 比 如, 需要使用遗留的连接池, 但是它没有符合 JavaBean 的规范,Spring 也能照样管理它 基于 XML 的配置元数据, 你可以如下来定义 bean: <bean id="examplebean" class="examples.examplebean"/> <bean name="anotherexample" class="examples.examplebeantwo"/> 关于提供构造方法参数 ( 如果需要 ) 和在对象被构造后, 设置对象实例属性机制的详情, 请参考 节依赖注入 使用静态工厂方法来实例化 当使用静态工厂方法来定义 bean 的时候, 可以使用 class 属性来指定包含 static 工厂 方法的类, 而名为 factory-method 的属性来指定静态方法 你应该调用这个方法 ( 还可 以有可选的参数 ) 并返回一个实际的对象, 随后将它视为是通过构造方法创建的一样 在遗

38 留代码中, 这样定义 bean 的使用方式之一是调用 static 工厂 下面 bean 的定义指定了要通过调用工厂方法生成的 bean 这个定义没有指定返回对象 的类型 ( 类 ), 仅仅是包含工厂方法的类 在本例中,createInstance() 方法必须是静态方法 <bean id="clientservice" class="examples.clientservice" factory-method="createinstance"/> public class ClientService { private static ClientService clientservice = new ClientService(); private ClientService() { public static ClientService createinstance() { return clientservice; 关于提供 ( 可选的 ) 参数到工厂方法并在对象由工厂返回后设置对象实例属性的机制详 情, 请参考 节深入依赖和配置 使用实例工厂方法来实例化 和使用静态工厂方法 ( 节 ) 实例化相似, 使用实例工厂方法实例化是要调用容器 中已有 bean 的一个非静态的方法来创建新的 bean 要使用这个机制, 请把 class 属性留 空, 但在 factory-bean 属性中指定当前 ( 或父 / 祖先 ) 容器中 bean 的名字, 该 bean 要包含被调用来创建对象的实例方法 使用 factory-method 方法来设置工厂方法的名称 <!-- 工厂 bean, 包含名为 createinstance() 的方法 --> <bean id="servicelocator" class="examples.defaultservicelocator"> <!-- 为 locator bean 注入任意需要的依赖 --> <!-- 通过工厂 bean 来创建的 bean --> <bean id="clientservice" factory-bean="servicelocator" factory-method="createclientserviceinstance"/> public class DefaultServiceLocator { private static ClientService clientservice = new ClientServiceImpl(); private DefaultServiceLocator() { public ClientService createclientserviceinstance() { return clientservice;

39 一个工厂类也可以有多于一个工厂方法, 比如下面这个 : <bean id="servicelocator" class="examples.defaultservicelocator"> <!-- 为 locator bean 注入任意需要的依赖 --> <bean id="clientservice" factory-bean="servicelocator" factory-method="createclientserviceinstance"/> <bean id="accountservice" factory-bean="servicelocator" factory-method="createaccountserviceinstance"/> public class DefaultServiceLocator { private static ClientService clientservice = new ClientServiceImpl(); private static AccountService accountservice = new AccountServiceImpl(); private DefaultServiceLocator() { public ClientService createclientserviceinstance() { return clientservice; public AccountService createaccountserviceinstance() { 这个方法展示了工厂 bean 本身可以通过依赖注入 (DI) 被管理和配置 请参考 节 深入依赖和配置 注意 return accountservice; 在 Spring 文档中, 工厂 bean 指的是在 Spring 容器中配置的 bean, 可以通过实例 ( 节 ) 或静态 ( 节 ) 工厂方法来创建对象 与此相反的是,FactoryBean( 注意大小 写 ) 指的是 Spring 特定的 FactoryBean(4.8.3 节 ) 4.4 依赖 典型的企业级应用程序不是由单独对象 ( 或 Spring 中的 bean) 构成的 尽管最简单的 应用程序有一些对象协同工作来表示终端用户所看到的连贯的应用 下一节会解释如何去为完全实现的应用程序定义一组独立的 bean, 其中对象间相互协作来达到目标 依赖注入 依赖注入 (DI) 是对象定义它们依赖的过程, 也就是说, 要和它们协同工作其它对象, 仅仅可以通过构造方法参数, 工厂方法参数, 或者是在工厂方法返回的对象或被构造好后,

40 为对象实例设置的属性 容器当创建好 bean, 随后就会注入那些依赖 这个过程从根本上 来说是反向的, 因此命名为控制反转 (IoC), bean 本身直接使用构造好的类或服务定位器 模式来控制实例或它的依赖的所在位置 应用了 DI 原则, 代码就干净多了, 当为对象提供它们依赖的时候, 解耦是很有效率的 对象不再去检查它的依赖, 也不需要知道位置或依赖的类 因此, 类就很容易被测试, 特别 是当依赖是接口或抽象基类的时候, 这允许在单元测试中使用 stub 或 mock 的实现类 DI 存在两种主要的方式, 基于构造方法的依赖注入 ( 节 ) 和基于 setter 方法的依 赖注入 ( 节 ) 基于构造方法的依赖注入 基于构造方法的依赖注入是容器调用构造方法和一组参数完成的, 每个都表示着一个依 赖 使用特定的参数来调用 static 工厂方法构造 bean 基本也是相同的, 这种说法把给构 造方法的参数和给 static 工厂方法的参数相类似 下面的示例展示了一个仅使用构造方法进行依赖注入的饿类 注意这个类没有什么特殊之处, 就是一个 POJO 而且没有对容器特 定接口, 基类或注解的依赖 public class SimpleMovieLister { // SimpleMovieLister 对 MovieFinder 有依赖 private MovieFinder moviefinder; // 这个构造方法使得 Spring 容器可以 注入 MovieFinder public SimpleMovieLister(MovieFinder moviefinder) { this.moviefinder = moviefinder; // 业务逻辑就可以 使用 注入的 MovieFinder 了, 代码就省略了... 构造方法参数解析 构造方法参数解析匹配使用参数的类型 如果在 bean 的构造方法参数不存在潜在的歧 义, 那么当 bean 被实例化的时候, 定义的构造方法参数的顺序就是被提供到适当构造方法参数的顺序 请看下面的类 : package x.y; public class Foo { public Foo(Bar bar, Baz baz) { //... 没有潜在的歧义存在, 假设 Bar 和 Baz 类没有继承关系 因此下面的配置就可以使用 了, 而且并不需要明确地在 <constructor-arg/> 元素中去指定构造方法参数的索引和 / 或类型

41 <beans> <bean id="foo" class="x.y.foo"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> <bean id="bar" class="x.y.bar"/> <bean id="baz" class="x.y.baz"/> </beans> 当另外一个 bean 被引用时, 类型是明确的, 那么匹配就能成功 ( 前面示例中也是这样 的 ) 当使用简单类型时, 比如 <value>true<value>,spring 不能决定值的类型, 所以 没有帮助是不能匹配的 看下面的示例 : package examples; public class ExampleBean { // 计算最佳答案的年数 private int years; // 生命, 宇宙, 所有问题的答案 private String ultimateanswer; public ExampleBean(int years, String ultimateanswer) { this.years = years; this.ultimateanswer = ultimateanswer; 构造方法参数类型匹配 在上面的情形下, 如果你使用 type 属性明确地为构造方法参数指定类型的话, 容器可 以进行匹配简单的类型 比如 : <bean id="examplebean" class="examples.examplebean"> <constructor-arg type="int" value=" "/> <constructor-arg type="java.lang.string" value="42"/> 构造方法参数索引使用 index 属性来指定明确的构造方法参数索引 比如 : <bean id="examplebean" class="examples.examplebean"> <constructor-arg index="0" value=" "/> <constructor-arg index="1" value="42"/> 此外, 为了解决多个简单值的歧义, 如果构造方法有两个相同类型的参数时, 指定所以 可以解决歧义 注意索引是基于 0 开始的 构造方法参数名称 在 Spring 3.0 中, 你也可以使用构造方法参数名称来消除歧义 :

42 <bean id="examplebean" class="examples.examplebean"> <constructor-arg name="years" value=" "/> <constructor-arg name="ultimateanswer" value="42"/> 要记住要使得这种方式可用, 代码必须和内嵌的调试标识一起编译, 那样 Spring 才可 以从构造方法中来查找参数 如果没有和调试标识 ( 或不想 ) 一起编译, 那么可以使用 JDK 来明确构造方法参数 那么示例代码就如下所示 : package examples; public class ExampleBean { // "ultimateanswer") public ExampleBean(int years, String ultimateanswer) { this.years = years; this.ultimateanswer = ultimateanswer; 基于 setter 方法的依赖注入 基于 setter 方法的依赖注入由容器在调用过无参数的构造方法或无参数的 static 工厂 方法来实例化 bean 之后, 再调用 bean 的 setter 方法来完成的 下面的示例展示了一个仅仅能使用纯 setter 方法进行依赖注入的类 这是一个常见的 Java 类, 是一个没有依赖容器指定的接口, 基类或注解的 POJO public class SimpleMovieLister { // SimpleMovieLister 对 MovieFinder 有依赖 private MovieFinder moviefinder; // setter 方法可以让 Spring 容器来 ' 注入 'MovieFinder public void setmoviefinder(moviefinder moviefinder) { this.moviefinder = moviefinder; // 真正 使用 注入的 MovieFinder 的业务逻辑代码被省略了... ApplicationContext 对它管理的 bean 支持基于构造方法和 setter 方法的依赖注入 也支持在一些依赖已经通过构造方法注入之后再进行 setter 方法注入 以 BeanDefinition 形式来配置依赖, 使用 PropertyEditor 实例将属性从一种形式格式 化到另一种 但很多 Spring 的用户不直接 ( 编程时 ) 使用这些类, 而是使用 XML 文件来定义, 之后会在内部转换这些类的实例, 需要加载整个 Spring IoC 容器的实例

43 基于构造方法还是 setter 方法进行依赖注入? 因为你可以将二者混淆, 那么对于基于构造方法或是 setter 方法的依赖注入, 有一 个很好的规则就是为强制依赖使用构造方法参数, 而对于可选参数使用 setter 方法 要 注意在 setter 节 ), 可用于 setter 方法所需的依赖 Spring 团队通常主张使用 setter 方法注入, 因为大量的构造方法参数会使程序变得非常笨拙, 特别是当属性为可选的时候 Setter 方法会让该类的对象今后适合于重新配置或 重新注入 通过 JMX Mbean( 第 23 章 ) 来管理就是一个令人关注的用例 一些人纯粹赞成构造方法注入 提供所有对象的依赖意味着对象在完全初始化状态 时, 通常要返回客户端 ( 调用 ) 代码 这个缺点会使得对象变得不适合去重新配置或重 新注入 使用依赖注入的时候要特别注意一些类 当要选择处理没有源代码时的第三方类库 的时候 遗留的类可能没有暴露任何 setter 方法, 而构造方法注入则是唯一可用的依赖注入方式 解决依赖过程 容器按如下步骤来解决 bean 的依赖 : 1. ApplicationContext 和描述了所有 bean 的配置元数据一起被创建并初始化 配置元数据可以通过 XML,Java 代码或注解来指定 2. 对于每一个 bean 来说, 它的依赖被表述为属性, 构造方法参数的形式, 如果你使用 了静态工厂方法来代替构造方法, 那么还会是静态工厂方法参数的形式 当 bean 被实际创 建时, 这些依赖被提供给 bean 3. 每个属性或构造方法参数就是一个要被设置的值或者是容器中其它 bean 的引用 4. 每个属性或构造方法参数值会被转换特定格式的形式, 去匹配属性或构造方法参数 的类型 默认情况下,Spring 可以转换给定的字符串格式的值到内建的类型, 比如 int,long, String,boolean 等 当容器被创建时,Spring 容器会来验证每个 bean 的配置, 包括验证 bean 的引用属性是 否是一个合法的 bean 然而,bean 属性本身直到 bean 真正被创建出来后才被设置进去 当容器被创建时,bean 的范围是单例时, 会被设置成预实例 ( 默认情况 ) 来创建 范围在 4.5 节, bean 的范围 部分来解释 否则,bean 就会当被请求的时候被创建 一个 bean 的创建潜在地会引起一系列 bean 被创建, 因为 bean 的依赖和它依赖的依赖 ( 等等 ) 要不 创建和定义出来 循环依赖 如果你使用主要的构造方法注入, 就可能会引起不可解决的循环依赖情形 比如, 类 A 需要通过构造方法注入获得类 B 的实例, 而类 B 也需要通过构造方法注 入获得类 A 的实例 如果把类 A 和类 B 进行相互注入,Spring 的 IoC 容器会在运行时检 测到这是循环引用的情况, 并且抛出 BeanCurrentlyInCreationException 异常 一个可行的方案是编辑一些要配置的类的源码, 通过 setter 方法而不是构造方法进 行注入 而且, 避免构造方法注入并仅仅使用 setter 方法注入 换句话说, 尽管这不是推荐做法, 你可以通过 setter 方法注入来配置循环依赖 不像典型的用例 ( 没有循环依赖 ), 在 bean A 和 bean B 之间的循环依赖强制一个 bean 被注入到另一个中会先于被完全初始化自己 ( 就是经典的鸡和蛋的问题 )

44 通常情况下你可以信任 Spring 做出正确的事情 它会在容器加载时来检测配置问题, 比如引用了一个不存在的 bean 和循环依赖问题 当 bean 被实际创建出来后,Spring 设置属 性和解决依赖会尽量地晚些 这就意味着 Spring 容器已经加载正确了但晚些时候可能会生成异常, 比如当你请求一个创建时发生问题的对象或者是它的依赖发送问题 例如,bean 因为丢失或非法属性而抛出异常 这种潜在的一些配置问题的可见度延迟也就是为什么 ApplicationContext 的实现类默认情况都是预实例的单例 bean 在前期的时间和内存 消耗中, 在 bean 真正需要前来创建这些 bean, 当 ApplicationContext 被创建的时候, 你会发现这些配置问题, 这还不晚 你也可以覆盖这个默认的行为, 那么单例 bean 就会延迟加载, 而不是预实例的了 如果没有循环依赖的存在, 当一个或多个协作的 bean 被注入到一个独立的 bean 时, 每个协作的 bean 就会在被注入之前完全被配置好 这就意味着如果 bean A 对 bean B 有依 赖, 那么 Spring 的 IoC 容器会完全配置 bean B 而优先于调用 bean A 中的 setter 方法 换句 话说,bean 被实例化了 ( 而不是预实例的单例 bean), 它的依赖才被注入, 相关的生命周期方法 ( 比如配置初始化方法 ( 节 ) 或 InitializingBean 的回调方法 ( 节 )) 才 被调用 依赖注入示例 下面的示例使用了基于 XML 的配置元数据来进行基于 setter 方法的依赖注入 Spring XML 配置文件的一小部分来指定几个 bean 的定义 : <bean id="examplebean" class="examples.examplebean"> <!-- 使用嵌入 <ref/> 的元素来进行 setter 方法注入 <ref/> --> <property name="beanone"> <ref bean="anotherexamplebean"/> </property> <!-- 使用整洁的 'ref' 属性来进行 setter 方法注入 --> <property name="beantwo" ref="yetanotherbean"/> <property name="integerproperty" value="1"/> <bean id="anotherexamplebean" class="examples.anotherbean"/> <bean id="yetanotherbean" class="examples.yetanotherbean"/> public class ExampleBean { private AnotherBean beanone; private YetAnotherBean beantwo; private int i; public void setbeanone(anotherbean beanone) { this.beanone = beanone; public void setbeantwo(yetanotherbean beantwo) { this.beantwo = beantwo; public void setintegerproperty(int i) { this.i = i;

45 上面的示例中,setter 方法被声明为匹配 XML 文件中指定的属性 下面的示例使用基于 构造方法的依赖注入 : <bean id="examplebean" class="examples.examplebean"> <!-- 使用嵌入的 <ref/> 元素进行构造方法注入 --> <constructor-arg> <ref bean="anotherexamplebean"/> </constructor-arg> <!-- 使用整洁的 'ref' 属性来进行构造方法注入 --> <constructor-arg ref="yetanotherbean"/> <constructor-arg type="int" value="1"/> <bean id="anotherexamplebean" class="examples.anotherbean"/> <bean id="yetanotherbean" class="examples.yetanotherbean"/> public class ExampleBean { private AnotherBean beanone; private YetAnotherBean beantwo; private int i; public ExampleBean(AnotherBean anotherbean, YetAnotherBean yetanotherbean, int i) { this.beanone = anotherbean; this.beantwo = yetanotherbean; this.i = i; 在 bean 中指定的构造方法参数会被用于 ExampleBean 的构造方法参数 现在考虑一下这个示例的变化情况, 要代替使用构造方法,Spring 被告知调用 static 工厂方法并返回一个对象的实例 : <bean id="examplebean" class="examples.examplebean" factory-method="createinstance"> <constructor-arg ref="anotherexamplebean"/> <constructor-arg ref="yetanotherbean"/> <constructor-arg value="1"/> <bean id="anotherexamplebean" class="examples.anotherbean"/> <bean id="yetanotherbean" class="examples.yetanotherbean"/>

46 public class ExampleBean { // 私有的构造方法 private ExampleBean(...) {... // 静态工厂方法 ; 这个方法的参数可以被认为是要返回 bean 的依赖, // 而不管那些参数是如何被使用的 public static ExampleBean createinstance (AnotherBean anotherbean, YetAnotherBean yetanotherbean, int i) { ExampleBean eb = new ExampleBean (...); // 其它的操作... return eb; static 工厂方法的参数通过 <constructor-arg/> 元素来提供, 这和构造方法已经 被实际调用是完全一致的 由工厂方法返回的类的类型不需要和包含 static 工厂方法类 的类型相同, 尽管在本例中是相同的 实例 ( 非静态 ) 工厂方法可以被用于本质上相同的方式 ( 除了 factory-bean 属性的使用, 来代替 class 属性 ), 所以这里不讨论它们的细节 深入依赖和配置 正如之前章节中所提到的, 你可以定义 bean 的属性和构造方法参数作为其它被管理 bean( 协作者 ) 的引用, 或者作为内联值的定义 出于这个目的,Spring 的基于 XML 的配置元数据支持使用 <property/> 和 <constructor-arg/> 元素的子元素类型 直接值 ( 原生类型,String, 等 ) <property/> 元素的 value 属性指定了属性或构造方法参数, 这是人们可以阅读的 字符串的表达 正如之前提到过的 (6.4.2 节 ),JavaBean 的 PropertyEditor 可以用来转换这些字符串值从 String 到属性或参数的真实类型 <bean id="mydatasource" class="org.apache.commons.dbcp.basicdatasource" destroy-method="close"> <!-- setdriverclassname(string) 方法调用的结果 --> <property name="driverclassname" value="com.mysql.jdbc.driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mydb"/> <property name="username" value="root"/> <property name="password" value="masterkaoli"/> 对于更简洁的 XML 配置, 下面的示例使用了 p- 命名空间 ( 节 )

47 <beans xmlns=" xmlns:xsi=" xmlns:p=" xsi:schemalocation=" d"> <bean id="mydatasource" </beans> class="org.apache.commons.dbcp.basicdatasource" destroy-method="close" p:driverclassname="com.mysql.jdbc.driver" p:url="jdbc:mysql://localhost:3306/mydb" p:username="root" p:password="masterkaoli"/> 上面的 XML 非常简洁 ; 然而, 错误之处会在运行时被发现而不是设计的时候, 除非在 你创建 bean 的时候, 使用如 IntelliJ IDEA 或 SpringSource Tool Suite(STS,SpringSource 组织 开发的工具套件 ) 这样的 IDE 来支持自动地属性补全 这样的 IDE 帮助是强烈建议使用的 你也可以这样来配置 java.util.properties 实例 : <bean id="mappings" class="org.springframework.beans.factory.config.propertyplac eholderconfigurer"> <!-- 作为 java.util.properties 类型 --> <property name="properties"> <value> </value> </property> Spring 容器会使用 JavaBean 的 PropertyEditor 机制来转换 <value/> 元素中的文本 到 java.util.properties 实例 这是一个很好的捷径, 也是 Spring 团队少有喜欢使用嵌套的 <value/> 元素而不是 value 属性方式的地方之一 idref 元素 jdbc.driver.classname=com.mysql.jdbc.driver jdbc.url=jdbc:mysql://localhost:3306/mydb idref 元素是一种简单防错的形式来传递容器中另外一个 bean 的 id( 字符串值而不是 引用 ) 到 <constructor-arg/> 或 <property/> 元素中 <bean id="thetargetbean" class="..."/> <bean id="theclientbean" class="..."> <property name="targetname"> <idref bean="thetargetbean" /> </property>

48 上面定义 bean 的代码片段是和下面的片段完全等价 ( 在运行时 ): <bean id="thetargetbean" class="..." /> <bean id="client" class="..."> <property name="targetname" value="thetargetbean" /> 第一种形式比第二种形式可取, 因为使用 idref 标签允许容器在部署时来验证被引用 的, 命名的 bean 是否真的存在 第二种形式下, 没有对传递给 client bean 的 targetname 属性执行验证 错误仅仅是在 client bean 被真正实例化的时候才会被发现 ( 和很多可能 致命的结果 ) 如果 client bean 是 prototype(4.5 节 ) 类型的 bean, 这个错误和结果异常 可能仅仅在容器被部署很长一段时间后才会被发现 此外, 如果被引用的 bean 在同一个 XML 单元中,bean 的名称就是 bean 的 id, 那么你 还可以使用 local 属性, 这允许 XML 解析器本身在 XML 文档解析的时候, 及早地来验证 bean 的 id <property name="targetname"> <!-- id 为 'thetargetbean' 的 bean 必须存在 ; 否则就会抛出异常 --> <idref local="thetargetbean"/> </property> <idref/> 元素带来的一个相同之处 ( 最少是 Spring 2.0 版本以前的 ) 是值在 ProxyFactoryBean 定义的 AOP 拦截器的配置中 当你指定拦截器名称来防止拼错拦截 器的 id 时, 可以使用 <idref/> 元素 引用其它 bean( 协作者 ) ref 元素是 <constructor-arg/> 或 <property/> 定义元素中最后的一个 在这里 你可以为 bean 设置指定属性的值, 来引用被容器管理的另外一个 bean( 协作者 ) 被引用 的 bean 就是要设置属性的这个 bean 的一个依赖, 并且是初始化的作为属性设置之前的点 播 ( 如果协作者是一个单例的 bean, 它可能已经被容器初始化过了 ) 所有引用最终都会被引用到一个对象中 范围和验证基于通过 bean,local 或 parent 属性指定 id/name 的其它对象 通过 <ref/> 标签的 bean 属性来指定目标 bean 是最常用的方式, 并允许创建引用到相 同容器或父容器的任意 bean 中, 而不管它们是不是在同一个 XML 文件中 bean 属性的值 可能和目标 bean 的 id 属性相同, 或者是目标 bean 的 name 属性值之一 <ref bean="somebean"/> 通过 local 属性来指定目标 bean 是利用了 XML 解析器的能力, 来验证 XML 相同文件 内的 id 引用 local 属性的值必须和目标 bean 的 id 属性一致 如果没有在相同的文件内 发现匹配的元素, 那么 XML 解析器会报告问题 因此, 如果目标 bean 在同一个 XML 文件中的话, 使用 local 这种形式是最佳选择 ( 为了更早地知道错误 ) <ref local="somebean"/> 通过 parent 属性来指定目标 bean 会为 bean 创建引用, 它是在当前容器的父容器中

49 的 parent 属性的值可能和目标 bean 的 id 属性相同, 或者是目标 bean 的 name 属性值 之一, 而且目标 bean 必须在当前容器的父容器中 当有一个容器继承关系, 可以使用这个 bean 的引用, 或在你想使用和父 bean 有相同名称的代理包装一个父容器中已有 bean 时 <!-- 在父上下文中 --> <bean id="accountservice" class="com.foo.simpleaccountservice"> <!-- 在这里插入所需要的依赖 --> <!-- 在子 ( 后继 ) 上下文中 --> <bean id="accountservice" <-- bean 名称和父 bean 相同 --> class="org.springframework.aop.framework.proxyfactorybean"> <property name="target"> <ref parent="accountservice"/> <!-- 注意我们如何引用父 bean --> </property> <!-- 在这里插入其它配置和所需的依赖 --> 内部 bean 在 <property/> 或 <constructor-arg/> 元素内部的 <bean/> 元素的定义被称为 内部 bean <bean id="outer" class="..."> <!-- 为了替代为目标 bean 使用引用, 简单内联定义目标 bean --> <property name="target"> <bean class="com.example.person"> <!-- 这就是内部 bean --> </property> <property name="name" value="fiona Apple"/> <property name="age" value="25"/> 内部 bean 的定义不需要定义 id 或 name; 容器忽略这些值 也会忽略 scope 标识 内部 bean 通常是匿名的, 而且范围通常是 prototype(4.5.2 节 ) 的 注入内部 bean 到协作 bean 是不可能的, 只能到包围它的 bean 中 集合 在 <list/>, <set/>, <map/> 和 <props/> 元素中, 你可以分别设置 Java 的 Collection 类型 List,Set,Map 和 Properties 的属性和参数

50 <bean id="morecomplexobject" class="example.complexobject"> <!-- results in a setadmin s(java.util.properties) call --> <property name="admin s"> Map 类型的 key 或 value 的值, 或 set 的值, 也可以是下列元素之一 : 集合合并 <props> <prop key="administrator">administrator@example.org</prop> <prop key="support">support@example.org</prop> <prop key="development">development@example.org</prop> </props> </property> <!-- results in a setsomelist(java.util.list) call --> <property name="somelist"> <list> <value>a list element followed by a reference</value> <ref bean="mydatasource" /> </list> </property> <!-- results in a setsomemap(java.util.map) call --> <property name="somemap"> <map> <entry key="an entry" value="just some string"/> </map> </property> <entry key ="a ref" value-ref="mydatasource"/> <!-- results in a setsomeset(java.util.set) call --> <property name="someset"> <set> </set> </property> <value>just some string</value> <ref bean="mydatasource" /> bean ref idref list set map props value null 在 Spring 2.0 中, 容器支持集合的合并 应用开发人员可以定义父样式的 <list/>, <map/>,<set/> 或 <props/> 元素, 子样式的 <list/>,<map/>,<set/> 或 <props/> 元素继承或重写来自父集合的值 也就是说, 子集合的值是合并元素父与子集合中的元素, 和子集合元素覆盖父集合中指定值的结果 本节关于导论父子 bean 合并的机制 如果读者不熟悉父和子 bean 的定义, 可能要先去 阅读一下相关章节 (4.7 节 ) 下面的示例说明了集合合并 :

51 <beans> <bean id="parent" abstract="true" class="example.complexobject"> 注意在 child bean 中的 admin s 属性下的 <props/> 元素中的 merge=true 属性的使用 当 child bean 被容器处理并实例化时, 结果实例中有一个 admin s Properties 的集合, 包含了合并子 bean 的 admin s 集合和父 bean 的 admin s 集合 子 bean 的 Properties 集合的值设置继承了从父 <props/> 元素而来的所有属性, 子 bean 中 support 的值覆盖了父 bean 中的值 这种合并行为的应用和 <list/>,<map/> 和 <set/> 集合类型很相似 在 <list/> 元素特 定的情形下, 和 List 集合类型相关的语义, 也就是说,ordered 集合值的概念, 是要维护的 ; 父值优先于所有子 list 的值 在 Map,Set 和 Properties 集合类型的情况下, 没 有顺序的存在 因此对于容器内部使用的, 和 Map,Set 和 Properties 实现类型相关的 集合类型没有排序语义的作用 集合合并的限制 不能合并不同类型的集合 ( 比如 Map 和 List), 如果你要尝试这么去做, 那么就会抛出 Exception merge 属性必须在低级的, 继承的, 子 bean 中来指定 ; 在父集合中指定 merge 属性是冗余的, 也不会看到想要的合并结果 合并特性仅在 Spring 2.0 和更高版本中 可用 <property name="admin s"> <props> <prop key="administrator">administrator@example.com</prop> <prop key="support">support@example.com</prop> </props> </property> <bean id="child" parent="parent"> <property name="admin s"> <!-- 合并在 * 子 * 集合定义中来指定 definition --> <props merge="true"> <prop key="sales">sales@example.com</prop> <prop key="support">support@example.co.uk</prop> </props> </property> <beans> administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk 强类型集合 (Java 5 以上版本 ) 在 Java 5 或更高版本中, 你可以使用强类型集合 ( 使用泛型 ) 也就是说, 可以声明一个 Collection 类型, 它可以仅仅包含 String 元素 ( 作为示例 ) 如果你使用 Spring 来

52 对强类型的 Collection 依赖注入到 bean 中, 你可以利用 Spring 的类型转换来支持这样 强类型 Collection 实例的元素, 在被加到 Collection 之前, 可以转换成合适的类型 public class Foo { private Map<String, Float> accounts; public void setaccounts(map<string, Float> accounts) { this.accounts = accounts; <beans> <bean id="foo" class="x.y.foo"> <property name="accounts"> <map> <entry key="one" value="9.99"/> </map> </property> </beans> <entry key="two" value="2.75"/> <entry key="six" value="3.99"/> 当 foo bean 的 accounts 属性准备好注入时, 关于强类型元素 Map<String, Float> 类型的泛型信息就通过反射机制准备好了 因此 Spring 的类型转换工具识别到各种元素的值作为 Float 类型, 字符串值 9.99,2.75 和 3.99 被转换成实际的 Float 类型 null 和空字符串 Spring 将属性的空参数当作空 String 下面基于 XML 的配置元数据片段设置了电子邮 件属性为空 String 值 ("") <bean class="examplebean"> <property name=" " value=""/> 上面的例子和下面的 Java 代码是一样的 :examplebean.set ("") <null/> 元素控制 null 值 比如 : <bean class="examplebean"> <property name=" "><null/></property> 上面的配置和下面的 Java 代码一致 :examplebean.set (null)

53 使用 p- 命名空间的 XML 快捷方式 p- 命名空间可以使你使用 bean 的元素属性, 而不是内嵌的 <property/> 元素, 来描述属 性的值和 / 或协作的 bean Spring 2.0 和后续版本支持使用命名空间 ( 附录 C) 的可扩展的配置格式, 这是基于 XML 的 Schema 定义的 本章中讨论的 bean 的配置格式是定义在 XML 的 Schema 下的 然而, p- 命名空间则不是定义在 XSD 文件下的, 仅仅存在于 Spring 的核心中 下面的示例展示了两个 XML 片段, 解析得到相同的结果 : 第一个使用了标准的 XML 格 式, 第二个使用了 p- 命名空间 <beans xmlns=" xmlns:xsi=" xmlns:p=" xsi:schemalocation=" d"> <bean name="classic" class="com.example.examplebean"> <property name=" " value="foo@bar.com"/> <bean name="p-namespace" class="com.example.examplebean" </beans> p: ="foo@bar.com"/> 示例展示了 p- 命名空间下的属性, 在 bean 的定义中称为 这就告诉 Spring 来包 含属性声明 正如前面提到的,p- 命名空间没有 schema 定义, 所以你可以设置属性的名称 和 bean 中属性的名称一样 下面的示例包含了两个 bean 的定义, 两者都有对其它 bean 的引用 : <beans xmlns=" xmlns:xsi=" xmlns:p=" xsi:schemalocation=" d"> <bean name="john-classic" class="com.example.person"> <property name="name" value="john Doe"/> <property name="spouse" ref="jane"/> <bean name="john-modern" class="com.example.person" p:name="john Doe" p:spouse-ref="jane"/> <bean name="jane" class="com.example.person"> <property name="name" value="jane Doe"/> </beans>

54 正如你所看到的一样, 这个例子包含着不仅仅使用了 p- 命名空间的属性值, 也使用了 特殊格式来声明属性的引用 在第一个 bean 中使用了 <property name="spouse" ref="jane"/> 来创建 john bean 对 jane bean 的引用关系, 第二个 bean 中, 使用了 p:spouse-ref="jane" 作为属性来做相同的事情 本例中,spouse 是属性名, 而 -ref 部分表明了这不是一个直接值而是一个对其它 bean 的引用 注意 P- 命名空间没有标准 XML 格式那么灵活 比如, 声明属性引用的格式和以 Ref 结尾的 属性相冲突, 而标准的 XML 格式则不会 我们建议谨慎选择所用的方法并和开发团队成员充分地交流, 避免产生同时使用这三种方法的 XML 文档 使用 c- 命名空间的 XML 快捷方式 和 节, 使用 p- 命名空间的 XML 快捷方式 相似,c- 命名空间是在 Spring 3.1 中 被引入的, 允许使用内联属性来配置构造方法参数而不是使用 constructor-arg 元素 我们来看 节, 基于构造方法的依赖注入 中的示例, 现在使用 c 命名空间 : <beans xmlns=" xmlns:xsi=" xmlns:p=" xsi:schemalocation=" <bean id="bar" class="x.y.bar"/> <bean id="baz" class="x.y.baz"/> <-- ' 传统的 ' 声明方式 --> <bean id="foo" class="x.y.foo"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> <constructor-arg value="foo@bar.com"/> <-- 'c- 命名空间 ' 声明方式 --> <bean id="foo" class="x.y.foo" c:bar-ref="bar" c:baz-ref="baz" c: ="foo@bar.com"> </beans> c: 命名空间使用了和 p:( 以 -ref 结尾的 bean 引用 ) 相同的转换机制通过它们的名称来设置构造方法参数 这样一来, 即便没有在 XSD schema( 但是存在于 Spring 核心的内部 ) 中定义, 它还是需要声明出来 在极少数的情况下, 构造方法参数名称是不可用的 ( 通常如果字节码在编译时没有调试信息 ), 我们可以使用参数索引 : <-- 'c- 命名空间 ' 索引声明 --> <bean id="foo" class="x.y.foo" c:_0-ref="bar" c:_1-ref="baz">

55 注意 因为 XML 的语法, 索引符号需要在其头部使用 _ 作为 XML 属性名称, 因为 XML 中属性 是不能以数字开头的 ( 尽管一些 IDE 允许这样做 ) 在实际运用中, 构造方法解析机制 ( 节 ) 在匹配参数时是非常有效率的, 所以除 非真有需要, 我们建议在配置中使用名称符号 复合属性名称 在设置 bean 的属性时, 只要路径中的所有组件, 除了最后一个属性名称是非 null 的, 可以使用复合或者嵌套的属性名称 参考下面的 bean 定义 <bean id="foo" class="foo.bar"> foo bean 有一个 fred 属性, 它还有一个 bob 属性, 而它仍有一个 sammy 属性, 而最 终的 sammy 属性被设置成数值 123 为了让这样的配置可用,foo 的属性 fred,fred 的 属性 bob 在 bean 被构造好后必须不能为 null, 否则会抛出 NullPointerException 异常 <property name="fred.bob.sammy" value="123" /> 使用 depends-on 如果一个 bean 是另外一个 bean 的依赖, 通常表明了它会被设置成另外一个的属性 典型的情况是在基于 XML 的配置元数据中使用 <ref/>( 节 ) 元素来完成 然而, 有 时在两个 bean 之间的依赖并不是直接的 ; 比如, 类中的静态初始化器需要触发, 就像数据 库驱动程序的注册 depends-on 属性可以明确地强制一个或多个 bean 在使用这个元素的 bean 被初始化之前被初始化 下面的示例使用了 depends-on 属性来表示一个独立 bean 的依赖 : <bean id="beanone" class="examplebean" depends-on="manager"/> <bean id="manager" class="managerbean" /> 为了表示对多个 bean 的依赖, 提供一个 bean 名称的列表作为 depends-on 属性的值 即可, 要用逗号, 空白或分号分隔开, 它们都是有效的分隔符 : <bean id="beanone" class="examplebean" depends-on="manager,accountdao"> <property name="manager" ref="manager" /> <bean id="manager" class="managerbean" /> <bean id="accountdao" class="x.y.jdbc.jdbcaccountdao" /> 注意在 bean 定义中的 depends-on 属性可以指定初始化时的依赖, 也可以是仅仅是单例 (4.5.1 节 )bean, 对应销毁时的依赖 和给定 bean 定义了 depends-on 关系的依赖 bean 首先被销毁, 先于给定的 bean 本身 因此 depends-on 也能控制关闭顺序

56 4.4.4 延迟初始化 bean 默认情况下,ApplicationContext 的实现类积极地创建并配置所有单例的 bean (4.5.1 节 ), 作为初始化过程的一部分 通常来说, 这种预实例化是非常可取的, 因为在配 置或周边环境中的错误可以直接被发现, 而不是几小时或几天后去发现 当这种行为不可用时, 你可以阻止单例 bean 的预实例化, 在 bean 定义中使用延迟初始化来标记一下就可以 了 延迟初始化 bean 告诉 IoC 容器在该 bean 第一次被请求时再来实例化, 而不是在启动时 实例化 在 XML 中, 这个行为可以通过 <bean/> 元素的 lazy-init 属性来控制 ; 比如 : <bean id="lazy" class="com.foo.expensivetocreatebean" lazy-init="true"/> <bean name="not.lazy" class="com.foo.anotherbean"/> 当前者配置被 ApplicationContext 处理时, 命名为 lazy 的 bean 并不会在 ApplicationContext 启动时被预实例化, 而 not.lazy bean 会被先预实例化 而到延迟初始化 bean 是一个单例 bean 的依赖时, 且这个单例 bean 不是延迟初始化的, 那么 ApplicationContext 也会在启动时来创建延迟初始化的 bean, 因为它必须满足单 例 bean 的依赖 延迟初始化的 bean 被注入到单例 bean 中的时候它就不是延迟初始化的了 你也可以在容器级别来控制延迟初始化, 在 <beans/> 元素上使用 default-lazy-init 属性 ; 比如 : <beans default-lazy-init="true"> <!-- 那么就没有 bean 是预实例化的了... --> </beans> 自动装配协作者 Spring 容器可以自动装配协作 bean 之间的关系 你可以允许 Spring 自动为你的 bean 来 解析协作者 ( 其它 bean), 通过检查 ApplicationContext 的内容即可 自动装配有下 列优势 : 自动装配可以显著减少指定属性或构造方法参数的需要 ( 如 bean 模板的机制, 这将在本章的 4.7 节来讨论, 在这方面是有价值的 ) 自动装配可以更新配置对象的演变 比如, 如果你需要给一个类添加依赖, 那个依赖可 以自动被填入而不需要修改配置 因此, 自动装配在开发期间是非常有用的, 当代码库 变得更稳定时切换到明确的装配也没有否定的选择 当使用基于 XML 的配置元数据 (4.4.1 节 ) 时, 你可以为 bean 的定义指定自动装配模式, 在 <bean/> 元素上设置 autowire 属性即可 自动装配功能有五种模式 你可以为每 个 bean 来指定自动装配, 因此可以选择为哪一个来指定自动装配 no 模式 表 4.2 自动装配模式 解释 ( 默认情况 ) 没有自动装配 Bean 的引用必须通过 ref 元素来定义 对于 大型的部署, 修改默认设置是不推荐的, 因为明确地指定协作者会给予更多

57 的控制和清晰 某种程度上来说, 它勾勒出了系统的结构 byname 通过属性名称来自动装配 Spring 以相同名称来查找需要被自动装配的 bean bytype constructor 比如, 如果 bean 被设置成由名称来自动装配, 并含有一个 master 属性 ( 也 就说, 有 setmaster(..) 方法 ),Spring 会查找名为 master 的 bean 定义, 并且 用它来设置属性 如果 bean 的属性类型在容器中存在的话, 就允许属性被自动装配 如果存 在多于一个, 就会抛出致命的异常, 这就说明了对那个 bean 不能使用 bytype 进行自动装配 如果没有匹配的 bean 存在, 就不会有任何效果 ; 属性不会被设置 和 bytype 类似, 但是是应用于构造方法参数的 如果在容器中没有确定的构 造方法参数类型的 bean 的存在, 就会发生致命的错误 使用 bytype 或 constructor 自动装配模式, 你可以装配数组和集合类型 这种情况下所 有在容器内匹配期望类型的自动装配候选者会被用来满足依赖 如果期望的键类型是 String, 你可以自动装配强类型的 Map 自动装配的 Map 值会包括匹配期望类型的实例, 而且 Map 的键会包含对应 bean 的名称 你可以联合自动装配行为和依赖检查, 这会在自动装配完成之后执行 自动装配的限制和缺点 当在项目中一直使用时, 自动装配是非常不错的 如果自动装配通常是不使用的, 它就 可能会迷惑开发人员来使用它去装配仅仅一两个 bean 考虑一下自动装配的限制和缺点 : 在 property 和 constructor-arg 中设置的明确依赖通常覆盖自动装配 不能自动 装配所谓的简单属性, 比如原生类型,String 和 Class( 还有这样简单属性的数字 ) 这 是由于设计的限制 自动装配没有明确装配那么精确, 尽管, 在上面的表格中已经说明了,Spring 很小心地避免在有歧义的情况下去猜测, 但也可能会有意想不到的结果, 在 Spring 管理的对象 中间的关系可能就不会再清晰地说明了 装配信息可能对从 Spring 容器中来生成文档的工具来说不可用 在容器中的多个 bean 定义可能通过 setter 方法或构造方法参数匹配指定的类型进行自 动装配 对于数组, 集合或 Map, 这不一定是一个问题 而对期望简单值的依赖, 这种歧义不能随意解决 如果没有唯一的 bean 可用, 就会抛出异常 在后面一种情况中, 你有几种选择 : 放弃自动装配而使用明确的装配 避免设置它的 autowire-candidate 属性为 false 来自动装配 bean, 这会在下一 节中来解释 设置 <bean/> 元素的 primary 属性为 true 来指定单独的 bean 作为主要的候选者 如果你使用 Java 5 或更高版本, 使用基于注解的配置实现更细粒度的控制, 这会在 4.9 节, 基于注解的容器配置 中来解释

58 从自动装配中排除 bean 在每个 bean 的基础上, 你可以从自动装配中来排除 bean 在 Spring 的 XML 格式配置 中, 设置 <bean/> 元素的 autowire-candidate 属性为 false; 容器会把指定的 bean 对自动装配不可用 ( 包含注解风格的配置, 节 )) 你也可以基于 bean 名称的模式匹配来限制自动装配候选者 顶级的 <beans/> 元素中 的 default-autowire-candidates 属性接受一个或多个模式 比如, 为了限制自动装 配候选者到任意名称以 Repository 结尾 bean 的状态, 提供 *Repository 值 要提供多个模式, 把它们定义在以逗号分隔的列表中 Bean 定义中 autowire-candidate 属性的 true 或 false 明确的值通常是优先的, 而且对于这些 bean 来说, 模式匹配规则是不适用的 这些技术对那些永远不想通过自动装配被注入到其它 bean 中的 bean 来说是很有用的 这并不意味着未包含的 bean 不能使用自动装配来配置 相反,bean 本身不是自动装配其它 bean 的候选者 方法注入 在很多应用场景中, 很多容器中的 bean 是单例 (4.5.1 节 ) 的 当一个单例的 bean 需 要和其它单例的 bean 协作时, 或者一个非单例的 bean 需要和其它非单例的 bean 协作时, 典型地做法是通过定义一个 bean 作为另外一个的属性来控制依赖 当 bean 的生命周期不 同时问题就产生了 假设单例 bean A 需要使用非单例 (prototype, 原型 )bean B, 或许在 A 的每个方法调用上 容器仅仅创建单例 bean A 一次, 因此仅仅有一次机会去设置属性 容器不能每次为 bean A 提供所需的 bean B 新的实例 解决方法就是放弃一些控制反转 你可通过实现 ApplicationContextAware 接口 以让 bean A 去感知容器 (4.6.2 节 ), 而且在每次 bean A 需要 bean B 的实例时, 可以让容器 调用 getbean( B )(4.2.3 节 ) 去获取 ( 一个新的 )bean B 下面的代码就是这种方式的例子 : // 使用了有状态的命令风格的类来执行一些处理 package fiona.apple; // 导入 Spring 的 API import org.springframework.beans.beansexception; import org.springframework.context.applicationcontext; import org.springframework.context.applicationcontextaware; public class CommandManager implements ApplicationContextAware { private ApplicationContext applicationcontext; public Object process(map commandstate) { // 抓取相应命令的新实例 Command command = createcommand(); // 在命令实例上 ( 希望标记新的 ) 设置状态 command.setstate(commandstate); return command.execute(); protected Command createcommand() { // 注意 Spring API 的依赖! return this.applicationcontext.getbean("command", Command.class);

59 public void setapplicationcontext(applicationcontext applicationcontext) throws BeansException { this.applicationcontext = applicationcontext; 前面的做法是不可取的, 因为这些业务代码感知并耦合到了 Spring 框架中 方法注入, 这种 Spring IoC 容器中的有点先进的功能, 允许以一种干净的方式来处理这个用例 你可以在博客文章中来阅读更多关于方法注入的动机 查找方法注入 查找方法注入是容器在其管理的 bean 上来覆盖方法的能力, 来返回容器中其它命名 bean 的查找结果 查找, 典型的情况是涉及原型 bean, 这是在之前章节中描述的情景 Spring Framework 从 CGLIB 类库中, 通过使用字节码生成机制实现了这种方法注入, 来动态地生成 覆盖方法的子类 注意 要让这些动态子类起作用, 在类路径下必须有 CGLIB 的 jar 文件 这些 Spring 容器中的子类不能是 final 类型的, 要被覆盖的方法也不能是 final 类型的 而且, 测试有 abstract 方法的类要求你自己去编写类的子类并提供 abstract 方法的实现 最后, 是 方法注入目标的对象还不能被序列化 看一下之前代码片段中的 CommandManager 类, 你会看到 Spring 容器会动态地覆盖 createcommand() 方法的实现 CommandManager 类不会有任何 Spring 的依赖, 在重新设计的例子中你会看到 : package fiona.apple; // 没有 Spring API 的导入! public abstract class CommandManager { public Object process(object commandstate) { // 抓取一个心得合适的 Command 接口的实例 Command command = createcommand(); // 在命令实例上 ( 希望标记新的 ) 设置状态 command.setstate(commandstate); return command.execute(); // 好的... 但是这个方法的实现在哪儿? protected abstract Command createcommand(); 在客户端类中包含要被注入 ( 本例中的 CommandManager) 的方法, 要被注入的方法 需要从下面的示例中编写一个签名 : <public protected> [abstract] <return-type> themethodname(no-arguments);

60 如果方法是 abstract 的, 动态生成的子类就实现这个方法 否则, 动态生成的子类覆盖 定义在源类中的确定方法 比如 : <!-- 部署为原型的 ( 非单例的 ) 有状态的 bean --> <bean id="command" class="fiona.apple.asynccommand" scope="prototype"> <!-- 注入所需要的依赖 --> <!-- commandprocessor 使用 statefulcommandhelper --> <bean id="commandmanager" class="fiona.apple.commandmanager"> <lookup-method name="createcommand" bean="command"/> 当需要 command bean 的新的实例时, 标识为 commandmanager 的 bean 调用它自己的方法 createcommand() 部署 command bean 为原型的可必须要小心, 那确实就是需要 的才行 如果被部署为单例的 (4.5.1 节 ), 那么每次会返回相同的 command bean 的实例 提示 感兴趣的读者可能会发现要使用 ServiceLocatorFactoryBean ( 在 org.springframework.beans.factory.config 包下 ) 在 ServiceLocatorFactoryBean 中的使用的方法和其它工具类是相似的,ObjectFactoryCreatingFactoryBean, 但 是它允许你去指定你自己的查找接口而不是 Spring 特定的查找接口 对这些类查询一下 JavaDoc 文档, 还有博客文章来获取 ServiceLocatorFactoryBean 的额外的信息 任意方法的替代 在方法注入中, 用处不如查找方法注入大的一种形式, 就是使用另外一个方法实现来替 换被容器管理的 bean 中的任意方法的能力 用户可以安全地跳过本节的其它部分, 直到你 真正需要这些功能的时候来回过头来看 使用基于 XML 的配置元数据, 对于部署的 bean, 你可以使用 replaced-method 元 素来使用另外一个方法替换已有的方法实现 看看下面这个类, 有一个我们想要去覆盖的 computevalue 方法 : public class MyValueCalculator { public String computevalue(string input) { // 真正的代码... // 其它方法... 实现了 org.springframework.beans.factory.support.methodreplacer 接口的类提供新的方法定义

61 /** 也就是要在 MyValueCalculator 中实现用来覆盖已有的方法 computevalue(string) */ public class ReplacementComputeValue implements MethodReplacer { public Object reimplement(object o, Method m, Object[] args) throws Throwable { // 获取输入值, 并处理它, 返回一个计算的结果 String input = (String) args[0];... return...; 部署源类的 bean 定义和指定的方法覆盖可以是这样的 : <bean id="myvaluecalculator" class="x.y.z.myvaluecalculator"> <!-- 任意方法替换 --> <replaced-method name="computevalue" replacer="replacementcomputevalue"> <arg-type>string</arg-type> </replaced-method> <bean id="replacementcomputevalue" 你可以在 <replaced-method/> 元素中使用一个或多个包含的 <arg-type/> 元素来 指示被覆盖方法的方法签名 如果方法是被重载的并在类中有很多种形式的存在, 那么参数 的签名是必须的 为了简便, 字符串类型的参数可能是类型全名的一个子串 比如, 下面所 有的都匹配 java.lang.string: String Str class="a.b.c.replacementcomputevalue"/> java.lang.string 因为用参数的数量用来区分每一个可能的选择通常是足够的, 这种快捷方式可以节省大量的输入, 允许你去输入匹配参数类型的最短的字符串 4.5 Bean 的范围 当创建 bean 时, 也就创建了对通过 bean 定义创建的类真正实例的配方 bean 定义的 配方这个概念是很重要的, 因为它就意味着, 你可以通过配方来创建一个类的多个对象实例 你不仅可以控制从特定 bean 定义创建出的对象的各个依赖和要配置到对象中的值, 也 可以控制对象的范围 这个方法非常强大并且很灵活, 你可以选择通过配置创建的对象的范 围, 而不必去处理 Java 类级别对象的范围 Bean 可以被定义部署成一种范围 : 开箱,Spring Framework 支持五种范围, 里面的三种仅仅通过感知 web 的 ApplicationContext 可用 下列的范围支持开箱 你也可以创建自定义范围 (4.5.5 节 )

62 范围 单例 (4.5.1 节 ) 表 4.3 Bean 的范围 描述 ( 默认的 ) 为每一个 Spring 的 IoC 容器定义一个 bean 为独立对象的实例 原型 (4.5.2 节 ) 定义可以有任意个对象实例的 bean 请求 ( 节 ) 会话 ( 节 ) 全局会话 ( 节 ) 线程范围的 bean 定义生命周期为一个独立 HTTP 请求的 bean; 也就是说, 每一个 HTTP 请求有一个 bean 的独立的实例而不是一个独立的 bean 仅仅在可感知 Web 的 Spring ApplicationContext 中可用 定义一个生命周期为一个 HTTP Session 的独立的 bean 仅仅在可感知 Web 的 Spring ApplicationContext 中可用 定义一个生命周期为一个全局的 HTTP Session 的独立的 bean 典型地 是仅仅使用 portlet 上下文时可用 仅仅在可感知 Web 的 Spring ApplicationContext 中可用 在 Spring 3.0 当中, 线程范围是可用的, 但是它默认是不注册的 要获取更多信息, 请 参考 SimpleThreadScope 的 JavaDoc 文档 对于如何注册这个范围或其它自定义范围的做法, 请参考 节, 使用自定义范围 单例范围 仅仅共享被管理的 bean 的一个实例, 所有使用一个或多个 id 来匹配 bean 的结果对 bean 请求, 由 Spring 容器返回指定 bean 的实例 另外一种方式, 当你定义一个范围是单例的 bean 后,Spring 的 IoC 容器通过 bean 的定义创建了这个对象的一个实例 这个独立的实例存储在单例 bean 的缓存中, 所有对这个命 名 bean 的后续的请求和引用都返回缓存的对象 Spring 中对单例 bean 的概念和四人帮 (Gang of Four,GoF) 设计模式书中定义的单例 模式是不同的 GoF 的单例硬编码了对象的范围, 也就是特定的类仅仅能有一个实例被每一 个 ClassLoader 来创建 Spring 中单例 bean 的范围, 是对每一个容器和 bean 来说的 这 就意味着在独立的 Spring 容器中, 对一个特定的类创建了一个 bean, 那么 Spring 容器通过 bean 的定义仅仅创建这个类的一个实例 在 Spring 中, 单例范围是默认的范围 要在 XML

63 中定义单例的 bean, 可以按照如下示例来编写 : <bean id="accountservice" class="com.foo.defaultaccountservice"/> <!-- 尽管是冗余的 ( 单例范围是默认的 ), 下面的 bean 定义和它是等价的 --> <bean id="accountservice" class="com.foo.defaultaccountservice" scope="singleton"/> 原型范围 非单例, 原型范围的 bean 就是当每次对指定 bean 进行请求时, 一个新的 bean 的实例 就会创建 也就是说,bean 被注入到其它 bean 或是在容器中通过 getbean() 方法来请求时就 会创建新的 bean 实例 作为一项规则, 对所有有状态的 bean 使用原型范围, 而对于无状 态的 bean 使用单例范围 下图讲述了 Spring 的原型范围 数据访问对象 (DAO) 通常不是配置成原型的, 因为典 型的 DAO 不会持有任何对话状态 ; 仅仅是对作者简单对单例图的重用 下面的示例在 XML 中定义了原型范围的 bean: <!-- 使用 spring-beans-2.0.dtd --> <bean id="accountservice" class="com.foo.defaultaccountservice" scope="prototype"/> 和其它范围相比,Spring 不管理原型 bean 的完整生命周期 ; 容器实例化, 配置并装配 原型对象, 并把他给客户端, 对于原型 bean 的实例来说, 就没有进一步的跟踪记录了 因 此, 尽管初始化生命周期回调方法可以对所有对象调用而不管范围, 那么在原型范围中, 配 置销毁生命周期回调是不能被调用的 客户端代码必须清理原型范围的对象并且释放原型 bean 持有的系统资源 要让 Spring 容器来释放原型范围 bean 持有的资源, 可以使用自定义 bean 后处理器 (4.8.1 节 ), 它持有需要被清理的 bean 的引用 在某些方面, 关于原型范围 bean 的 Spring 容器的角色就是对 Java new 操作符的替代 所有之后生命周期的管理必须由客户端来处理 ( 关于 Spring 容器中 bean 的生命周期的详

Untitled

Untitled Spring 4.0.0 spring-framework-reference QQ 413615763 Weibo le Email not-three@foxmail.com 2013.12.16 2.2 2013.12.17 2.3 : 2013.12.18 2.3 : 2013.12.18 2.3 :- Commons Logging Spring Spring Spring IoC StrutsHibernate

More information

Spring3.x开发入门

Spring3.x开发入门 Spring Bean 管理 Spring 的工厂类 课程安排 Spring 的 Bean 管理 (XML 方式 ) Spring 的属性注入 (XML 方式 ) Spring 的 Bean 管理 ( 注解方式 ) Spring 的属性注入 ( 注解方式 ) Spring 的工厂类 Spring 的 Bean 管理 (XML 方式 ) 三种实例化 Bean 的方式 使用类构造器实例化 ( 默认无参数

More information

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc 1.1 组合 Hibernate 与 Spring 1. 在 Eclipse 中, 新建一个 Web project 2. 给该项目增加 Hibernate 开发能力, 增加 Hibernate 相关类库到当前项目的 Build Path, 同时也提供了 hibernate.cfg.xml 这个配置文件 3. 给该项目增加 Spring 开发能力, 增加 spring 相关类库到当前项目的 Build

More information

SpringFrameWork 3.0 开发教程 2 目 录 第 1 章 SPRING FRAMEWORK 概述 节介绍 SPRING FRAMEWORK 节依赖注入与控制反转 节模块组成...

SpringFrameWork 3.0 开发教程   2 目 录 第 1 章 SPRING FRAMEWORK 概述 节介绍 SPRING FRAMEWORK 节依赖注入与控制反转 节模块组成... SpringFrameWork 3.0 开发教程 http://www.elearn007.com 1 Spring FrameWork3.0 开发教程 作者 :JAVA 自由城市 http://www.elearn007.com 加入 VIP 会员咨询 QQ:1229173104 友情提示 : 教程都是网站原创出品,JAVA 自由城市提供专业的 JAVA 软件工程师培训 专业, 不俗的技术实力,

More information

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 本章学习目标 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 配置视图解析器 @RequestMapping 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 和 Struts2 都属于表现层的框架, 它是 Spring 框架的一部分, 我们可 以从 Spring 的整体结构中看得出来 :

More information

第03章 控制反转(Spring IoC)

第03章  控制反转(Spring IoC) 3 Spring IoC GoF Design Patterns: Elements of Reusable Object-Oriented Software Programming to an Interface not an Implementation Java Java Java GoF Service Locator IoC IoC Spring IoC 3.1 IoC IoC IoC Dependency

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

IoC容器和Dependency Injection模式.doc

IoC容器和Dependency Injection模式.doc IoC Dependency Injection /Martin Fowler / Java Inversion of Control IoC Dependency Injection Service Locator Java J2EE open source J2EE J2EE web PicoContainer Spring Java Java OO.NET service component

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

设计模式 Design Patterns

设计模式 Design Patterns Spring 与 Struts Hibernate 的集成 丁勇 Email:18442056@QQ.com 学习目标 掌握 Spring 与 Struts 的集成 掌握 Spring 与 Hibernate 的集成 学会使用 Spring 实现声明式事务 Spring 与 Hibernate 集成 使用 Spring 简化 Hibernate 编程 使现有使现有 Java Java EE EE 技术更易用

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

untitled

untitled -JAVA 1. Java IDC 20 20% 5 2005 42.5 JAVA IDC JAVA 60% 70% JAVA 3 5 10 JAVA JAVA JAVA J2EE J2SE J2ME 70% JAVA JAVA 20 1 51 2. JAVA SUN JAVA J2EE J2EE 3. 1. CSTP CSTP 2 51 2. 3. CSTP IT CSTP IT IT CSTP

More information

优迈科技教学大纲2009版本

优迈科技教学大纲2009版本 java 软 件 工 程 师 培 训 教 学 大 纲 1 JAVA 软 件 工 程 师 培 训 教 学 大 纲 深 圳 软 件 园 人 才 实 训 基 地 2009 年 3 月 目 录 java 软 件 工 程 师 培 训 教 学 大 纲 2 教 学 阶 段...3 第 一 章 JAVA 起 步...3 第 二 章 面 向 对 象 的 编 程...4 第 三 章 数 据 结 构 IO 线 程 网 络...5

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat 本章学习目标 小风 Java 实战系列教程 AOP 思想概述 AOP 底层技术实现 AOP 术语介绍 SpringAOP 的 XML 方式 HelloWorld SpringAOP 的 XML 方式配置细节 SpringAOP 的注解方式 SpringAOP 的零配置方式 1. AOP 思想概述 1.1. AOP 思想简介 1.2. AOP 的作用 2. AOP 底层技术实现 小风 Java 实战系列教程

More information

<!-- import outer proper

<!-- import outer proper 概述 基于 Spring 支持的客户端编程, 包括发送方客户端 接收方客户端 发送方客户端代码 :jms-producer 接收方客户端代码 :jms-consumer 发送方客户端 这里基于 demo 进行说明 这个 demo 将往 example.queue 和 example.topic 各发一条信息 文件目录结构 1. src/main/resources/ 2. ---- jndi.properties

More information

Stateless Session Beans(无状态bean)的学习

Stateless Session Beans(无状态bean)的学习 一 Stateless Session Beans( 无状态 bean) 的学习 第一步 : 要定义一个会话 Bean, 首先需要定义一个包含他所有业务方法的接口 这个接口不需要任何注释, 就像普通的 java 接口那样定义 调用 EJB 的客户端通过使用这个接口引用从 EJB 容器得到的会话 Bean 对象 stub 接口的定义如下: HelloWorld.java package com.foshanshop.ejb3;

More information

在Spring中使用Kafka:Producer篇

在Spring中使用Kafka:Producer篇 在某些情况下, 我们可能会在 Spring 中将一些 WEB 上的信息发送到 Kafka 中, 这时候我们就需要在 Spring 中编写 Producer 相关的代码了 ; 不过高兴的是,Spring 本身提供了操作 Kafka 的相关类库, 我们可以直接通过 xml 文件配置然后直接在后端的代码中使用 Kafka, 非常地方便 本文将介绍如果在 Spring 中将消息发送到 Kafka 在这之前,

More information

EJB-Programming-3.PDF

EJB-Programming-3.PDF :, JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Value Object Design Pattern J2EE Design Patterns Value Object Value Object Factory J2EE EJB Test Client

More information

new 进行创建对象, 是程序主动去创建依赖对象 ; 而 IoC 是有专门一个容器来创建这些对象, 即由 Ioc 容器来控制对象的创建 ; 谁控制谁? 当然是 IoC 容器控制了对象 ; 控制什么? 那就是主要控制了外部资源获取 ( 不只是对象包括比如文件等 ) 为何是反转, 哪些方面反转了 : 有

new 进行创建对象, 是程序主动去创建依赖对象 ; 而 IoC 是有专门一个容器来创建这些对象, 即由 Ioc 容器来控制对象的创建 ; 谁控制谁? 当然是 IoC 容器控制了对象 ; 控制什么? 那就是主要控制了外部资源获取 ( 不只是对象包括比如文件等 ) 为何是反转, 哪些方面反转了 : 有 本章学习目标 小风 Java 实战系列教程 Spring 框架简介 SpringIOC 的概念和作用 工厂模式设计一个简单的 IOC 容器 SpringIOC 的 XML 方式 HelloWorld SpringIOC 的 XML 方式创建对象配置细节 SpringIOC 的 XML 方式依赖注入 SpringIOC 的注解方式 Spring 整合 Junit 简化测试类编写 1. Spring 框架简介

More information

untitled

untitled JavaEE+Android - 6 1.5-2 JavaEE web MIS OA ERP BOSS Android Android Google Map office HTML CSS,java Android + SQL Sever JavaWeb JavaScript/AJAX jquery Java Oracle SSH SSH EJB+JBOSS Android + 1. 2. IDE

More information

J2ME ISBN J2ME MIDP MIDP 2.0 API J2ME Netbeans IDE 4.1 Mobility Pack 4.1 MIDlet MIDlet MIDP PUSH API PDA API Ja

J2ME ISBN J2ME MIDP MIDP 2.0 API J2ME Netbeans IDE 4.1 Mobility Pack 4.1 MIDlet MIDlet MIDP PUSH API PDA API Ja Java JBuilder 2005 2005 6 ISBN 7-121-01166-2 69.00 1 688 JBuilder JBuilder 2005 JBuilder JBuilder 2005 JBuilder 2005 Java Java Java JBuilder 17 J2ME 2006 1 ISBN 7-121-02210-9 39.00 1 436 J2ME MIDP MIDP

More information

Spring 的入门程序 依赖注入的概念 依赖注入的实现方式 Spring 的核心容器 Spring 的入门程序 依赖注入的概念 依赖注入的实现方式 依赖注入的概念 了解 Spring 的概念和优点 理解 Spring 中的 IoC 和 DI 思想 掌握 ApplicationContext 容器的

Spring 的入门程序 依赖注入的概念 依赖注入的实现方式 Spring 的核心容器 Spring 的入门程序 依赖注入的概念 依赖注入的实现方式 依赖注入的概念 了解 Spring 的概念和优点 理解 Spring 中的 IoC 和 DI 思想 掌握 ApplicationContext 容器的 Java EE 企业级应用开发教程 (Spring+Spring MVC+MyBatis) 课程教学大纲 ( 课程英文名称 ) 课程编号 : XXXX 学分 : 5 学分学时 : 90 学时 ( 其中 : 讲课学时 :55 上机学时 :35) 先修课程 :Java 基础案例教程 Java Web 程序设计任务教程 MySQL 数据库入门适用专业 : 信息及其计算机相关专业开课部门 : 计算机系 一

More information

序号:001

序号:001 第 一 组 选 题 简 介 序 号 :001 题 目 : 基 于 BPEL 的 网 上 订 餐 系 统 的 设 计 与 实 现 网 上 订 餐 系 统 是 在 互 联 网 上 进 行 菜 单 信 息 发 布 网 上 订 餐 以 及 维 护 客 户 关 系 的 电 子 商 务 系 统, 餐 饮 企 业 可 以 通 过 这 个 电 子 商 务 系 统 发 布 自 己 的 菜 单 信 息 以 供 客 户

More information

EJB-Programming-4-cn.doc

EJB-Programming-4-cn.doc EJB (4) : (Entity Bean Value Object ) JBuilder EJB 2.x CMP EJB Relationships JBuilder EJB Test Client EJB EJB Seminar CMP Entity Beans Session Bean J2EE Session Façade Design Pattern Session Bean Session

More information

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7.

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes 包管理理 工具 Helm 蔺礼强 Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit Tomcat Web JUnit Cactus JUnit Java Cactus JUnit 26.1 JUnit Java JUnit JUnit Java JSP Servlet JUnit Java Erich Gamma Kent Beck xunit JUnit boolean JUnit Java JUnit Java JUnit Java 26.1.1 JUnit JUnit How

More information

输入 project name 选择完成

输入 project name 选择完成 JAVA 程序访问 HighGo DB 的环境准备 山东瀚高科技有限公司版权所有仅允许不作任何修改的转载和转发 Hibernate 的配置 MyEclipse 中创建新项目 : 选择菜单栏 file---new---project 选择 web project 进行下一步 输入 project name 选择完成 4. 单击 " 添加 JAR/ 文件夹 ", 会如下图出现 JDBC 下载 Hibernate

More information

工程项目进度管理 西北工业大学管理学院 黄柯鑫博士 甘特图 A B C D E F G 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 甘特图的优点 : 直观明了 ( 图形化概要 ); 简单易懂 ( 易于理解 ); 应用广泛 ( 技术通用 ) 甘特图的缺点 : 不能清晰表示活动间的逻辑关系 WBS 责任分配矩阵 ( 负责〇审批

More information

将 MD5 的工具类拷贝到项目中 二 微服务模块的搭建 我们将权限的查询放到一个单独的模块中, 这个模块提供接口供给消费者远程调用 (RPC), 这次范例是微服开发的雏形, 在以后你使用 springcloud 的时候会使用到今天的概念 1 使用 maven 创建新的模块 (microboot-sh

将 MD5 的工具类拷贝到项目中 二 微服务模块的搭建 我们将权限的查询放到一个单独的模块中, 这个模块提供接口供给消费者远程调用 (RPC), 这次范例是微服开发的雏形, 在以后你使用 springcloud 的时候会使用到今天的概念 1 使用 maven 创建新的模块 (microboot-sh Shiro 的环境搭建 一 公共模块的搭建 在实际的开发中, 一个项目可能会分多个模块进行实际的开发, 但是这些模块需要使用一些公 共的操作, 那么这些公共的操作不应该在每个模块中重新定义, 而是将这些公共的操作专门定 义在一个公共的模块之后哦在模块中的 pom 文件里面引入这个公共的模块, 比如说 vo 类就是 一个公共的模块, 所以定义到公共类中 1. 定义公共模块 (microboot-shiro-api)maven

More information

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票 复习 创建对象 构造函数 函数重载 : 函数 = 函数名 + 参数列表 public class MyType { int i; double d; char c; void set(double x)

More information

untitled

untitled 653 JAVA 2008 11 Institution of Software Engineer... 2... 4... 4... 5... 5... 8... 8... 8... 8... 8... 9... 9... 9... 11... 13... 13... 13... 13... 15... 15... 15... 15... 16... 16... 17... 17... 17...

More information

拦截器(Interceptor)的学习

拦截器(Interceptor)的学习 二 拦截器 (Interceptor) 的学习 拦截器可以监听程序的一个或所有方法 拦截器对方法调用流提供了细粒度控制 可以在无状态会话 bean 有状态会话 bean 和消息驱动 bean 上使用它们 拦截器可以是同一 bean 类中的方法或是一个外部类 下面介绍如何在 Session Bean 类中使用外部拦截器类 @Interceptors 注释指定一个或多个在外部类中定义的拦截器 下面拦截器

More information

计算机软件技术专业教学计划

计算机软件技术专业教学计划 计 算 机 软 件 技 术 专 业 人 才 培 养 方 案 ( 服 务 外 包 方 向 ) 专 业 大 类 名 称 ( 代 码 ):++(++) 专 业 类 名 称 ( 代 码 ):++++++(++++) 专 业 名 称 ( 代 码 ):+++++++(++++++) 修 业 年 限 : 三 年, 全 日 制 招 生 对 象 : 三 年 制 普 通 高 中 及 对 口 中 职 专 业 毕 业 生

More information

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii 前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii C# 7 More Effective C# C# C# C# C# C# Common Language Runtime CLR just-in-time

More information

基于CDIO一体化理念的课程教学大纲设计

基于CDIO一体化理念的课程教学大纲设计 Java 语 言 程 序 设 计 课 程 教 学 大 纲 Java 语 言 程 序 设 计 课 程 教 学 大 纲 一 课 程 基 本 信 息 1. 课 程 代 码 :52001CC022 2. 课 程 名 称 :Java 语 言 程 序 设 计 3. 课 程 英 文 名 称 :Java Programming 4. 课 程 类 别 : 理 论 课 ( 含 实 验 上 机 或 实 践 ) 5. 授

More information

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取将导致上次获取的 access_token 失效 接入方可以使用 AppID 和 AppSecret

More information

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class

More information

untitled

untitled 4.1AOP AOP Aspect-oriented programming AOP 來說 AOP 令 理 Cross-cutting concerns Aspect Weave 理 Spring AOP 來 AOP 念 4.1.1 理 AOP AOP 見 例 來 例 錄 Logging 錄 便 來 例 行 留 錄 import java.util.logging.*; public class HelloSpeaker

More information

1

1 PRIMETON TECHNOLOGIES, LTD. EOS EOS Manager No part of this document may be reproduced, stored in any electronic retrieval system, or transmitted in any form or by any means, mechanical, photocopying,

More information

设计模式 Design Patterns

设计模式 Design Patterns 丁勇 Email:18442056@QQ.com 组件技术概述 现在软件开发都已经转向了基于组件的开发, 目前具备代表性的组件技术有微软的 COM COM+, 有 Sun 的 Bean 和 EJB(Enterprise Bean), 另外还有 CORBA(Common Object Request Broker Architecture, 公 共对象请求代理结构 ) Bean Bean 规范将 软件组件

More information

Microsoft Word - 第7章 初识Hibernate—教学大纲.doc

Microsoft Word - 第7章 初识Hibernate—教学大纲.doc SSH 框架整合实战教程 课程教学大纲 ( 课程英文名称 ) 课程编号 : 学分 : 5 学分学时 : 108 学时 ( 其中 : 讲课学时 :76 上机学时 :32) 先修课程 :Java 基础入门 MySQL 数据库入门 JavaWeb 程序开发入门 JavaWeb 程序开发进阶适用专业 : 信息及其计算机相关专业开课部门 : 计算机系 一 课程的性质与目标 SSH 框架整合实战教程 是面向计算机相关专业的一门专业

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型 文 章 编 号 :1007-757X(2012)1-0036-04 领 域 驱 动 模 型 的 WEB 软 件 系 统 设 计 研 究 摘 要 : J2EE 3 JDK1.7 Tomcat WEB 关 键 词 : 中 图 分 类 号 :TP311 文 献 标 志 码 :A 0 引 言 Web 软 件 系 统 的 分 层 结 构 典 型 的 J2EE 软 件 系 统 开 发 方 法 分 为 三 层 结

More information

<4D6963726F736F667420576F7264202D2031A3AD4A617661BCBCCAF5CAC6CDB7D5FDBEA22E646F63>

<4D6963726F736F667420576F7264202D2031A3AD4A617661BCBCCAF5CAC6CDB7D5FDBEA22E646F63> Java 技 术 的 势 头 正 劲 清 华 大 学 计 算 机 科 学 与 技 术 系 李 涓 子 徐 鹏 王 克 宏 Java 技 术 已 经 遍 布 世 界 各 个 角 落, 从 智 能 卡 Java 手 机 和 电 话, 到 汽 车 生 产 以 至 于 控 制 火 星 漫 游 者 号 的 临 界 任 务 系 统 都 能 看 到 它 的 作 用,Java 已 经 成 为 一 种 普 遍 深 入

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d =

More information

Java 1 Java String Date

Java 1 Java String Date JAVA SCJP Java 1 Java String Date 1Java 01 Java Java 1995 Java Java 21 Java Java 5 1-1 Java Java 1990 12 Patrick Naughton C++ C (Application Programming Interface API Library) Patrick Naughton NeXT Stealth

More information

2 Java 语 言 程 序 设 计 教 程 1.2.1 简 单 性 Java 语 言 的 语 法 与 C 语 言 和 C++ 语 言 很 接 近, 使 得 大 多 数 程 序 员 很 容 易 学 习 和 使 用 Java 另 一 方 面,Java 丢 弃 了 C++ 中 很 少 使 用 的 很 难

2 Java 语 言 程 序 设 计 教 程 1.2.1 简 单 性 Java 语 言 的 语 法 与 C 语 言 和 C++ 语 言 很 接 近, 使 得 大 多 数 程 序 员 很 容 易 学 习 和 使 用 Java 另 一 方 面,Java 丢 弃 了 C++ 中 很 少 使 用 的 很 难 第 1 章 Java 概 述 Java 的 诞 生 Java 的 特 点 Java 开 发 环 境 安 装 与 配 置 创 建 并 运 行 一 个 简 单 的 Java 程 序 Java 语 言 是 当 今 计 算 机 软 件 行 业 中 最 热 门 的 网 络 编 程 语 言, 以 Java 为 核 心 的 芯 片 技 术 编 译 技 术 数 据 库 连 接 技 术, 以 及 基 于 企 业 级

More information

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

res/layout 目录下的 main.xml 源码 : <?xml version=1.0 encoding=utf 8?> <TabHost android:layout_height=fill_parent xml 拓展训练 1- 界面布局 1. 界面布局的重要性做应用程序, 界面是最基本的 Andorid 的界面, 需要写在 res/layout 的 xml 里面, 一般情况下一个 xml 对应一个界面 Android 界面布局有点像写 html( 连注释代码的方式都一样 ), 要先给 Android 定框架, 然后再在框架里面放控件,Android 提供了几种框架,AbsoluteLayout,LinearLayout,

More information

目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放 性... 8 3.5 高 性 能 和

目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放 性... 8 3.5 高 性 能 和 致 远 协 同 管 理 软 件 V5 平 台 白 皮 书 北 京 致 远 协 创 软 件 有 限 公 司 2014 年 6 月 1 / 20 目 录 目 录... 2 1 平 台 概 述... 3 2 技 术 架 构... 4 3 技 术 特 点... 7 3.1 基 于 统 一 平 台 的 多 产 品 线 支 撑... 7 3.2 先 进 性... 7 3.3 安 全 性... 7 3.4 开 放

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information

水晶分析师

水晶分析师 大数据时代的挑战 产品定位 体系架构 功能特点 大数据处理平台 行业大数据应用 IT 基础设施 数据源 Hadoop Yarn 终端 统一管理和监控中心(Deploy,Configure,monitor,Manage) Master Servers TRS CRYSTAL MPP Flat Files Applications&DBs ETL&DI Products 技术指标 1 TRS

More information

北京北信源软件股份有限公司招股书(申报稿)

北京北信源软件股份有限公司招股书(申报稿) qimingengz 31 创 业 板 投 资 风 险 提 示 本 次 股 票 发 行 后 拟 在 创 业 板 市 场 上 市, 该 市 场 具 有 较 高 的 投 资 风 险 创 业 板 公 司 具 有 业 绩 不 稳 定 经 营 风 险 高 退 市 风 险 大 等 特 点, 投 资 者 面 临 较 大 的 市 场 风 险 投 资 者 应 充 分 了 解 创 业 板 市 场 的 投 资 风 险 及

More information

Office Office Office Microsoft Word Office Office Azure Office One Drive 2 app 3 : [5] 3, :, [6]; [5], ; [8], [1], ICTCLAS(Institute of Computing Tech

Office Office Office Microsoft Word Office Office Azure Office One Drive 2 app 3 : [5] 3, :, [6]; [5], ; [8], [1], ICTCLAS(Institute of Computing Tech - OfficeCoder 1 2 3 4 1,2,3,4 xingjiarong@mail.sdu.edu.cn 1 xuchongyang@mail.sdu.edu.cn 2 sun.mc@outlook.com 3 luoyuanhang@mail.sdu.edu.cn 4 Abstract. Microsoft Word 2013 Word 2013 Office Keywords:,, HTML5,

More information

基于ECO的UML模型驱动的数据库应用开发1.doc

基于ECO的UML模型驱动的数据库应用开发1.doc ECO UML () Object RDBMS Mapping.Net Framework Java C# RAD DataSetOleDbConnection DataGrod RAD Client/Server RAD RAD DataReader["Spell"].ToString() AObj.XXX bug sql UML OR Mapping RAD Lazy load round trip

More information

Struts2自定义类型转换.doc

Struts2自定义类型转换.doc Struts2 自定义类型转换 原理 struts2 的自定义类型转换机制为复杂类型的输入输出处理提供了便捷.struts2 已经为我们提供了几乎所有的 primitive 类型以及常用类型 ( 如 Date) 的类型转换器, 我们也可以为我们自定义类添加自定义类型转化器. struts2 为我们提供了一个类型转化器的入口 : ognl.defaulttypeconverter, 或继承 org.apache.struts2.util.strutstypeconverter,

More information

Hive:用Java代码通过JDBC连接Hiveserver

Hive:用Java代码通过JDBC连接Hiveserver Hive: 用 Java 代码通过 JDBC 连接 Hiveserver 我们可以通过 CLI Client Web UI 等 Hive 提供的用户接口来和 Hive 通信, 但这三种方式最常用的是 CLI;Client 是 Hive 的客户端, 用户连接至 Hive Server 在启动 Client 模式的时候, 需要指出 Hive Server 所在节点, 并且在该节点启动 Hive Server

More information

长 安 大 学 硕 士 学 位 论 文 基 于 数 据 仓 库 和 数 据 挖 掘 的 行 为 分 析 研 究 姓 名 : 杨 雅 薇 申 请 学 位 级 别 : 硕 士 专 业 : 计 算 机 软 件 与 理 论 指 导 教 师 : 张 卫 钢 20100530 长安大学硕士学位论文 3 1 3系统架构设计 行为分析数据仓库的应用模型由四部分组成 如图3 3所示

More information

软件工程文档编制

软件工程文档编制 实训抽象类 一 实训目标 掌握抽象类的定义 使用 掌握运行时多态 二 知识点 抽象类的语法格式如下 : public abstract class ClassName abstract void 方法名称 ( 参数 ); // 非抽象方法的实现代码 在使用抽象类时需要注意如下几点 : 1 抽象类不能被实例化, 实例化的工作应该交由它的子类来完成 2 抽象方法必须由子类来进行重写 3 只要包含一个抽象方法的抽象类,

More information

Java应用框架Spring实验指导书.doc

Java应用框架Spring实验指导书.doc Java Spring lyaiqing@126.com Spring 1. Spring jsp 001 Spring name mike password name Tom password 123456 Mysql 1. a) i. mysql Empl, sql 1. 2. a) Eclipse Web Project :myspring b) jar i. / ii. spring-framework-3.2.0.release

More information

IDEO_HCD_0716

IDEO_HCD_0716 IDEO HCD Toolkit Tencent CDC ...? Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC

More information

目 录 1. 业 务 流 程 系 统 开 发 面 临 的 挑 战 与 机 遇... 3 1.1 业 务 流 程 管 理... 4 2. 新 一 代 开 源 业 务 流 程 开 发 平 台 BPMX3... 5 2.1 BPMX3 是 什 么... 5 2.2 为 什 么 要 优 先 采 用 BPMX

目 录 1. 业 务 流 程 系 统 开 发 面 临 的 挑 战 与 机 遇... 3 1.1 业 务 流 程 管 理... 4 2. 新 一 代 开 源 业 务 流 程 开 发 平 台 BPMX3... 5 2.1 BPMX3 是 什 么... 5 2.2 为 什 么 要 优 先 采 用 BPMX BPMX3 技 术 白 皮 书 业 务 流 程 开 发 平 台 介 绍 目 录 1. 业 务 流 程 系 统 开 发 面 临 的 挑 战 与 机 遇... 3 1.1 业 务 流 程 管 理... 4 2. 新 一 代 开 源 业 务 流 程 开 发 平 台 BPMX3... 5 2.1 BPMX3 是 什 么... 5 2.2 为 什 么 要 优 先 采 用 BPMX3... 5 2.2.1 BPMX3

More information

Ioncube Php Encoder 8 3 Crack 4. llamaba octobre traslado General Search colony

Ioncube Php Encoder 8 3 Crack 4. llamaba octobre traslado General Search colony Ioncube Php Encoder 8 3 Crack 4 ->>->>->> DOWNLOAD 1 / 5 2 / 5 Press..the..General..Tools..category4Encrypt..and..protect..files..with..PHP..encoding,..encryption,..ob fuscation..and..licensing... 2016

More information

附件3:

附件3: 目 录 第 一 部 分 主 体 部 分... 1 一 专 业 建 设 发 展 情 况... 1 二 专 业 培 养 目 标... 4 三 就 业 面 向... 7 四 毕 业 要 求... 10 五 课 程 体 系 与 核 心 课 程... 10 六 实 践 教 学 基 本 要 求... 16 七 教 学 及 课 程 安 排... 21 八 继 续 专 业 学 习 深 造 建 议... 25 九 其

More information

<4D6963726F736F667420576F7264202D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63>

<4D6963726F736F667420576F7264202D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63> 基 于 Android 平 台 的 电 子 拍 卖 系 统 摘 要 本 电 子 拍 卖 系 统 其 实 就 是 一 个 电 子 商 务 平 台, 只 要 将 该 系 统 部 署 到 互 联 网 上, 客 户 都 可 以 在 该 系 统 上 发 布 想 出 售 的 商 品, 也 可 以 对 拍 卖 中 的 商 品 参 与 竞 价 整 个 过 程 无 须 人 工 干 预, 由 系 统 自 动 完 成 本

More information

untitled

untitled How to using M-Power Report API M-Power Report API 力 了 M-Power Report -- Java (Library) M-Power Report API 行 Java M-Power Report M-Power Report API ( 30 ) PDF/HTML/CSV/XLS JPEG/PNG/SVG 料 料 OutputStream

More information

D C 93 2

D C 93 2 D9223468 3C 93 2 Java Java -- Java UML Java API UML MVC Eclipse API JavadocUML Omendo PSPPersonal Software Programming [6] 56 8 2587 56% Java 1 epaper(2005 ) Java C C (function) C (reusability) eat(chess1,

More information

jsp

jsp JSP Allen Long Email: allen@huihoo.com http://www.huihoo.com 2004-04 Huihoo - Enterprise Open Source http://www.huihoo.com 1 JSP JSP JSP JSP MVC Huihoo - Enterprise Open Source http://www.huihoo.com 2

More information

Microsoft Word - 王彬_已修改_.doc

Microsoft Word - 王彬_已修改_.doc 第 39 卷 第 1 期 应 用 科 技 Vol.39, No.1 2012 年 2 月 Applied Science and Technology Feb. 2012 doi:10.3969/j.issn.1009-671x.201110009 基 于 J2EE 网 络 教 学 系 统 的 设 计 与 实 现 李 静 梅, 王 彬, 彭 晴 晴 哈 尔 滨 工 程 大 学 计 算 机 科 学 与

More information

weblogic

weblogic Weblogic Allen Long allen@huihoo.com http://www.huihoo.com 2004-04 1 WebLogic, WLS WLS Domain 2 Weblogic6.1 Weblogic6.1 J2EE1.2,J2EE1.3 HTTP 1.1 J2EE Connector Architecture 1.0 J2EE EJB 2.0 J2EE JDBC 2.0

More information

Chapter #

Chapter # 第三章 TCP/IP 协议栈 本章目标 通过本章的学习, 您应该掌握以下内容 : 掌握 TCP/IP 分层模型 掌握 IP 协议原理 理解 OSI 和 TCP/IP 模型的区别和联系 TCP/IP 介绍 主机 主机 Internet TCP/IP 早期的协议族 全球范围 TCP/IP 协议栈 7 6 5 4 3 应用层表示层会话层传输层网络层 应用层 主机到主机层 Internet 层 2 1 数据链路层

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

欢迎访问动力节点官方网站,动力节点java0基础免费学习半个月,java就业班免费学习一个月,满意后再交学费,请稊等,正在为您接入咨询老师

欢迎访问动力节点官方网站,动力节点java0基础免费学习半个月,java就业班免费学习一个月,满意后再交学费,请稊等,正在为您接入咨询老师 JDK 中的设计模式应用实例在 JDK(Java Development Kit) 类库中, 开发人员使用了大量设计模式, 正因为如此, 我们可以在不修改 JDK 源码的前提下开发出自己的应用软件, 本文列出了部分 JDK 中的模式应用实例, 有兴趣的同学可以深入研究, 看看前 Sun 公司的开发人员是如何在实际框架开发中运用设计模式的,Sunny 认为, 研究 JDK 类库中的模式实例也不失为学习如何使用设计模式的一个好方式.

More information

Spring 3.x权威开发指南:实施Java EE 6的利器

Spring 3.x权威开发指南:实施Java EE 6的利器 Spring 3.x 权威开发指南 : 实施 Java EE 6 的利器 罗时飞著 http://www.open-v.com 2010 年 3 月 25 日 版权所有 侵权必究 目录 序... VIII 前言... X 1 借助 Spring 3.0 实施 Java EE 6... 1 1.1 Java EE 6 编程模型讨论... 1 1.1.1 Java EE 6 够敏捷,No!... 1 1.1.2

More information

使用MapReduce读取XML文件

使用MapReduce读取XML文件 使用 MapReduce 读取 XML 文件 XML( 可扩展标记语言, 英语 :extensible Markup Language, 简称 : XML) 是一种标记语言, 也是行业标准数据交换交换格式, 它很适合在系统之间进行数据存储和交换 ( 话说 Hadoop H ive 等的配置文件就是 XML 格式的 ) 本文将介绍如何使用 MapReduce 来读取 XML 文件 但是 Had oop

More information

FAQ -PowerDesigner9.5.DOC

FAQ -PowerDesigner9.5.DOC PowerDesigner 9.5 FAQ 1. PowerDesigner PowerDesigner PowerDesigner (CASE Tool,Computer Aided Software Engineering) PowerDesigner 1989 9.5 2. PowerDesigner PowerDesigner Internet ( Java) PowerDesigner 7.0

More information

论文,,, ( &, ), 1 ( -, : - ), ; (, ), ; ;, ( &, ),,,,,, (, ),,,, (, ) (, ),,, :. : ( ), ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ), ( ),,,, 1 原译作 修补者, 但在英译版本中, 被译作

论文,,, ( &, ), 1 ( -, : - ), ; (, ), ; ;, ( &, ),,,,,, (, ),,,, (, ) (, ),,, :. : ( ), ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ), ( ),,,, 1 原译作 修补者, 但在英译版本中, 被译作 * 夏传玲 : 本文简要回顾了国内外定性研究在最近 多年的发展概况, 总结 了定性研究的六个发展趋势和分析策略上的三种流派 在上述两种背景下, 本文探讨了计算机辅助的定性分析给定性研究带来的机遇和挑战, 特别是它和手工操作对比时的优势和劣势, 以及应用这种定性分析技术所可能面临的困难 : 定性研究定性分析 文化差异,, (, ),,,, ( - ) ( - ) ( - ) ( - ) ( - ) (

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

LiveBOS产品白皮书

LiveBOS产品白皮书 面 向 对 象 的 业 务 支 撑 平 台 与 建 模 工 具 * 实 现 应 您 所 需, 随 时 而 变 的 应 用 * 业 务 管 理 应 用 软 件 最 佳 选 择 * LiveBOS 产 品 白 皮 书 LiveBOS 产 品 白 皮 书 福 州 顶 点 信 息 管 理 有 限 公 司 http://www.apexinfo.com.cn Copyright c 2008-2015 版 权

More information

(Microsoft Word - \272\364\263q\245|\244A_49636107_\304\254\253\330\336\263__\272\353\302\262\263\370\247i.doc)

(Microsoft Word - \272\364\263q\245|\244A_49636107_\304\254\253\330\336\263__\272\353\302\262\263\370\247i.doc) SCJP (Oracle Certified Professional, Java SE5/6 Programmer) 學 制 / 班 級 : 四 年 制 / 網 通 四 乙 指 導 老 師 : 方 信 普 老 師 學 生 學 號 / 姓 名 : 49636107 蘇 建 瑋 繳 交 年 份 : 100 年 6 月 一 SCJP 介 紹 SCJP 是 Sun Certified Java Programmer

More information

停止混流接口 请注意 : 该功能需要联系 ZEGO 技术支持开通 1 接口调用说明 http 请求方式 : POST/FORM, 需使用 https 正式环境地址 access_token=access_token (http

停止混流接口 请注意 : 该功能需要联系 ZEGO 技术支持开通 1 接口调用说明 http 请求方式 : POST/FORM, 需使用 https 正式环境地址   access_token=access_token (http 停止混流接口 请注意 : 该功能需要联系 ZEGO 技术支持开通 1 接口调用说明 http 请求方式 : POST/FORM, 需使用 https 正式环境地址 https://webapi.zego.im/cgi/stop-mix? access_token=access_token (https://webapi.zego.im/cgi/stop-mix? access_token=access_token)

More information

第四章 102 图 4唱16 基于图像渲染的理论基础 三张拍摄图像以及它们投影到球面上生成的球面图像 拼图的圆心是相同的 而拼图是由球面图像上的弧线图像组成的 因此我 们称之为同心球拼图 如图 4唱18 所示 这些拼图中半径最大的是圆 Ck 最小的是圆 C0 设圆 Ck 的半径为 r 虚拟相机水平视域为 θ 有 r R sin θ 2 4畅11 由此可见 构造同心球拼图的过程实际上就是对投影图像中的弧线图像

More information

云数据库 RDS SDK

云数据库 RDS SDK 云数据库 RDS SDK SDK SDK 下载 SDK 下载 最新版本 java_sdk.zip python_sdk.zip php_sdk.zip c#_sdk.zip 历史版本 2015-11-3 java_sdk.zip python_sdk.zip php_sdk.zip c#_sdk.zip JAVA 教程 JAVA 创建 Access Key 登陆阿里云账号 打开 我的 Access

More information

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6 www.brainysoft.net 1.JasperReport ireport...4 1.1 JasperReport...4 1.2 ireport...4 2....4 2.1 JDK...4 2.1.1 JDK...4 2.1.2 JDK...5 2.1.3 JDK...5 2.2 ant...6 2.2.1 ant...6 2.2.2 ant...6 2.3 JasperReport...7

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc 2 5 8 11 0 13 1. 13 2. 15 3. 18 1 23 1. 23 2. 26 3. 28 2 36 1. 36 2. 39 3. 42 4. 44 5. 49 6. 51 3 57 1. 57 2. 60 3. 64 4. 66 5. 70 6. 75 7. 83 8. 85 9. 88 10. 98 11. 103 12. 108 13. 112 4 115 1. 115 2.

More information

季刊9web.indd

季刊9web.indd 在 全 国 现 场 会 上 成 功 展 示 全 国 烟 叶 收 购 暨 现 代 烟 草 农 业 建 设 现 场 会 7 月 6 日 至 8 日 在 昆 明 召 开 在 国 家 局 的 领 导 下, 由 我 司 技 术 开 发 的 烟 站 ( 单 元 ) 烟 叶 管 理 信 息 系 统 在 现 场 会 上 成 功 展 示, 并 得 到 参 会 领 导 及 代 表 们 的 关 注 与 认 可 该 系 统

More information

android讲座

android讲座 湖 南 卓 景 京 信 息 移 动 互 联 行 业 -- JAVA+Android 湖 南 卓 景 京 信 息 主 要 内 容 一. 移 动 互 联 网 行 业 介 绍 二.Java 和 Android 三. 行 业 前 景 和 用 人 需 求 四. 我 们 该 怎 么 做 湖 南 卓 景 京 信 息 李 海 波 ( 软 件 架 构 师 项 目 经 理 技 术 总 监 ) QQ:50859246 行

More information

1. 2. Flex Adobe 3.

1. 2. Flex Adobe 3. 1. 2. Flex Adobe 3. Flex Adobe Flex Flex Web Flex Flex Flex Adobe Flash Player 9 /rich Internet applications/ria Flex 1. 2. 3. 4. 5. 6. SWF Flash Player Flex 1. Flex framework Adobe Flex 2 framework RIA

More information

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0, http://debut.cis.nctu.edu.tw/~chi Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0, : POSITIVE_INFINITY NEGATIVE_INFINITY

More information

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 310-065Big5 Title : Sun Certified Programmer for the Java 2 Platform, SE 6.0 Version : Demo 1 / 14 1. 35. String #name = "Jane Doe"; 36. int

More information

Dia 1

Dia 1 平台 第 1 部分 主题 托管 Bean Servlet 3.0 JPA 2.0 Alexis Moussine-Pouchkine GlassFish 团队 总体演示目标 侧重于 Java EE 6 的新特性 编写一个 web 应用程序 如果了解 Java EE 5 会更好 这不是科幻小说 Java EE 6 和 GlassFish v3 于 2009 年 12 月 10 日发布了 最终版本 议题

More information

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7

软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7 计 算 机 系 软 件 工 程 专 业 习 指 南 广 东 科 技 院 计 算 机 系 2015-9-1 软 件 工 程 专 业 习 指 南 目 录 一 软 件 工 程 专 业 设 置 背 景 与 发 展 前 景... 3 二 软 件 工 程 专 业 实 践 教 条 件... 4 三 软 件 工 程 专 业 课 程 类 型 及 核 方 式... 6 1. 软 件 工 程 专 业 课 程 类 型...7

More information

PowerPoint Presentation

PowerPoint Presentation 1 版权所有 2011,Oracle 和 / 或其分支机构 保留所有权利 从幻灯片 8 中插入信息保护策略分类 WAC Widget Java ME 手机新动向陈志宇 2 版权所有 2011,Oracle 和 / 或其分支机构 保留所有权利 从幻灯片 8 中插入信息保护策略分类 以下内容旨在概述我们产品总的发展方向 该内容仅供参考, 不可纳入任何合同 该内容不构成提供任何材料 代码或功能的承诺, 并且不应该作为制定购买决策的依据

More information

Eclipse 插件之Spring IDE

Eclipse 插件之Spring IDE Eclipse 插件之 Spring IDE 本文介绍如何利用 Eclipse 插件 Spring IDE 在 Eclipse 中的使用 Eclipse 是目前非常流行的开发平台, 开放扩展的架构让很多程序员找到了自己个性化的工作环境 问题提出 : 在采用 Spring 框架进行系统开发时,Bean 的配置文件 XML 的书写 XML 文件的内容校验及 Bean 之间的依赖关系查看等工作, 如果能够采用合适的工具来完成,

More information

册子0906

册子0906 IBM SelectStack ( PMC v2.0 ) 模块化私有云管理平台 是跨主流虚拟化技术的统一资源云管理平台 01 亮点 : 快速可靠地实现集成化 私有云管理平台 02/03 丰富的功能支持企业数据中心云计算 扩展性强 : 简单易用 : 04/05 功能丰富 : 06/07 为什么选择 IBM SelectStack (PMC v2.0)? 快速实现价值 提高创新能力 降低 IT 成本 降低复杂度和风险

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information