October 2003
You may have heard the buzz this summer around the Spring Framework. In this article, I’ll try to explain what Spring sets out to achieve, and how I believe it can help you to develop J2EE applications.
在这个夏天,你可以听到许许多多围绕着Spring Framework的声音. 这篇文章,我将说明Spring 的作用和如何帮助你开发J2EE应用.
Yet another framework?
哦,又一个框架?
You may be thinking \\\\\\\"not another framework.\\\\\\\" Why should you bother to read this article, or download the Spring Framework, when there are already many open source (and proprietary) J2EE frameworks?
你也许正在想\\\\\\\"不,又一个框架\\\\\\\". 在众多的开源J2EE框架横行的时代,为什么你还会去读这篇文章或者下载Spring Framework?
I believe that Spring is unique, for several reasons:
我相信Sping 的独特,有下列原因:
* It addresses areas that many other popular frameworks don’t. Spring focuses around providing a way to manage your business objects.
* Spring 的地址区域? 是其他框架所不具备的. Spring 只围绕一点,那就是管理业务对象.
* Spring is both comprehensive and modular. Spring has a layered architecture, meaning that you can choose to use just about any part of it in isolation, yet its architecture is internally consistent. So you get maximum value from your learning curve. You might choose to use Spring only to simplify use of JDBC, for example, or you might choose to use Spring to manage all your business objects.
* Spring 非常的全面和标准. Spring是一个分层构架,意思是你可以选择只用它的一部分,而不影响其他.它的构架体系是内部相容的.所以,你将会在你的学习曲线中获得最大价值.
例如,你可以选择只用Spring 的JDBC 单一应用 或者 用Spring 管理你的业务对象.
* It’s designed from the ground up to help you write code that’s easy to test. Spring is an ideal framework for test driven projects.
* Spring的设计可以帮助你从表层到简单地写出测试代码.Spring是一个理想的测试驱动项目的框架.
Spring is not necessarily one more framework dependency for your project. Spring is potentially a one-stop shop, addressing most infrastructure concerns of typical applications. It also goes places other frameworks don’t.
在你的项目中,Spring 不必依靠更多的框架. Spring 相当于一个一站式商店,从事更多的涉及典型应用的基础框架.它也不必替换任何框架.
Although it has been an open source project only since February 2003, Spring has a long heritage. The open source project started from infrastructure code published with my book, Expert One-on-One J2EE Design and Development, in late 2002. Expert One-on-One J2EE also laid out the basic architectural thinking behind Spring. However, the architectural concepts go back to early 2000, and reflect my experience in developing infrastructure for a series of successful commercial projects.
虽然Spring 是一个起始于2003年2月的一个开源项目,但是它有很长时间的传统. 这个开源项目开始于(2002年出版)
发布的基础编码, 这本书同样也展示了在Spring之后的基础构架. 然而,这个构架的观念在2000年就诞生了, 而且源自我长时间从事一连串的商业项目的成功开发经验.
Since January 2003, Spring has been hosted on SourceForge. There are now ten developers, of whom six are highly active.
自从2003年一月份,Spring 在SourceForge上被建立起来. 现在有10名开发人员,6名高手.
Architectural benefits of Spring
Spring 构架优势
Before we get down to specifics, let’s look at some of the benefits Spring can bring to a project:
在我们详细说明之前,让我们先看一下Spring 可以给一个项目带来的好处:
* Spring can effectively organize your middle tier objects, whether or not you choose to use EJB. Spring takes care of plumbing that would be left up to you if you use only Struts or other frameworks geared to particular J2EE APIs.
*Spring 可以有效的组织你的中间层对象,无论你是否选择了EJB. 如果你只用了Struts 或者其他框架来连接特定的J2EE APIs,Spring 更关心的是委托到你的管道?
* Spring can eliminate the proliferation of Singletons seen on many projects. In my experience, this is a major problem, reducing testability and object orientation.
* Spring 可以消除一个单独项目看起来像多个项目的扩散. 以我的经验, 主要的问题是, 减弱了测试能力和对象方位.
* Spring can eliminate the need to use a variety of custom properties file formats, by handling configuration in a consistent way throughout applications and projects. Ever wondered what magic property keys or system properties a particular class looks for, and had to read the Javadoc or even source code? With Spring you simply look at the class’s JavaBean properties. The use of Inversion of Control (discussed below) helps achieve this simplification.
* Spring 可以消除规定多样的定制属性文件的需要, 用一致的配置操作贯穿这个应用和项目.多样的属性健或者系统属性寻找使你不得不去读Javadoc 或者甚至是源代码?然而, Sping可以使你非常简单地看到这些class 的 JavaBean的属性. 控制的倒置用法(下面介绍)可以帮助你完成简化.
* Spring can facilitate good programming practice by reducing the cost of programming to interfaces, rather than classes, almost to zero.
* Spring 可以使良好的编程习惯更容易培养,利用接口代替classes 减弱编程成本,降至最小.
* Spring is designed so that applications built with it depend on as few of its APIs as possible. Most business objects in Spring applications have no dependency on Spring.
* Spring 的设计使依靠很少的APIs 建立应用成为可能. 在Spring 应用中的许多业务对象根本不要依靠Spring.
* Applications built using Spring are very easy to unit test.
* 利用Sping 建立的应用使单元测试变得非常简单.
* Spring can make the use of EJB an implementation choice, rather than the determinant of application architecture. You can choose to implement business interfaces as POJOs or local EJBs without affecting calling code.
* Spring 是使用EJB成为一个选择,优于成为决定性的应用构架 .你可以选择作为POJOs 或者 local EJBs 扩展业务借口,而不影响调用代码.
* Spring helps you solve many problems without using EJB. Spring can provide an alternative to EJB that’s appropriate for many web applications. For example, Spring can use AOP to deliver declarative transaction management without using an EJB container; even without a JTA implementation, if you only need to work with a single database.
* Spring 可以帮助你解决没有EJB的许多的问题.Spring 提供了为多个web 应用选择性适当的JEB.例如, Spring 可以用 AOP 去传递声明事务管理,在不用EJB容器的情况下.
如果你只需要工作在单个的数据库上面, 甚至不用JTA 的支持.
* Spring provides a consistent framework for data access, whether using JDBC or an O/R mapping product such as Hibernate.
* Spring 提供了坚固的数据存储框架, 无论用JDBC 或者 像Hibernate 一样的 O/R mapping 产品.
Spring really can enable you to implement the simplest possible solution to your problems. And that’s worth a lot.
Spring 确实是你程序扩展简单的方案.并且具有相当大的价值.
What does Spring do?
Spring 做什么呢?
Spring provides a lot of functionality, so I’ll quickly review each major area in turn.
Spring 具有很多的功能, 我们可以快速浏览每个主要的范围.
Mission statement
任务描述
Firstly, let’s be clear on Spring’s scope. Although Spring covers a lot of ground, we do have clear vision as to what it should and shouldn’t address.
首先, 让我们跳出Spring. 虽然Spring 覆盖了很多的层面, 我们必须清楚了解他做什么不做什么.
Spring’s main aim is to make J2EE easier to use and promote good programming practice.
Spring 的主要目标是使J2EE更简单易用, 促进良好的编程习惯.
Spring does not reinvent the wheel. Thus you’ll find no logging packages in Spring, no connection pools, no distributed transaction coordinator. All these things are provided by open source projects (such as Commons Logging, which we use for all our log output, or Commons DBCP), or by your application server. For the same reason, we don’t provide an O/R mapping layer. There are good solutions to this problem such as Hibernate and JDO.
Spring 遵守不重新发明轮子的原则. 因此,你在Spring 找不到 日志管理, 连接池,分布事务调节的程序包. 所有这些功能可以由开源项目(如,Commons Logging ,Common DBCP)提供,
或者是你的应用服务器. 同样的原因, 我们不提供O/R mapping 层, 因为已经有很好地解决方案, 如,Hibernate 和 JDO.
Spring does aim to make existing technologies easier to use. For example, although we are not in the business of low-level transaction coordination, we do provide an abstraction layer over JTA or any other transaction strategy.
Spring 主要目标是让已经存在的技术更简单易用. 例如,虽然我们没有低级的事务调节业务,但是我们提供了在JTA 或者其他事物级别处理之上的提取层.
Spring doesn’t directly compete with other open source projects unless we feel we can provide something new. For example, like many developers, we have never been happy with Struts, and feel that there’s room for improvement in MVC web frameworks. In some areas, such as its lightweight IoC container and AOP framework, Spring does have direct competition, but these are areas in which no solution has become popular. (Spring was a pioneer in these areas.)
Spring
Spring 没有直接和其他的开源项目进行竞争除非我们认为我们提供了新的功能. 例如, 像很多开发者一样,我们一直对strus感觉不好,是因为它把我们框在了它提供了MVC框架之中.
在某些地方,像轻巧的IoC 容器和AOP 框架,Spring 将和他们有着直接的竞争, 但是在这些区域还没有形成普遍成型的方案(Spring 是这个区域的先驱)
Spring also benefits from internal consistency. All the developers are singing from the same hymn sheet, the fundamental ideas remaining faithful to those of Expert One-on-One J2EE Design and Development. And we’ve been able to use some central concepts, such as Inversion of Control, across multiple areas.
Spring 同样获益于区域一致性. 就像所有的开发者唱着同样的赞美诗一样,大家都支持Expert One-on-One J2EE Design and Development . 并且我们都用一些主要的概念,
倒置控制,穿越多个区域.
Spring is portable between application servers. Of course ensuring portability is always a challenge, but we avoid anything platform-specific or non-standard, and support users on WebLogic, Tomcat, Resin, JBoss, WebSphere and other application servers.
Spring 可以轻巧的用于应用服务器. 当然, 保证轻巧的能力一直是一个挑战,但是, 我们避免任何平台详细或者不标准, 并且支持于Weblogic ,Tomcat ,Resin, JBoss, WebSphere 和其他的应用服务器.
Inversion of control container
控制容器的倒置
The core of Spring’s design is the org.springframework.beans package, designed for working with JavaBeans. This package typically isn’t used directly by users, but serves as the underpinning of much of the other functionality.
Spring的设计核心是 org.springframework.beans 包, 设计协调JavaBeans的工作. 这个包代表可以直接被用户使用, 但是可以作为其他很多功能的基础服务.
The next higher layer of abstraction is the \\\\\\\"Bean Factory.\\\\\\\" A Spring bean factory is a generic factory that enables objects to be retrieved by name, and which can manage relationships between objects.
下一个较高的层面是\\\\\\\"Bean Factory\\\\\\\", 一个Spring bean factory 是一个通常可以管理连接多个对象且可以根据name重新获得对象的factory。
Bean factories support two modes of objects:
Bean factories 支持两种对象模式:
* \\\\\\\"Singleton\\\\\\\": in this case, there’s one shared instance of the object with a particular name, which will be retrieved on lookup. This is the default, and most often used, mode. It’s ideal for stateless service objects.
* 单粒模式: 在这里,有一个共享具有特使名称的对象实例,它将可以被找回. 这是一个缺省模式, 而且是应用最为广泛德模式.这种模式是理想的无状态服务对象.
* \\\\\\\"Prototype\\\\\\\": in this case, each retrieval will result in the creation of an independent object. For example, this could be used to allow each user to have their own object.
* \\\\\\\"原型模式\\\\\\\": 在这里,每一个获得导致一个独立的对象创立, 例如,这可以用于允许用户使用他们自己的对象.
As org.springframework.beans.factory.BeanFactory is a simple interface, it can be implemented for a range of underlying storage methods. You could easily implement your own, although few users find they need to. The most commonly used BeanFactory definitions are:
因为 org.springframwork.beans.factory.BeanFactory是一个简单的接口, 它可以被潜在的存储方法行列执行?. 虽然,很少用户需要,但是这可以使你可以简单的拓展你自己 . 一些通常用于BeanFactory 定义是:
* The XmlBeanFactory. This parses a simple, intuitive XML structure defining the classes and properties of named objects. We provide a DTD to make authoring easier.
* XmlBeanFactory. 这是一个简单的解析器.根据XML 结构定义classes和命名对象的属性. 我们提供了一个DTD来使命名更加得简单.
* ListableBeanFactoryImpl: This provides the ability to parse bean definitions in properties files, and create BeanFactories programmatically.
* ListableBeanFactoryImpl: 这提供了在属性文件里面解析bean定义的能力,和编写创建BeanFactories.
Each bean definition can be a POJO (defined by class name and JavaBean initialisation properties), or a FactoryBean. The FactoryBean interface adds a level of indirection. Typically this is used to create proxied objects using AOP or other approaches: for example, proxies that add declarative transaction management. (This is similar to EJB interception in concept, but works out much simpler in practice.)
每个bean的定义可以是一个POJO(定义class和JavaBean初始化属性), 或者一个FactoryBean. FactoryBean 接口添加了一个间接层.代表了这将用于创建用于AOP或者其他途径的
代理对象:例如, 加入声明事务管理的代理.(这是一个类似于EJB侦听的概念,但是在实践中实现十分的简单)
BeanFactories can optionally participate in a hierarchy, \\\\\\\"inheriting\\\\\\\" definitions from their ancestors. This enables the sharing of common configuration across a whole application, while individual resources such as controller servlets also have their own independent set of objects.
BeanFactories 可以在一个层面上进行随意的添加,根据他们的原先的定义. 这能够通过基础配置的共享穿过整个应用,当个别资源如controller servlets也设置自己为单个的对象.
This motivation for the use of JavaBeans is described in Chapter 4 of Expert One-on-One J2EE Design and Development, which is available on the ServerSide as a free PDF (http://www.theserverside.com/res ... dJohnsonInterview).
这是为了声明JavaBeans的用法,在第四章,用法在ServerSide的免费PDF(http://www.theserverside.com/res ... dJohnsonInterview).
Through its BeanFactory concept, Spring is an Inversion of Control container. (I don’t much like the term container, as it conjures up visions of heavyweight containers such as EJB containers. A Spring BeanFactory is a container that can be created in a single line of code, and requires no special deployment steps.)
通过它的BeanFactory 概念,Spring 作为一个控制容器的倒置.(我非常不喜欢期限容器,因为它依靠重量级的容器,如EJB容器).Spring BeanFactory是一个可以在一行代码中创建的容器,而且不需要特殊的部署)
The concept behind Inversion of Control is often expressed in the Hollywood Principle: \\\\\\\"Don’t call me, I’ll call you.\\\\\\\" IoC moves the responsibility for making things happen into the framework, and away from application code. Where configuration is concerned this means that while in traditional container architectures such as EJB, a component might call the container to say \\\\\\\"where’s object X, which I need to do my work\\\\\\\", with IoC the container figures out that the component needs an X object, and provides it to it at runtime. The container does this figuring out based on method signatures (such as JavaBean properties) and, possibly, configuration data such as XML.
控制倒置(IoC)这个感念是经常在好莱坞原则上使用:\\\\\\\"不要打电话给我,我打给你\\\\\\\".IoC的责任是记录进入framework 发生的事件,并且远离应用代码. 涉及到配置的地方,也就是说,
像EJB一样传统的容器构架,一个组建可以调用容器,并且说\\\\\\\"哪儿有可以让我工作的Object X\\\\\\\",对于IoC容器判断出这个组建需要 X 对象,并且在运行的时候提供它执行.容器在方法
签名(就像JavaBean属性)上作出这个基础的判断,并且,尽可能的,配置数据,如XML一样.
IoC has several important benefits. For example:
控制倒置的几个优势,例如:
* Because components don’t need to look up collaborators at runtime, they’re much simpler to write and maintain. In Spring’s version of IoC, components express their dependency on other components via exposing JavaBean setter methods. The EJB equivalent would be a JNDI lookup, which requires the developer to write code.
* 因为组件不需要在运行时间寻找合作,所以他们可以很容易的编写和维护. 在Spring的IoC版本里面, 组件表述了他们通过JavaBean的setter方法来被其他组件支持. 这等于EJB中
通过JNDI lookup,开发人员写的请求代码.
* For the same reasons, application code is much easier to test. JavaBean properties are simple, core Java and easy to test: just write a self-contained JUnit test method that creates the object and sets the relevant properties.
* 为了同样的原因,应用代码变得非常容易测试.JavaBean属性简单,主要的程序测试也变得容易: 刚刚写了一个包含自己的创建对象和设置关联属性的JUnit测试方法.
* A good IoC implementation preserves strong typing. If you need to use a generic factory to look up collaborators, you have to cast the results to the desired type. This isn’t a major problem, but it is inelegant. With IoC you express strongly typed dependencies in your code and the framework is responsible for type casts. This means that type mismatches will be raised as errors when the framework configures the application; you don’t have to worry about class cast exceptions in your code.
* 一个良好的IoC执行保持健壮的输入. 如果你需要用一般的factory寻找合作者,你不得不造型结果成你需要的类型.这不是一个主要的程序,但是这是不好的.对于IoC 你需要在你的
代码 和框架响应里为输入造型传递健壮的信任类型. 这意味着在配置应用的时候输入机制将可能存在错误;但是不必担心造型异常.
* Most business objects don’t depend on IoC container APIs. This makes it easy to use legacy code, and easy to use objects either inside or outside the IoC container. For example, Spring users often configure the Jakarta Commons DBCP DataSource as a Spring bean: there’s no need to write any custom code to do this. We say that an IoC container isn’t invasive: using it won’t invade your code with dependency on its APIs. Any JavaBean can become a component in a Spring bean factory.
* 许多业务对象不依靠IoC. 这使简化为使用继承代码,并且简单用于IoC容器的内部和外部.例如,Spring 用户通常配置Commons DBCP 数据源作为Spring bean:这不需要写任何
代码就可以完成. 我们说IoC容器不会影响:利用APIs用它将不会影响你的代码. 任何JavaBean可以成为Spring bean factory 的一个组件.
This last point deserves emphasis. IoC is unlike traditional container architectures, such as EJB, in this minimization of dependency of application code on container. This means that your business objects can potentially be run in different IoC frameworks - or outside any framework - without code changes.
最后要强调的是,IoC 不同于传统的容器构架,如:EJB, 应用最小限度的依靠容器. 这意味着你的业务对象可以潜在的运行在不同的IoC 框架上-或者没有框架-而不需要改动任何代码.
In my experience and that of Spring users, it’s hard to overemphasize the benefits that IoC brings to application code.
最为Spring用户的经验,这里强调了IoC给你的代码带来的好处.
IoC is not a new concept, although it’s only just made prime time in the J2EE community. There are alternative IoC containers: notably, Apache Avalon, PicoContainer and HiveMind. Avalon has never become particularly popular, although it is powerful and has a long history. Avalon is fairly heavyweight and complex, and seems more invasive than newer IoC solutions. PicoContainer is lightweight and emphasizes the expression of dependencies through constructors rather than JavaBean properties. Unlike Spring, its design allows the definition of only one object of each type (possibly a limitation resulting from its rejection of any metadata outside Java code). For a comparison between Spring and PicoContainer and other IoC frameworks, see the article \\\\\\\"The Spring Framework - A Lightweight Container\\\\\\\" on the Spring website at http://www.springframework.org/docs/lightweight_container.html. This page includes a link to the PicoContainer website.
IoC不是一个新的概念,但是它在J2EE团体里面刚刚成为精华. 有那些IoC 容器可选呢: notably, Apache Avalon, PicoContainer 和 HiveMind.Avalon 不会成为通用,虽然它很强大
而且有很长的历史.Avalon 相当的重量级和复杂,并且看起来比新的IoC解决方案更内聚. PicoContainer是一个轻量级而且强调通过构造器传递优于JavaBean 属性. 不像Spring,
它涉及允许定义一个对象多种输入(可能局限于外部的java code收集结果), 作为比较http://www.springframework.org/docs/lightweight_container.html. 这个业面包含了
PicoContainer站点.
Spring BeanFactories are very lightweight. Users have successfully used them inside applets, as well as standalone Swing applications. (They also work fine within an EJB container.) There are no special deployment steps and no detectable startup time. This ability to instantiate a container almost instantly in any tier of an application can be very valuable.
Spring BeanFactories 是非常轻型的.用户可以成功地在applets里面使用,作为独立的Swing应用.(它们也在EJB容器工作的很好) 没有制定的部署步骤和省去了重起的时间.这个能力
表明一个容器在应用的任何层面差不多立即可以发挥重大的价值.
The Spring BeanFactory concept is used throughout Spring, and is a key reason that Spring is so internally consistent. Spring is also unique among IoC containers in that it uses IoC as a basic concept throughout a full-featured framework.
Spring BeanFactory 概念应用于Spring, 而且是Spring中心协调的关键原因. Spring 也是在IoC容器中唯一利用基础概念完成全部特点的框架.
Most importantly for application developers, one or more BeanFactories provide a well-defined layer of business objects. This is analogous to, but much simpler than, a layer of local session beans. Unlike EJBs, the objects in this layer can be interrelated, and their relationships managed by the owning factory. Having a well-defined layer of business objects is very important to a successful architecture.
许多应用开发者关心的,一个或者多个BeanFactories可以提供了一个定义好的业务对象层. 这类似,且非常简单,一个本地session beans的一个层. 不同于EJBs, 在这个层里面的对象
是相关的,并且他们的关系被自己的factory 管理.提供一个定义完好的业务对象层是成功构架非常重要的一点.
A Spring ApplicationContext is a subinterface of BeanFactory, which provides support for:
Spring ApplicationContext 是BeanFactory的子接口,为下列提供支持:
* Message lookup, supporting internationalization
* 消息寻找,支持国际化
* An eventing mechanism, allowing application objects to publish and optionally register to be notified of events
* 事件机制,允许应用对象发布和操作注册成为事件
* Portable file and resource access
* 轻巧的文件和资源存储
In the following example, we use a BasicDataSource from the Jakarta Commons DBCP project. This class (like many other existing classes) can easily be used in a Spring bean factory, as it offers JavaBean-style configuration. The close method that needs to be called on shutdown can be registered via Spring\\\\\\\'s \\\\\\\"destroy-method\\\\\\\" attribute, to avoid the need for BasicDataSource to implement any Spring interface.
在下面的例子里,我们用一个DBCP项目中的BasicDataSource 。这个class(和其他存在的class一样)可以简单的在Spring bean factory使用,并且提供了JavaBean配置。这种需要在shutdown的时候被调用的精密方法可以通过Spring的\\\\\\\"destroy-method\\\\\\\"属性被注册,而且提供了需要为BasicDataSource执行的许多Spring 接口。
代码:
destroy-method=\\\\\\\"close\\\\\\\">
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/mydb
root
All the properties of BasicDataSource we e interested in are Strings, so we specify their values with the element. Spring uses the standard JavaBean PropertyEditor mechanism to convert String representations to other types if necessary.
我们感兴趣的是Strings ,BasicDataSource的所有属性,所以我们用标签指定了他们的值。如果必要的话,Spring 用标准的JavaBean属性编辑机制来转换String 表示其他的类型.
Now we define the DAO, which has a bean reference to the DataSource. Relationships between beans are specified using the element:
现在,我们定义这个用一个bean 表示为DataSource的 DAO. 用标签来表示beans之间的关系:
代码:
class=\\\\\\\"example.ExampleDataAccessObject\\\\\\\">
The business object has a reference to the DAO, and an int property (exampleParam):
这个业务对象涉及到DAO,并且有一个int属性(exampleParam):
代码:
class=\\\\\\\"example.ExampleBusinessObject\\\\\\\">
10
Relationships between objects are normally set explicitly in configuration, as in this example. We consider this to be a Good Thing. However, Spring also provides what we call \\\\\\\"autowire\\\\\\\" support, a la PicoContainer, where it figures out the dependencies between beans. The limitation with this - as with PicoContainer - is that if there are multiple beans of a particular type it impossible to work out which instance a dependency of that type should be resolved to. On the positive side, unsatisfied dependencies can be caught when the factory is initialized. (Spring also offers an optional dependency check for explicit configuration, which can achieve this goal.)
这两个对象的关系可以在配置中非常清楚,有如例子一样。我们认为这样做很好.无论如何,Spring也提供了我们叫做\\\\\\\"autowire\\\\\\\"的支持, 一个la PicoContainer,它可以判断这两个beans只见的依赖关系.PicoContainer的局限性是如果有多个的Beans有特殊的类型,这种类型不可能完全解决实例的类型可以判断之间的依赖关系.值得一提的是,不能班组的依赖关系可以在factory初始化的时候被捕获.(Spring 也提供一种可以完成这个目标的的外部配置)
We could use the autowire feature as follows in the above example, if we didn\\\\\\\'t want to code these relationships explicitly:
在以上的例子里,我们可以用autowire 用来理解,如果我们不想编码这些外部关系:
代码:
class=\\\\\\\"example.ExampleBusinessObject\\\\\\\"
autowire=\\\\\\\"byType\\\\\\\">
10
With this usage, Spring will work out that the dataSource property of exampleBusinessObject should be set to the implementation of DataSource it finds in the present BeanFactory. It‘s an error if there is none, or more than one, bean of the required type in the present BeanFactory. We still need to set the exampleParam property, as it\\\\\\\'s not a reference.
对于这个用法,Spring 将可以理解为exampleBusinessObject的dataSource 属性在父BeanFactory里找到DataSource,将其设置执行.如果在beanFactory没找到或者多于一个请求类型的bean产生一个error。我们还需要设置exampleParam属性,因为它没有参数.
Autowire support and dependency checking is presently in CVS and will be available in Spring 1.0 M2 (due October 20, 2003). All other features discussed in this article are in the current 1.0 M1 release.
Autowire支持和依赖关系检查是刚刚加入CVS和将发布在Spring 1.0 M2(10/20,2003).所有其他的特点讨论当前1.0 M1发布版本.
Externalizing relationships from Java code has an enormous benefit over hard coding it, as it possible to change the XML file without changing a line of Java code. For example, we could simply change the myDataSource bean definition to refer to a different bean class to use an alternative connection pool, or a test data source. We could use Spring JNDI location FactoryBean to get a datasource from an application server in a single alternative XML stanza.
具体的说,这样描述关系比硬编码有很大的好处,因为只改变XML文件而不用改变java 代码.例如,我们可以简单的改变myDataSource bean 定义提供不同的bean class 用选择性的连接池,或者一个测试数据源. 我们用Spring JNDI本地FactoryBean从application server两个单独的选择性节点得到一个数据源.
Now let\\\\\\\'s look at the Java code for the example business object. Note that there are no Spring dependencies in the code listing below. Unlike an EJB container, a Spring BeanFactory is not invasive: you don\\\\\\\'s normally need to code awareness of it into application objects.
现在让我们来看一段业务对象的java 代码的例子.注意下面没有Spring的依赖。不像EJB容器,Spring BeanFactory不用嵌入:在应用对象里面你通常不需要编码.
代码:
public class ExampleBusinessObject implements MyBusinessObject {
private ExampleDataAccessObject dao;
private int exampleParam;
public void setDataAccessObject(ExampleDataAccessObject dao) {
this.dao = dao;
}
public void setExampleParam(int exampleParam) {
this.exampleParam = exampleParam;
}
public void myBusinessMethod() {
// do stuff using dao
}
}
Note the property setters, which correspond to the XML references in the bean definition document. These are invoked by Spring before the object is used.
注意属性设置,在bean定义文档里面对应XML定义.这将在对象使用之前被Spring调用.
Such application beans do not need to depend on Spring: They don\\\\\\\'t need to implement any Spring interfaces or extend Spring classes: they just need to observe JavaBeans naming convention. Reusing one outside of a Spring application context is easy, for example in a test environment. Just instantiate it with its default constructor, and set its properties manually, via setDataSource() and setExampleParam() calls. So long as you have a no-args constructor, you are free to define other constructors taking multiple properties if you want to support programmatic construction in a single line of code.
这种应用bean不需要依靠Spring.他们不需要执行任何Spring接口或者继承Spring classes:他们只需要遵守JavaBeans名称转换.在Spring 应用内容之外重用非常简单,例如一个测试环境.不过示例定义了一个缺省的构造器,并且通过setDataSource()和setExampleParam()调用配置了属性。只要你有一个没有参数的构造器,如果你想在单行代码支持程序的构件器,你可以自由定义其他的构建器设置其他的属性.
Note that the JavaBean properties are not declared on the business interface callers will work with. They are an implementation detail. We could \\\\\\\"plug in\\\\\\\" different implementing classes that have different bean properties without affecting connected objects or calling code.
注意,在业务借口没有声明的JavaBean属性一起工作. 他们是一个详细地执行.我们可以插入不同的bean属性执行classes,而不硬性连接对象或者调用代码.
Of course Spring XML bean factories have many more capabilities than described here, but this should give you a feel for the basic approach. As well as simple properties, and properties for which you have a JavaBeans PropertyEditor, Spring can automatically handle lists, maps and java.util.Properties.
当然,Spring XML bean factories 有更多的能力没有在这里描述,但是,这将给你在基础步骤上一个基本的认识.还有简单属性,和用于javabean属性编辑器的属性,Spring可以自动操作lists,maps和java.util.Properties.
Bean factories and application contexts are usually associated with a scope defined by the J2EE server, such as:
Bean factories 和application contexts 通常通过被J2EE server定义一个范围,例如:
*The Servlet context. In the Spring MVC framework, an application context is defined for each web application containing common objects. Spring provides the ability to instantiate such a context through a listener or servlet without dependence on the Spring MVC framework, so it can also be used in Struts, WebWork or other web frameworks.
Servlet context. 在spring MVC 框架里, 一个应用context 可以为每一个饱含基础对象的web 应用 定义.Spring提供了如示例一样一个context通过监听器或者servlet不需要依靠Spring MVC 框架的能力,所以它也可以用于Struts,WebWork 或者其他的web框架.
*A Servlet: Each controller servlet in the Spring MVC framework has its own application context, derived from the root (application-wide) application context. It also easy to accomplish this with Struts or another MVC framework.
A Servlet:在Spring MVC 框架里每一个servlet控制器由它特有的应用context,根源于应用context.这同样可以简单应用于Struts或者其他的MVC框架.
*EJB: Spring provides convenience superclasses for EJB that simplify EJB authoring and provide a BeanFactory loaded from an XML document in the EJB Jar file.
EJB:Spring 提供为EJB创建者方便的超类和在EJB jar 文件里从XML 文档提供的BeanFactory载入.
These hooks provided by the J2EE specification generally avoid the need to use a Singleton to bootstrap a bean factory.
这样符合J2EE规范通常避免使用Singleton 到 bean factory.
However, it\\\\\\\'s trivial to instantiate a BeanFactory programmatically if we wish. For example, we could create the bean factory and get a reference to the business object defined above in the following three lines of code:
不管怎样,我们将详细示例一个BeanFactory,下面3行代码,我们创建一个bean factory 并且作为定义业务对象的参考。
代码:
InputStream is = getClass().getResourceAsStream(\\\\\\\"myFile.xml\\\\\\\");
XmlBeanFactory bf = new XmlBeanFactory(is);
MyBusinessObject mbo = (MyBusinessObject) bf.getBean(\\\\\\\"exampleBusinessObject\\\\\\\");
This code will work outside an application server: it doesn\\\\\\\'s even depend on J2EE, as the Spring IoC container is pure Java.
这段代码工作在一个应用server之外:甚至不依靠J2EE,因为Spring IoC容器是纯java的.
JDBC abstraction and data access exception hierarchy
JDBC 抽象和数据存储异常层次
Data access is another area in which Spring shines.
数据存储是Spring 的另一个闪光点.
JDBC offers fairly good abstraction from the underlying database, but is a painful API to use. Some of the problems include:
JDBC 提供还算不错的数据库抽象,但是需要用痛苦的API. 这些问题包含:
The need for verbose error handling to ensure that ResultSets, Statements and (most importantly) Connections are closed after use. This means that correct use of JDBC can quickly result in a lot of code. It’s also a common source of errors. Connection leaks can quickly bring applications down under load.
麻烦的是需要在用完ResultSets,Statements 和(最重要的)Connections必须关闭. 这意味着正确的使用JDBC得到结果需要一大堆的代码. 同样是一个错误的根源。Connection泄漏可以马上让应用down掉.
The relatively uninformative SQLException. JDBC does not offer an exception hierarchy, but throws SQLException in response to all errors. Finding out what actually went wrong - for example, was the problem a deadlock or invalid SQL? - involves examining the SQLState and error code. The meaning of these values varies between databases.
没有相关的SQLException. JDBC 不能提供异常层次,而是在响应里抛出SQLException.找不出实际是错误 – 例如,程序死锁或者错误的SQL? - 包括可检查的SQLState 和错误码.这可能在数据库之间出错.
Spring addresses these problems in two ways:
Spring 解决这些问题有两个方法:
By providing APIs that move tedious and error-prone exception handling out of application code into the framework. The framework takes care of all exception handling; application code can concentrate on issuing the appropriate SQL and extracting results.
通过提供APIs 使 不易移植和错误倾向的异常排除在应用代码之外而到框架层面.这个框架可以照顾到所有的异常操作;应用代码可以集中发布的适当的SQL和提取结果.
By providing a meaningful exception hierarchy for your application code to work with in place of SQLException. When Spring first obtains a connection from a DataSource it examines the metadata to ascertain the database. It uses this knowledge to map SQLExceptions to the correct exception in its own hierarchy descended from org.springframework.dao.DataAccessException. Thus your code can work with meaningful exceptions, and need not worry about proprietary SQLState or error codes. Spring’s data access exceptions are not JDBC-specific, so your DAOs are not necessarily tied to JDBC because of the exceptions they may throw.
为你的应用代码通过提供一组对SQLException起作用的异常级别.当Spring 第一次在DataSource获得一个连接,它将核对数据库的元数据. 在自己的层面利用绘制SQLException 到当前的异常org.springframework.dao.DataAccessException.因而,你的代码可以和有意义的exceptions一起运行,并且, 不用担心任何SQLState 或错误码.Spring 的数据存储异常不是JDBC规范,所以你的DAOs不必依赖JDBC,因为他们可以抛出异常.
Spring provides two levels of JDBC API. The first, in the org.springframework.jdbc.core package, uses callbacks to move control - and hence error handling and connection acquisition and release - from application code inside the framework. This is a different type of Inversion of Control, but equally valuable to that used for configuration management.
Spring 提供了2个JDBC API的级别. 第一个,在org.springframework.jdbc.core package里面,用callbacks来移动控制- 因此错误操作和连接获得释放 – 从framework里的应用代码.这是一种倒置控制的一种不同类型, 然而,这和用配置管理一样有价值.
Spring uses a similar callback approach to address several other APIs that involve special steps to acquire and cleanup resources, such as JDO (acquiring and relinquishing a PersistenceManager), transaction management (using JTA) and JNDI. Spring classes that perform such callbacks are called templates.
Spring 用一个类似的回调方法通过几个其他的APIs ,这包括特特殊的步骤获得和清除资源,例如,JDO(获得和释放一个PersistenceManager),事务管理(用JTA)和JNDI.Spring classes提供了几个callbacks 调用模式.
For example, the Spring JdbcTemplate object can be used to perform a SQL query and save the results in a list as follows:
例如,Spring JdbcTemplate对象可以用于提供一个SQL query 和保存list结果:
代码:
JdbcTemplate template = new JdbcTemplate(dataSource);
final List names = new LinkedList();
template.query(\\\\\\\"SELECT USER.NAME FROM USER\\\\\\\",
new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
names.add(rs.getString(1));
}
});
Note that application code within the callback is free to throw SQLException: Spring will catch any exceptions and rethrow them in its own hierarchy. The application developer can choose which exceptions, if any, to catch and handle.
注意这段没有callback的代码可以自由的抛出SQLException:Spring 将catch 任何一场和抛出他们自己的异常.应用开发者可以选择是否将异常捕获或者处理掉.
The JdbcTemplate provides many methods to support different scenarios including prepared statements and batch updates. The Spring JDBC abstraction has a very low performance overhead beyond standard JDBC, even in applications cases involving huge result sets.
JdbcTemplate 提供了许多的方法支持不同的情况, 包括准备statement 和批量更新. Spring JDBC 抽象的性能远远超过甚至在应用里包含大量的result sets 标准的JDBC.
The higher level JDBC abstraction is in the org.springframework.jdbc.object package. This is built on the core JDBC callback functionality, but provides an API in which an RDBMS operation - whether query, update or stored procedure - is modelled as a Java object. This API was partly inspired by the JDO query API, which I found intuitive and highly usable.
这个较高级的JDBC抽象在org.springframework.jdbc.object 包. 这建立在核心功能JDBC callback上,然而,提供了一组RDBMS操作的APIs – 无论query, update 或者 存储程序 – 模拟一个java object. 这组API的部分灵感来自JDO query API, 它非常的直观和有用.
A query object to return User objects might look like this:
一个query 对象返回User对象,大概这样:
代码:
class UserQuery extends MappingSqlQuery {
public UserQuery(DataSource datasource) {
super(datasource, \\\\\\\"SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?\\\\\\\");
declareParameter(new SqlParameter(Types.NUMERIC));
compile();
}
// Map a result set row to a Java object
protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
User user = new User();
user.setId(rs.getLong(\\\\\\\"USER_ID\\\\\\\"));
user.setForename(rs.getString(\\\\\\\"FORENAME\\\\\\\"));
return user;
}
public User findUser(long id) {
// Use superclass convenience method to provide strong typing
return (User) findObject(id);
}
}
This class can be used as follows(这个class按照下列使用):
代码:
User user = userQuery.findUser(25);
Such objects are often inner classes inside DAOs. They are threadsafe, unless the subclass does something unusual.
这种对象经常在DAOs用到内部类. 他们线程安全的,除非子类做了不寻常的事情.
Another important class in the org.springframework.jdbc.object package is the StoredProcedure class. Spring enables a stored procedure to be proxied by a Java class with a single business method. If you like, you can define an interface that the stored procedure implements, meaning that you can free your application code from depending on the use of a stored procedure at all.
在org.springframework.jdbc.object里面另一些重要的class是StoredProcedure class. Spring 使一个存储程序能够被一个具有单个业务方法的Java class代理. 如果你喜欢, 你可以定义一个存储程序执行的接口, 意思是你可以依靠一个存储程序的是用来释放你的应用代码.
The Spring data access exception hierarchy is based on unchecked (runtime) exceptions. Having worked with Spring on several projects I’m more and more convinced that this was the right decision.
Spring 数据存储异常在运行时不检查的.对于Spring几个对象的所有工作, 我认为重中之重是确认这是对的结果.
Data access exceptions not usually recoverable. For example, if we can’t connect to the database, a particular business object is unlikely to be able to work around the problem. One potential exception is optimistic locking violations, but not all applications use optimistic locking. It’s usually bad to be forced to write code to catch fatal exceptions that can’t be sensibly handled. Letting them propagate to top-level handlers like the servlet or EJB container is usually more appropriate. All Spring data access exceptions are subclasses of DataAccessException, so if we do choose to catch all Spring data access exceptions, we can easily do so.
数据存储异常通常不能重新覆盖. 例如, 如果我们没有连接数据库, 一个特殊的业务对象不大可能正常的工作. 潜在的异常是一个乐观锁定违例, 但是不是所有的应用都用乐观锁定. 这通常分层强制编写代码catch 致命的且不能明显被操作的异常. 像servlet 或者 EJB容器一样让他们传到最上层比较的合适. 所有Spring 数据存储异常都是DataAccessException的子类,所以如果我们选择catch所有的数据存储异常,我们可以简单的完成.
Note that if we do want to recover from an unchecked data access exception, we can still do so. We can write code to handle only the recoverable condition. For example, if we consider that only an optimistic locking violation is recoverable, we can write code in a Spring DAO as follows:
注意如果我们想从一个未检查的数据访问异常恢复,我们同样可以. 我们只有编写代码来操作可恢复的条件.例如, 如果我们考虑只有一个乐观的锁定是不能恢复的,我们可以在Spring DAO里编写下列代码:
代码:
try {
// do work
}
catch (OptimisticLockingFailureException ex) {
// I\\\\\\\'m interested in this
}
If Spring data access exceptions were checked, we’d need to write the following code. Note that we could choose to write this anyway:
如果Spring 数据访问异常被检查, 我们需要写下列代码. 注意我们可以选择这么写:
代码:
try {
// do work
}
catch (OptimisticLockingFailureException ex) {
// I\\\\\\\'m interested in this
}
catch (DataAccessException ex) {
// Fatal; just rethrow it
}
One potential objection to the first example - that the compiler can’t enforce handling the potentially recoverable exception - applies also to the second. Because we’re forced to catch the base exception (DataAccessException), the compiler won’t enforce a check for a subclass (OptimisticLockingFailureException). So the compiler would force us to write code to handle an unrecoverable problem, but provide no help in forcing us to deal with the recoverable problem.
在第一个例子里有一个潜在的缺陷 – 编译器不能强制操作潜在的不能恢复的异常 – 第二个也是一样. 因为我们强制catch 基本异常(DataAccessException), 编译器不能强制为子类(OptimisticLockingFailureException)做检查.所以编译器强制我们写代码来操作不能恢复的程序,但并不提供任何帮助.
Spring’s use of unchecked data access exceptions is consistent with that of many - probably most - successful persistence frameworks. (Indeed, it was partly inspired by JDO.) JDBC is one of the few data access APIs to use checked exceptions. TopLink and JDO, for example, use unchecked exceptions exclusively. Gavin King now believes that Hibernate should also have opted for unchecked exceptions.
Spring 非检查访问异常的用法对于大部分情况都是一致的 – 成功的持久框架.(确实,这部分来自JDO的灵感.) JDBC 是一个在少数用于check exception数据访问的APIs.TopLink 和JDO,例如,不特定检查异常. Gavin King 现在艰辛Hibernate 也不检查unchecked exception.
Spring JDBC can help you in several ways:
Spring JDBC 可以帮助一下列几点:
You’ll never need to write a finally block again to use JDBC
根本不必像用JDBC一样写finally.
You’ll need to write much less code overall
不必写大量大代码
You’ll never need to dig through your RDBMS documentation to work out what obscure error code it returns for a bad column name. Your application won’t be dependent on RDBMS-specific error handling code.
不必钻研关系数据库文档就可以解决为一个错误列名而返回的隐含错误码.你的应用还不用依靠关系数据库制定的错误操作码.
Whatever persistence technology use, you’ll find it easy to implement the DAO pattern without business logic depending on any particular data access API.
不管怎样持久技术的使用,可以使你方便的实现DAO模式,而业务逻辑不依靠任何特殊的数据访问API.
In practice we find that all this amounts to substantial productivity gains and fewer bugs. I used to loathe writing JDBC code; now I find that I can focus on the SQL I want to execute, rather than the incidentals of JDBC resource management.
在实践中我们可以找到完全的实质生产力数量和更少的bugs. 我们憎恨JDBC代码;现在我可以把精力放在我想执行的SQL上,总比附加JDBC的资源管理要好得多.
Spring’s JDBC abstraction can be used standalone if desired - you are not forced to use the other parts of Spring.
Spring的JDBC 抽象可以单独使用 – 一个可以只用Spring的其他部分.
posted on 2005-02-04 11:17
jacky 阅读(508)
评论(0) 编辑 收藏 所属分类:
Open source