Spring框架第 1 部分 开发方法学
Apache Geronimo 最新的 1.1 版具有很多引人注目的新特性,其核心为控制反转 (Inversion Of Control,IoC) 模型,这个模型也是 Spring 框架的核心模式。Spring 框架是在 Apache 许可协议下开发的,是一个分层的 Java™ Platform, Enterprise Edition (Java EE) 和 Java 2 Platform, Enterprise Edition (J2EE™) 应用程序框架。Spring 框架构建在 Java EE 应该更易于使用的基础上。本系列教程共分为六部分,涵盖了 Spring 框架从前端到后端的全部内容,包括如何用 Apache Geronimo 实现其功能的内容。本期教程是本系列教程的第 1 部分,将向您介绍 Spring 框架的架构,并探讨了 Geronimo 和 Spring 之间交叉的内容。
开始之前
本系列教程面向的读者是想深入了解 spring 框架,并想知道如何在 Apache Geronimo 应用服务器上发挥其强大功能的 Java EE 开发人员。
这个分为六部分的系列教程介绍了 Spring 框架以及如何在 Geronimo 中使用它。首先,我们将研究不同的 Spring 框架方法学,以及这几种方法学是如何在 Geronimo server 上工作的。在本系列教程中,将开发和部署一个个人地址薄应用程序。该应用程序包括下列功能:
- 显示地址薄
- 显示每个条目的详情
- 给地址薄添加一个新条目
- 编辑、修改和删除一个条目
在第 1 部分中,介绍了 Spring 框架的各个模块,以及各模块与 Geronimo 应用服务器上 java EE 应用程序开发工作的关系。还阐述了 Spring 框架所基于的方法学。
第 2 部分回顾了如何在 Geronimo 上使用 Spring 框架构建第一个只有骨架的应用程序。
在第 3 部分,通过添加由 Apache Derby 数据库提供的 Java Database Connectivity (JDBC™) 支持,对第 2 部分的 Geronimo 应用程序进行了扩展。您还将学习如何使用 iBatis 把对象关系映射集成到这个应用程序中。
在第 4 部分里,您将接触到 Spring 面向方面编程(aspect-oriented programming,AOP)和 Spring Web 框架的内容。通过使用 Spring AOP,可把任何由 Spring 框架管理的对象变成面向方面的。本教程依赖于 Spring AOP 所提供的声明性事务管理服务。
第 5 部分考察了 Spring 的模型–视图–控制器 (MVC) 架构。该教程向读者介绍了 Spring MVC 的 MVC 框架和 Web 视图,让读者对 Spring MVC 有初步的了解。
在本教程结束的第 6 部分,介绍了如何通过 Spring 框架使用 JavaServer Page™(JSP™)、Velocity、Tile 和 PDF 导出功能。您将使用和体验 Spring MVC 内置的各种 Web 视图。
![]() ![]() |
Spring 不仅仅是又一个应用程序框架。它纳入了经验丰富的架构师们在应用程序方面的最佳实践,是一个经过深思熟虑精心设计的框架。Rod Johnson 所著的 Expert One-on-One J2EE Design and Development 一书(参见 参考资料 部分的链接)中首先介绍了这个框架。对于 Spring 所提供的对象依赖性、实现和配置特性的分离的重要性,业界并没有马上理解和承认,但是,现在这个理念已经得到广泛的认可,使 Spring 成为近期最引人注意的框架之一。
如何使各组件去耦是应用程序系统分析员和开发人员们共同面对的一个棘手问题。许多框架试图解决这个问题,但都没有成功。由于 Spring 和 Geronimo 都采用 IoC 作为核心设计模式,所以现在有可能实现这种程度的配置分离。Spring 还简化了每个组件的测试。对于用 Spring 框架开发并部署在 Geronimo 上的组件,比较容易进行单独的测试,因为这些组件与它可能依赖的组件已经去耦了。
本教程介绍了 Spring 框架的各个模块,以及各模块与 Geronimo 应用服务器上 Java EE 应用程序开发工作的关系,为学习后续教程做准备。
本教程假定读者熟悉面向对象的编程(OOP),并了解 java ee 的术语。了解面向方面编程则更好,但不是必需的。
Spring 框架和 Apache Geronimo
首先我们来看下 Spring 框架的架构、构成该框架的 7 个模块以及它们与 Geronimo 的关系。
尽管有其他一些轻量级框架(如 Struts),但这些框架主要面向的是 Web 层。而 Spring 不仅处理 Web 层,还处理业务层的问题,此外,它还具有一些强大的集成选项,可连接到不同的数据库,如 Derby。Spring 是一个很全面的框架,包括 MVC 框架、AOP 集成框架、JDBC 框架和对象关系映射(ORM)组件,通过这些组件可与诸如 hibernate 和 Java Data Objects(JDO)之类的工具集成。
Spring 框架包含了许多功能和特性,它们在不同的层实现,各层间清晰地相互隔离。Spring 框架的分层架构允许您决定需要实现哪些组件。这种结构让您能够灵活地在各阶段使用 Spring,我们可以使用一个 Spring 组件,让它工作,然后再选择另一个组件。
Spring 架构中包括 7 个组织良好的模块。这些 Spring 模块设计在核心容器之上。核心容器的职能是充当 bean 容器,在运行时创建、管理和设置 bean。如 图 1 所示。
![]() ![]() |
那么,是什么让 Spring 框架可以很好地与 Geronimo 协同工作呢?这两种技术之所以具有互补性是由于以下一些事实细节:
- Geronimo 和 Spring 框架都允许松散地耦合各种应用程序组件。
- 二者都使用 IoC(也称为依赖性注入)来实现这样的去耦。
- 二者都没有试图重新实现的东西,而是尽可能利用现有的开放源码 API。
IoC 是一种有助于消除 OOP 组件之间耦合的设计模式。它通过消除某一组件 (X) 对另一组件 (Y) 的依赖性来实现。实现 IoC 有几种不同的方法,但基本方式是通过在 X 和 Y 之间引入接口来实现。Spring 框架容器在运行时管理依赖性解析(dependency resolution)和对象的生命周期。
![]() ![]() |
Spring 核心
Spring 的核心容器是该框架最重要和基本的部分。它提供了 IoC 功能,允许对 bean 容器进行管理。该核心的一个基本组件是 BeanFactory
,这是基本工厂模式的一个实现。它使应用程序的配置和依赖性规范与实际编程逻辑清晰地分离开。
org.springframework.beans
包为 Spring 的 IoC 特性提供了基础。需要考虑的最重要的接口之一是 BeanFactory
接口。通过使用高级配置,它能够管理任何性质或复杂性的 bean。我们来看看 BeanFactory
的更多细节。
BeanFactory
是创建和管理应用程序所需的大量 bean 的一个容器。这些 bean 的性质可以有很大差异。有些是只具有基本属性的简单 bean;有些则可以与其他 bean 协同工作,所以具有依赖性;还有些则具有递归的依赖性。BeanFactory
通过配置文件来管理这些依赖性。最常用的 BeanFactory
实现是 org.springframework.beans.factory.xml.XmlBeanFactory
。在 清单 1 和 清单 2 中列出了构造 BeanFactory
实例的一些例子。
//Create an XMLBeanFactory by specifying the configuration // file as a FileSystemResource Resource resource = new FileSystemResource("beans.xml"); XMLBeanFactory beanFactory = new XMLBeanFactory(resource); |
清单 2 显示了构造一个 BeanFactory
实例的另一种方法。
//Create an XMLBeanFactory by specifying the configuration // file as a ClassPathResource Resource cpResource = new ClassPathResource("beans.xml"); XMLBeanFactory beanFactory = new XMLBeanFactory(cpResource); |
BeanFactory
配置中最起码要包括 BeanFactory
必须管理的一个或多个 bean 的定义。在 XmlBeanFactory
中,它们被配置为在顶级 bean 元素内的一个或多个 bean 元素(参见 清单 3 )。
<beans> <bean id="xxxxxx" class="yyyyyy"> ... </bean> ... </beans> |
关于 BeanFactory
还有很多东西需要学习,我们将在本系列教程的后面部分进行讨论。
Spring 上下文
Spring 上下文位于核心包之上,它提供了一种以框架风格的方式访问 bean 的途径。Spring 上下文提供了对企业服务(如 Java Naming and Directory Interface™ (JNDI)、Enterprise JavaBeans (EJB)、e-mail、验证、国际化、事件传播 (event propagation)、资源加载,以及上下文的透明创建)的支持。
用 ApplicationContext 增强 BeanFactory
如 前一节 中所述,BeanFactory
为应用程序提供了配置框架和基本功能,而 ApplicationContext
则为它添加了增强功能。由于 ApplicationContext
是 BeanFactory
的子类,所以它具有 BeanFactory
所提供的所有功能,并向其中添加了许多专有的特性。其中一些专有特性为:
- 与 Spring AOP 特性轻松集成。
- 消息资源处理,用于 i18n(国际化)。
- 对资源(如 URL 和文件)的访问。
- 事件处理和传播给实现
ApplicationListener
接口的 bean。 - 透明地创建不同上下文的高级声明机制,如可选的父上下文和特定于应用程序层的上下文(例如,
WebApplicationContext
)。
ApplicationContext
构造是 BeanFactory
的一个完全超集,对 BeanFactory
功能的任何引用也应该同样适用于 ApplicationContext
。 在特定情形下,有时很难明确地决定该使用 BeanFactory
还是 ApplicationContext
。由于 ApplicationContext
提供了 BeanFactory
的所有特性,而且在允许以更具说明性的方式使用一些功能的同时,还为它增加了另外一些特性,所以与 BeanFactory
比较而言,该类更优越一点。在内存使用问题比较重要的场合,比如对于每千字节(内存)都很重要的 applet,使用 BeanFactory
是一个好的选择。在本系列教程的第 2 部分,将学习关于 ApplicationContext
的更多知识,并学习如何定义和使用它。
![]() ![]() |
Spring 面向方面的编程
使用 Spring 的 AOP 软件包可以直接在 Spring 框架中实现 AOP。该软件包还带有一些有利于实现 AOP 的内置方面(bean)。其中比较重要的一个方面是 AOP 对象的事务管理服务。
在讨论 AOP 之前,我们首先来看一下面向对象的编程。OOP 将应用程序分解为大量互操作的对象。在这里,对模块化因素的考虑主要还是集中在对象上。AOP 通过着眼于方面或关注点(Concern),而不是对象,扩展了 OOP 的概念。AOP 应用程序按方面或关注点进行分解,否则,一个方面或关注点可能跨越多个对象。事务和池(pooling) 就是方面(aspect)的例子。
Spring 框架带有一个专门的、隔离的 AOP 框架 —— 这里隔离的意思是 Spring IoC 容器并不依赖于 AOP,它并不要求必须使用 AOP。
Spring AOP 框架中已将一些声明性中间件服务(即 aspect)打包在内。其中有一个预打包的中间件服务是声明性事务管理服务,正如在 EJB 中一样,它提供了对声明性事务的控制。在本教程后面的几节将对此进行更详细的讨论。
![]() ![]() |
Spring DAO
Spring 的 Data Access Objects (DAO) 软件包提供了一个 JDBC 抽象层。它还提供了一种更为容易地管理异常处理和不同数据库厂商抛出的错误码的手段。另外,JDBC 包还提供了一种执行编程性或声明性事务管理的方法,不仅可用于实现特殊接口的类,也可用于所有的传统 Java 对象 (plain old Java object,POJO)。
Spring 框架的设计使得它可以直接跟一些流行的 ORM API(如 JDO、Hibernate 和 iBatis)集成。
Spring DAO 框架的主要目标是让数据访问技术(如 JDBC、Hibernate 或 JDO)相关的工作得以标准化和简化。如果使用 Spring DAO 框架,从一种数据访问技术转移到另一种会变得相当容易。
Spring DAO 框架试图在以下几方面实现标准化:
Spring DAO 框架具有自己的异常层次结构,相比传统的 SQLException
可提供多得多的信息。这些异常把底层数据访问技术抛出的异常包装起来,以一种标准的和易于理解的格式显示出来。
为了更容易地以一致的方式使用各种数据访问技术,如 JDBC、JDO 和 Hibernate,Spring 提供了一组抽象 DAO 类,可以对其进行扩展。这些抽象类具有一些方法,可对数据源和针对当前使用技术的任何其他配置设定项进行设置。
DAO 支持类包括:
JdbcDaoSupport
:JDBC 数据访问对象的超类。需要设置一个DataSource
,向子类提供一个基于它的JdbcTemplate
。HibernateDaoSupport
:Hibernate 数据访问对象的超类。需要设置一个SessionFactory
,向子类提供一个基于它的HibernateTemplate
。JdoDaoSupport
:JDO 数据访问对象的超类。需要设置一个PersistenceManagerFactory
,向子类提供一个基于它的JdoTemplate
。
现在让我们来看一下 Spring 框架如何用 JDBC 来支持数据访问。
在 Java Platform, Standard Edition (Java SE) 和 Java EE 平台上的应用程序中使用传统的 JDBC 有很多优缺点。JDBC 具有的一些特点使它的易用性变得差强人意。这些特性包括:
- 即使对于很简单的数据库功能,应用程序开发人员也必须写很长而乏味的 try-catch 代码块。
- JDBC 用户最常见的错误是没有正确地关闭连接。这就会让许多连接资源无法被其他任务所用。
- JDBC 没有异常层次结构。
- JDBC 的
SQLException
过于空泛,无法就出现的问题提供足够的信息。
Spring 框架中的 JDBC 支持试图通过一个非常有特色的方式解决这些问题。简单地说,它将连接管理功能和其他数据库相关的资源管理功能进行抽象,不再由开发人员管理,这就使得资源的关闭更加正确,代码可读性也得到了提高。
Spring 所提供的 JDBC 抽象框架包括 4 个不同的包 —— 核心包、数据源包、对象包和支持包。
- 核心包 包括
JdbcTemplate
类。它采取了 Web 应用程序中最常用的模板模式。JdbcTemplate
类是 JDBC 核心包中最主要的类。 - 数据源包 包括一个用于简化
DataSource
访问的实用工具类。它还包括了各种用于测试数据库访问代码的DataSource
实现。 - 对象包 包括一些类,它们把将关系数据库管理系统 (RDBMS) 的查询、更新和存储过程表示为线程安全的可重用对象。
- 支持包 包括许多实用工具类和
SQLException
翻译功能。
在本系列教程的后面几个部分,将介绍 Spring 如何使用模板模式来简化 JDBC 代码。
Spring ORM
Spring 框架的设计使得它可以直接集成到流行的对象关系映射 API(如 JDO、Hibernate 和 iBatis)中。
ORM 工具使开发人员能够实现面向对象设计的首要原则:封装。这就让客户端可以与一个对象交互,而不需要知道它的实现细节。Spring 的 IoC 魔法几乎使这种去耦得以完全实现。这里我说 “几乎” 是因为 Spring ORM 试图做到这一点,但并没有完全成功。
不过,Spring 的 ORM 模块仍然成为分层方法的杰出范例。Spring ORM 支持可以逐步地引入到应用程序中。这样做有个好处:可以确保它的实现得到充分的测试。使用 Spring 创建 ORM DAO 的其他好处有:
- 易于测试:如前所述,采用 Spring 的 IoC 方法,对于与对象关系有关的不同实体的实现和配置位置,可以很容易地进行切换。这样就很容易隔离地测试每一段与持久性有关的代码。
- 通用的数据访问异常:Spring 可以把您选择的 ORM 工具抛出的异常包装为一组易于理解的定义好的异常。
- 集成的事务管理:Spring 不仅处理事务语义,对于回滚之类的操作,还完成适当的事务管理工作。该框架也对异常进行处理。
- 避免供应商锁定并允许随意选用的实现策略:使用 Spring 的去耦方法,就有可能在运行时换用不同的 API 和实现。因此,你将不会锁定于使用某个供应商的产品和服务,而是可以根据需要随意选用。
Spring 方便了资源管理、DAO 实现支持以及与几种 ORM 工具的事务策略集成,这些 ORM 工具的例子有:Hibernate、JDO、Oracle Top Link、Apache ObJectRelationalBridge (OJB) 和 iBATIS SQL Maps。下一节将考察以 Hibernate 为底层 API 时的几种集成策略。
使用 Spring Hibernate OR Mapper 进行资源管理
正如 JdbcTemplate
处理应用程序中大多数资源管理功能和执行顺序一样,类似地,Spring 提供了一个 HibernateTemplate
和 HibernateCallback
,以便能与底层数据访问技术和事务技术实现清晰地隔离,从而使应用程序对象之间的耦合变得更为松散。
为了避免应用程序对象与资源查找表紧密地关联起来,Spring 中允许把像 JDBC DataSource
或 Hibernate SessionFactory
这样的资源定义为一个应用程序中上下文中的 bean。需要访问资源的应用程序对象只是通过对 bean 的引用来接受对这类预定义实例的引用。清单 4 显示了如何构造一个 JDBC DataSource
,并在其上构造一个 Hibernate SessionFactory
。
清单 4. 构造一个 JDBC DataSource,并在其上构造一个 Hibernate SessionFactory
<beans> <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> |-------- XML error: The previous line is longer than the max of 90 characters ---------| <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/> <property name="username" value="XXXX"/> <property name="password" value="YYYY"/> </bean> <bean id="mySessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="mappingResources"> <list> <value>product.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> net.sf.hibernate.dialect.MySQLDialect </prop> </props> </property> </bean> ... </beans> |
请看一个演示基本模板编程模型的示例。应用程序对象的实现只需要有一个 Hibernate SessionFactory
,它可以通过 Spring 应用程序上下文的一个简单 bean 引用来提供。清单 5 显示了在 Spring 应用程序上下文中定义一个 DAO,其中引用了前面定义的 SessionFactory
。
<beans> ... <bean id="employeeDao" class="emp.EmployeeDaoImpl"> <property name="sessionFactory" ref="mySessionFactory"/> </bean> </beans> |
清单 6 显示了 DAO 方法实现的一个示例
public class EmployeeDaoImpl implements EmployeeDao { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public Collection loadEmployeesByDepartment(final String department) throws DataAccessException { HibernateTemplate ht = new HibernateTemplate(this.sessionFactory); return (Collection) ht.execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query query = session.createQuery( "from test.Employee employee where employee.department=?"); query.setString(0, department); return query.list(); } }); } } |
对于任何 Hibernate 数据访问,都可以有效地采用回调(函数)实现。HibernateTemplate
确保会话可以正确地打开和关闭,并自动地参与事务。模板实例具有线程安全性和可重用性,所以在使用它的类中可以作为实例变量保存。
Spring 事务抽象的关键在于事务策略的概念。可以通过 org.springframework.transaction.PlatformTransactionManager
接口捕获它。清单 7 显示了使用事务策略的一个简单示例。
清单 7. 演示 PlatformTransactionManager 用法的示例
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; } |
在本系列教程的第 4 部分,将学习关于不同事务策略的更多内容。
![]() ![]() |
Spring Web Flow (SWF)
Spring Web Flow 模块提供了几个面向 Web 的集成特性。它通过声明帮助定义了 Web 应用程序的流(flow)。同时,它还提供了其他特性,例如多部分功能(multipart functionality)、利用 servlet 侦听器的上下文初始化,以及面向 Web 的应用程序上下文。当与 WebWork 或 Struts 一起使用 Spring 时,这个包就是可用来与它们集成的包。
多数人可能都曾在定义 Web 应用程序工作流时碰到过困难。随着复杂步骤越来越多,情形会变得更为麻烦。许多 Web 应用程序中包括一大堆复杂的浏览操作,其中用户可以自由地在页面间导航。当用户决定采取某些行动时,则使用受控的导航,引导用户通过一系列的步骤达成其业务目标。
假设有个贷款申请站点的例子。它允许用户在提供各种不同的贷款选项细节的页面间自由导航。这是一个很好的自由浏览 用例。但是,如果用户选择一个选项决定申请一笔贷款,就开始受控的工作流 —— 贷款申请流程。这个是一个受控导航或受控浏览的例子。
对于这种受控的导航,或称流,传统的建模方法无法将流作为一个最高级的概念来建模和实现。SWF 是 Spring 框架的分层架构中一个定义良好的组件,它以高效和功能强大的方式解决了这个问题。
遵循 Spring 框架的模型,SWF 也被设计为一个自包含的模块。它的流引擎对第三方 API 的依赖性非常小,而且所有的依赖性都得到仔细的管理。SWF 让您清楚简单地显示 Web 应用程序的页面流,并可以任何地方重用它,包括像 Struts、Spring MVC、Tapestry、JavaServer Faces (JSF) ,甚至是 portlet 这样的环境。
![]() ![]() |
SWF 的优点有:
- SWF 是一个自包含的模块,这样就可以设计出可重用的 Web 流,把它用于类似的场合。
- SWF 易于使用,这是因为它具有定义良好的构造。它具有清晰、可配置的生命周期,由容器自动进行管理。
- 通过查看相应的 Web 流定义(在一个 .xml 或 Java 类中),可以清楚地看到 Web 应用程序中的页面流。
- 如前所述,SWF 可以很容易地插入到其他框架中去。
简言之,SWF 是一个基于有限状态机的功能强大的控制器,它完全解决了 MVC 结构中 “C” 的问题。在本系列教程将来的几部分中将学习关于 SWF 的更多知识。
Spring Web MVC
Spring 的 Web MVC 包提供了模型-视图-控制器(MVC)的实现。Spring 的 MVC 实现不仅仅是一个普通的实现 —— 它在域建模代码和 Web 表单之间实现了清晰的分离,还允许使用 Spring 框架所有的其他特性,如验证。
对于基于 Web 的应用程序,MVC 架构是一种广泛采用的架构方案。它把应用程序分割为模型、视图和控制器这三个层,并使它们相应的职能去耦。每个层处理特定的任务,并具有针对其他层的特定职能。
简言之,模型表示业务数据和业务逻辑。视图显示模型的内容,它从模型那里获得数据,并指定如何显示这些数据。它分派用户的请求,并选择合适的视图来显示数据。
Spring 框架为构建 Web 应用程序提供了一个深思熟虑的 MVC 框架。Spring 的 MVC Web 应用程序框架构建在核心功能之上。它是一个与 Struts 类似的基于请求的框架,但试图解决 Struts 所暴露出来的缺陷。对于现代基于请求的框架必须处理的所有职能,Spring MVC 框架定义了不同的策略接口。这些接口的职能都很简单和清楚,所以,Spring MVC 用户可以很容易地编写自己的实现。
Spring 的 Web MVC 框架是围绕 DispatcherServlet
设计的,这个组件具有前端控制器的职能,在 HTTP 请求的执行阶段,它负责把控制委派给各个接口。默认处理器是一个非常简单的控制器接口,它只有一个方法:ModelAndView handleRequest(request, response)
。
下面是 Spring MVC 定义的最重要的接口:
HandlerMappings
:通过使用处理程序映射,可以把传入的请求映射到适当的处理程序。Spring MVC 还提供了一组前置和后置处理器和控制器,它们在特定条件下执行,例如匹配指定的 URL 和控制器。HandlerAdapater
:运行一个适当的对象来处理收到的请求。Controller(s)
:这些 bean 提供处理传入请求的实际功能,也就是 MVC 中的 “C”。View Resolver
:能够把视图名解析为视图。Locale Resolver
:能够解析客户机用于 i18n 支持的区域。Theme Resolver
:如果应用程序提供基于主题的个性化视图,该对象可以解析这些主题。Multipart Resolver
:提供了处理 HTML 表单的多部分文件上载的功能。
Spring MVC 所提供的高度抽象最重要的优点之一是:测试这些接口和整个应用程序的实现变得非常容易。DispatcherServlet
的设计允许开发人员以一种简单而一致的方式按照 Spring IoC 模型来配置应用程序的 Web 层。
在本系列教程的第 6 部分,将学习关于 Spring 的更多内容。
结束语
Spring 是一个功能强大的框架,它试图解决 J2EE 和 Java EE 开发中存在的普遍问题。它还非常灵活,可用于 J2EE 和 Java EE 之外的环境。它的目标是让大家记住面向对象编程中正确的做法:使用接口来设计应用程序。
本系列教程共分为六部分,本文是第一部分,概要介绍了功能强大的 Spring 框架以及它如何试图解决 J2EE 和 Java EE 开发中存要的普遍问题。现在读者应该已了解 Spring 的 7 个模块以及它们的方法。请准备好阅读第 2 部分,在这一部分中将介绍一个个人地址薄应用程序,该应用程序在整个系列教程中都被用作样例。
posted on 2017-07-10 10:47 alex5211314 阅读(138) 评论(0) 编辑 收藏 举报