2 Introduction to the Spring Framework
The Spring Framework is a Java platform that provides comprehensive(全面的) infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.
Spring Framework 是一个提供了全面基础设施来支持Java应用开发的Java平台。Spring专注于基础设施功能,因此程序员可以专注于自己的应用。
Spring enables you to build applications from "plain old Java objects" (POJOs) and to apply enterprise services non-invasively(无侵入的)to POJOs. This capability applies to the Java SE programming model and to full and partial Java EE.
Spring 可以使你从“简单的Java对象”(POJO)构建应用程序,并且将企业服务非侵入性的应用到 POJO。此功能适用于 Java SE 编程模型和完全或者部分的 Java EE 。
Examples of how you, as an application developer, can benefit from the Spring platform:
- Make a Java method execute in a database transaction without having to deal with transaction APIs.
- Make a local Java method an HTTP endpoint without having to deal with the Servlet API.
- Make a local Java method a message handler without having to deal with the JMS API.
- Make a local Java method a management operation without having to deal with the JMX API.
2.1 Dependency Injection and Inversion of Control
A Java application — a loose term that runs the gamut(整个范围) from constrained, embedded applications to n-tier, server-side enterprise applications — typically consists of objects that collaborate to form the application proper. Thus the objects in an application have dependencies on each other.
Although the Java platform provides a wealth of application development functionality, it lacks the means to organize the basic building blocks(模块) into a coherent(连贯的) whole, leaving that task to architects(架构师)and developers. Although you can use design patterns such as Factory, Abstract Factory, Builder, Decorator(装饰者模式), and Service Locator to compose the various classes and object instances that make up an application, these patterns are simply that: best practices given a name, with a description of what the pattern does, where to apply it, the problems it addresses, and so forth. Patterns are formalized(形式化的) best practices that you must implement yourself in your application.
The Spring Framework Inversion of Control (IoC) component addresses this concern by providing a formalized means of composing disparate components into a fully working application ready for use. The Spring Framework codifies formalized design patterns as first-class objects that you can integrate into your own application(s). Numerous organizations and institutions use the Spring Framework in this manner to engineer robust(健壮的), maintainable(可维护的) applications.
Background
"The question is, what aspect of control are [they] inverting?" Martin Fowler posed this question about Inversion of Control (IoC) on his site in 2004. Fowler suggested renaming the principle to make it more self-explanatory(自描述) and came up with Dependency Injection.
2.2 Framework Modules
The Spring Framework consists of features organized into about 20 modules. These modules are grouped into Core Container, Data Access/Integration(集成), Web, AOP (Aspect Oriented Programming), Instrumentation(设备支持), Messaging, and Test, as shown in the following diagram.
Figure 2.1. Overview of the Spring Framework
The following sections list the available modules for each feature along with their artifact names and the topics they cover. Artifact names correlate to artifact IDs used in Dependency Management tools.
2.2.1 Core Container
The Core Container consists of the spring-core
, spring-beans
, spring-context
, spring-context-support
, and spring-expression
(Spring Expression Language) modules.
The spring-core
and spring-beans
modules provide the fundamental parts of the framework, including the IoC and Dependency Injection features. The BeanFactory
is a sophisticated(富有经验的) implementation of the factory pattern. It removes the need for programmatic singletons and allows you to decouple(解耦) the configuration and specification of dependencies from your actual program logic.
The Context (spring-context
) module builds on the solid base provided by the Core and Beans modules(模块构架于核心模块之上): it is a means to access objects in a framework-style manner that is similar to a JNDI registry. The Context module inherits its features from the Beans module and adds support for internationalization (using, for example, resource bundles), event propagation, resource loading, and the transparent creation of contexts by, for example, a Servlet container. The Context module also supports Java EE features such as EJB, JMX, and basic remoting. The ApplicationContext
interface is the focal point(焦点) of the Context module. spring-context-support
provides support for integrating common third-party libraries into a Spring application context for caching (EhCache, Guava, JCache), mailing (JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports, Velocity).
The spring-expression
module provides a powerful Expression Language for querying and manipulating an object graph at runtime. It is an extension of the unified expression language (unified EL) as specified in the JSP 2.1 specification(规格,标准). The language supports setting and getting property values, property assignment, method invocation, accessing the content of arrays, collections and indexers, logical and arithmetic operators, named variables, and retrieval of objects by name from Spring’s IoC container. It also supports list projection and selection as well as common list aggregations.
2.2.2 AOP and Instrumentation
The spring-aop
module provides an AOP Alliance-compliant(服从) aspect-oriented programming implementation allowing you to define, for example, method interceptors and pointcuts to cleanly decouple code that implements functionality that should be separated. Using source-level metadata functionality, you can also incorporate behavioral information into your code, in a manner similar to that of .NET attributes.
The separate spring-aspects
module provides integration(集成) with AspectJ.
The spring-instrument
module provides class instrumentation support and classloader implementations to be used in certain application servers. The spring-instrument-tomcat
module contains Spring’s instrumentation agent for Tomcat.
2.2.3 Messaging
Spring Framework 4 includes a spring-messaging
module with key abstractions from the Spring Integration project such as Message
, MessageChannel
, MessageHandler
, and others to serve as a foundation for messaging-based applications. The module also includes a set of annotations for mapping messages to methods, similar to the Spring MVC annotation based programming model.
2.2.4 Data Access/Integration
The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS, and Transaction modules.
The spring-jdbc
module provides a JDBC-abstraction layer that removes the need to do tedious JDBC coding and parsing of database-vendor specific error codes.
The spring-tx
module supports programmatic and declarative transaction management for classes that implement special interfaces and for all your POJOs (Plain Old Java Objects).
The spring-orm
module provides integration layers for popular object-relational mapping APIs, including JPA, JDO, and Hibernate. Using the spring-orm
module you can use all of these O/R-mapping frameworks in combination with all of the other features Spring offers, such as the simple declarative transaction management feature mentioned previously.
The spring-oxm
module provides an abstraction layer that supports Object/XML mapping implementations such as JAXB, Castor, XMLBeans, JiBX and XStream.
The spring-jms
module (Java Messaging Service) contains features for producing and consuming messages. Since Spring Framework 4.1, it provides integration with the spring-messaging
module.
2.2.5 Web
The Web layer consists of the spring-web
, spring-webmvc
, spring-websocket
, and spring-webmvc-portlet
modules.
The spring-web
module provides basic web-oriented integration features such as multipart file upload functionality and the initialization of the IoC container using Servlet listeners and a web-oriented application context. It also contains an HTTP client and the web-related parts of Spring’s remoting support.
The spring-webmvc
module (also known as the Web-Servlet module) contains Spring’s model-view-controller (MVC) and REST Web Services implementation for web applications. Spring’s MVC framework provides a clean separation between domain model code and web forms and integrates with all of the other features of the Spring Framework.
The spring-webmvc-portlet
module (also known as the Web-Portlet module) provides the MVC implementation to be used in a Portlet environment and mirrors the functionality of the Servlet-based spring-webmvc
module.
2.2.6 Test
The spring-test
module supports the unit testing and integration testing of Spring components with JUnit or TestNG. It provides consistent loading of SpringApplicationContext
s and caching of those contexts. It also provides mock objects that you can use to test your code in isolation.
7.15 Additional capabilities of the ApplicationContext
As was discussed in the chapter introduction, the org.springframework.beans.factory
package provides basic functionality for managing and manipulating beans, including in a programmatic way. The org.springframework.context
package adds the ApplicationContext
interface, which extends the BeanFactory
interface, in addition to extending other interfaces to provide additional functionality in a more application framework-oriented style. Many people use the ApplicationContext
in a completely declarative fashion, not even creating it programmatically, but instead relying on support classes such as ContextLoader
to automatically instantiate an ApplicationContext
as part of the normal startup process of a Java EE web application.
To enhance BeanFactory
functionality in a more framework-oriented style the context package also provides the following functionality:
- Access to messages in i18n-style, through the
MessageSource
interface. - Access to resources, such as URLs and files, through the
ResourceLoader
interface. - Event publication to namely beans implementing the
ApplicationListener
interface, through the use of theApplicationEventPublisher
interface. - Loading of multiple (hierarchical) contexts, allowing each to be focused on one particular layer, such as the web layer of an application, through the
HierarchicalBeanFactory
interface.
7.15.1 Internationalization using MessageSource
The ApplicationContext
interface extends an interface called MessageSource
, and therefore provides internationalization (i18n) functionality. Spring also provides the interface HierarchicalMessageSource
, which can resolve messages hierarchically. Together these interfaces provide the foundation upon which Spring effects message resolution. The methods defined on these interfaces include:
-
String getMessage(String code, Object[] args, String default, Locale loc)
: The basic method used to retrieve a message from theMessageSource
. When no message is found for the specified locale, the default message is used. Any arguments passed in become replacement values, using theMessageFormat
functionality provided by the standard library. -
String getMessage(String code, Object[] args, Locale loc)
: Essentially the same as the previous method, but with one difference: no default message can be specified; if the message cannot be found, aNoSuchMessageException
is thrown. -
String getMessage(MessageSourceResolvable resolvable, Locale locale)
: All properties used in the preceding methods are also wrapped in a class namedMessageSourceResolvable
, which you can use with this method.
When an ApplicationContext
is loaded, it automatically searches for a MessageSource
bean defined in the context. The bean must have the name messageSource
. If such a bean is found, all calls to the preceding methods are delegated to the message source. If no message source is found, the ApplicationContext
attempts to find a parent containing a bean with the same name. If it does, it uses that bean as the MessageSource
. If theApplicationContext
cannot find any source for messages, an empty DelegatingMessageSource
is instantiated in order to be able to accept calls to the methods defined above.
Spring provides two MessageSource
implementations, ResourceBundleMessageSource
and StaticMessageSource
. Both implement HierarchicalMessageSource
in order to do nested messaging. The StaticMessageSource
is rarely used but provides programmatic ways to add messages to the source. The ResourceBundleMessageSource
is shown in the following example:
class="org.springframework.context.support.ResourceBundleMessageSource">
format
exceptions
windows
In the example it is assumed you have three resource bundles defined in your classpath called format
, exceptions
and windows
. Any request to resolve a message will be handled in the JDK standard way of resolving messages through ResourceBundles. For the purposes of the example, assume the contents of two of the above resource bundle files are…
# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.
A program to execute the MessageSource
functionality is shown in the next example. Remember that all ApplicationContext
implementations are also MessageSource
implementations and so can be cast to the MessageSource
interface.
public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}
The resulting output from the above program will be…
Alligators rock!
So to summarize, the MessageSource
is defined in a file called beans.xml
, which exists at the root of your classpath. The messageSource
bean definition refers to a number of resource bundles through its basenames
property. The three files that are passed in the list to the basenames
property exist as files at the root of your classpath and are called format.properties
, exceptions.properties
, and windows.properties
respectively.
The next example shows arguments passed to the message lookup; these arguments will be converted into Strings and inserted into placeholders in the lookup message.
public class Example {private MessageSource messages; public void setMessages(MessageSource messages) { this.messages = messages; } public void execute() { String message = this.messages.getMessage("argument.required", new Object [] {"userDao"}, "Required", null); System.out.println(message); }
}
The resulting output from the invocation of the execute()
method will be…
The userDao argument is required.
With regard to internationalization (i18n), Spring’s various MessageSource
implementations follow the same locale resolution and fallback rules as the standard JDKResourceBundle
. In short, and continuing with the example messageSource
defined previously, if you want to resolve messages against the British (en-GB
) locale, you would create files called format_en_GB.properties
, exceptions_en_GB.properties
, and windows_en_GB.properties
respectively.
Typically, locale resolution is managed by the surrounding environment of the application. In this example, the locale against which (British) messages will be resolved is specified manually.
# in exceptions_en_GB.properties
argument.required=Ebagum lad, the {0} argument is required, I say, required.
public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.UK);
System.out.println(message);
}
The resulting output from the running of the above program will be…
Ebagum lad, the 'userDao' argument is required, I say, required.
You can also use the MessageSourceAware
interface to acquire a reference to any MessageSource
that has been defined. Any bean that is defined in anApplicationContext
that implements the MessageSourceAware
interface is injected with the application context’s MessageSource
when the bean is created and configured.
|
|
As an alternative to ResourceBundleMessageSource
, Spring provides a ReloadableResourceBundleMessageSource
class. This variant supports the same bundle file format but is more flexible than the standard JDK based ResourceBundleMessageSource
implementation. In particular, it allows for reading files from any Spring resource location (not just from the classpath) and supports hot reloading of bundle property files (while efficiently caching them in between). Check out the ReloadableResourceBundleMessageSource
javadocs for details.
|
7.16 The BeanFactory
The BeanFactory
API provides the underlying basis for Spring’s IoC functionality. Its specific contracts are mostly used in integration with other parts of Spring and related third-party frameworks, and its DefaultListableBeanFactory
implementation is a key delegate within the higher-level GenericApplicationContext
container.
BeanFactory接口是Spring IoC的基础。它的特定契约主要用于与Spring的其他部分以及相关的第三方框架集成,它的“DefaultListableBeanFactory”实现是高级“GenericApplicationContext”容器中的一个关键委托。
BeanFactory
and related interfaces such as BeanFactoryAware
, InitializingBean
, DisposableBean
are important integration points for other framework components: not requiring any annotations or even reflection, they allow for very efficient interaction between the container and its components. Application-level beans may use the same callback interfaces but will typically prefer declarative dependency injection instead, either via annotations or through programmatic configuration.
“BeanFactory”和相关接口(如“BeanFactoryAware”、“InitializingBean”、“DisposableBean”)是其他框架组件的重要集成点:不需要任何注解甚至反射,它们允许容器及其组件之间非常高效的交互。应用程序级bean可能使用相同的回调接口,但通常更喜欢声明性依赖注入,通过注解或编程配置。
Note that the core BeanFactory
API level and its DefaultListableBeanFactory
implementation do not make assumptions about the configuration format or any component annotations to be used. All of these flavors come in through extensions such as XmlBeanDefinitionReader
and AutowiredAnnotationBeanPostProcessor
, operating on shared BeanDefinition
objects as a core metadata representation. This is the essence of what makes Spring’s container so flexible and extensible.
请注意,核心的“BeanFactory”API级别及其“DefaultListableBeanFactory”实现对配置格式或要使用的任何组件注释不做任何假设。所有这些功能都是通过诸如“XmlBeanDefinitionReader”和“AutowiredAnnotationBeanPostProcessor”等扩展来实现的,这些扩展在作为核心元数据表示的共享“BeanDefinition”对象上运行。这就是使Spring容器如此灵活和可扩展的本质。
BeanFactory接口方法
序号 | 方法名称 | 描述 |
---|---|---|
1 | Object getBean(String name) throws BeansException; | 返回指定bean的一个实例,该实例可以是共享的,也可以是独立的。 |
2 | 输入bean必须匹配。可以是实际类的接口或超类,也可以是任何匹配的{null}。例如,如果值是{Object.class}对象。无论返回的实例的类是什么,这个方法都会成功。 | |
3 | 允许指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数(如果有的话) | |
4 | Object getBean(String name, Object... args) throws BeansException; | 使用显式参数创建bean实例时使用的args参数(仅在创建新实例而不是检索现有实例时使用) |
5 | 使用显式参数创建bean实例时使用的args参数(仅在创建新实例而不是检索现有实例时使用) | |
6 | boolean containsBean(String name); | 这个bean工厂是包含bean定义还是外部注册的具有给定名称的singleton实例 |
7 | boolean isSingleton(String name) throws NoSuchBeanDefinitionException; | 是否singleton |
8 | boolean isPrototype(String name) throws NoSuchBeanDefinitionException; | 是否prototype |
9 | boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; | name与传入类型是否匹配,ResolvableType是封装的java.lang.reflect.Type |
10 | boolean isTypeMatch(String name, Class> typeToMatch) throws NoSuchBeanDefinitionException; | name与传入类型是否匹配 |
11 | Class> getType(String name) throws NoSuchBeanDefinitionException; | 返回给定bean name的类型 |
12 | String[] getAliases(String name); | 返回给定bean name的别名 |
The following section explains the differences between the BeanFactory
and ApplicationContext
container levels and the implications on bootstrapping.
下一节将解释“BeanFactory”和“ApplicationContext”容器级别之间的差异以及引导的含义。
7.16.1 BeanFactory or ApplicationContext?
Use an ApplicationContext
unless you have a good reason for not doing so, with GenericApplicationContext
and its subclass AnnotationConfigApplicationContext
as the common implementations for custom bootstrapping. These are the primary entry points to Spring’s core container for all common purposes: loading of configuration files, triggering a classpath scan, programmatically registering bean definitions and annotated classes.
尽量使用‘ApplicationContext’除非你有很好的理由不这样做,使用‘GenericApplicationContext’和它的子类‘AnnotationConfigApplicationContext’作为通用的自定义引导实现。这些是Spring核心容器的主要入口点,用于所有常见目的:加载配置文件、触发类路径扫描、以编程方式注册bean定义和带注释的类。
Because an ApplicationContext
includes all functionality of a BeanFactory
, it is generally recommended over a plain BeanFactory
, except for a scenarios where full control over bean processing is needed. Within an ApplicationContext
such as the GenericApplicationContext
implementation, several kinds of beans will be detected by convention (i.e. by bean name or by bean type), in particular post-processors, whereas a plain DefaultListableBeanFactory
is agnostic about any special beans.
因为“ApplicationContext”包含“BeanFactory”的所有功能,所以通常建议使用它而不是普通的“BeanFactory”,除非是需要对bean处理进行完全控制的场景。在‘ApplicationContext’(如‘GenericApplicationContext’实现)中,有几种类型的bean将被约定(即通过bean名称或bean类型)检测,特别是后处理器,而普通的‘DefaultListableBeanFactory’与任何特殊bean无关。
For many extended container features such as annotation processing and AOP proxying, the BeanPostProcessor
extension point is essential. If you use only a plain DefaultListableBeanFactory
, such post-processors will not get detected and activated by default. This situation could be confusing because nothing is actually wrong with your bean configuration; it is rather the container which needs to be fully bootstrapped through additional setup in such a scenario.
对于许多扩展容器特性,如注释处理和AOP代理,' BeanPostProcessor '扩展点是必不可少的。如果你只使用一个普通的“DefaultListableBeanFactory”,这样的后处理器在默认情况下不会被检测和激活。这种情况可能令人困惑,因为您的bean配置实际上没有任何问题;在这种情况下,需要通过额外的设置完全引导容器。
The following table lists features provided by the BeanFactory
and ApplicationContext
interfaces and implementations.
下表列出了“BeanFactory”和“ApplicationContext”接口和实现提供的功能
Table 7.9. Feature Matrix
Feature | BeanFactory |
ApplicationContext |
---|---|---|
Bean instantiation/wiring | Yes | Yes |
Integrated lifecycle management | No | Yes |
Automatic BeanPostProcessor registration |
No | Yes |
Automatic BeanFactoryPostProcessor registration |
No | Yes |
Convenient MessageSource access (for internalization) |
No | Yes |
Built-in ApplicationEvent publication mechanism |
No | Yes |
To explicitly register a bean post-processor with a DefaultListableBeanFactory
, you need to programmatically call addBeanPostProcessor
:
要显式地将bean后处理器注册到DefaultListableBeanFactory,您需要以编程方式调用addBeanPostProcessor:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());
// now start using the factory
To apply a BeanFactoryPostProcessor
to a plain DefaultListableBeanFactory
, you need to call its postProcessBeanFactory
method:
要将' BeanFactoryPostProcessor '应用到普通的' DefaultListableBeanFactory '上,需要调用其' postProcessBeanFactory '方法:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// now actually do the replacement
cfg.postProcessBeanFactory(factory);
In both cases, the explicit registration steps are inconvenient, which is why the various ApplicationContext
variants are preferred over a plainDefaultListableBeanFactory
in Spring-backed applications, especially when relying on BeanFactoryPostProcessor
s and BeanPostProcessor
s for extended container functionality in a typical enterprise setup.
在这两种情况下,显式注册步骤都不方便,这就是为什么在spring支持的应用程序中,各种“ApplicationContext”变体比普通的“defaultlistablebeanfactory”更受青睐的原因,特别是在典型的企业设置中依赖“BeanFactoryPostProcessor”和“BeanPostProcessor”实现扩展容器功能时更是如此。
An
AnnotationConfigApplicationContext
has all common annotation post-processors registered out of the box and may bring in additional processors underneath the covers through configuration annotations such as@EnableTransactionManagement
. At the abstraction level of Spring’s annotation-based configuration model, the notion of bean post-processors becomes a mere internal container detail.
一个“AnnotationConfigApplicationContext”具有所有现成注册的通用注释后处理器,并且可以通过配置注释(如“@EnableTransactionManagement”)在幕后引入额外的处理器。在Spring基于注释的配置模型的抽象级别上,bean后处理器的概念仅仅是一个内部容器细节。