文章作者:Tyan
博客:noahsnail.com
3.2 Container overview
The interface org.springframework.context.ApplicationContext
represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It allows you to express the objects that compose your application and the rich interdependencies between such objects.
org.springframework.context.ApplicationContext
接口代表了Spring IoC容器并且负责实例化、配置和组装前面提到的beans。容器通过读取配置元数据得到说明什么对象要实例化、配置和组装。配置元数据可以用XML、Java注解或Java代码表示。它允许你表示构成应用的对象和对象间丰富的依赖关系。
Several implementations of the ApplicationContext
interface are supplied out-of-the-box with Spring. In standalone applications it is common to create an instance of ClassPathXmlApplicationContext
or FileSystemXmlApplicationContext
. While XML has been the traditional format for defining configuration metadata you can instruct the container to use Java annotations or code as the metadata format by providing a small amount of XML configuration to declaratively enable support for these additional metadata formats.
Spring提供了一些可以直接使用的ApplicationContext
接口实现。在单独的应用中通常是创建一个 ClassPathXmlApplicationContext
实例或FileSystemXmlApplicationContext
实例。虽然XML是定义配置元数据的传统格式,但你可以指示容器支持使用Java注解或代码作为元数据的格式并通过提供少量的XML配置声明使容器支持这些额外的元数据格式。
In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the web.xml
file of the application will typically suffice (see Section 3.15.4, “Convenient ApplicationContext instantiation for web applications”). If you are using the Spring Tool Suite Eclipse-powered development environment this boilerplate configuration can be easily created with few mouse clicks or keystrokes.
在大多数应用场景中,不会要求用户用显式的代码来实例化一个或多个Spring IoC容器的。例如,在web应用场景中,在应用的web.xml
文件中写一个简单的八行左右的样板web描述符XML就足够了(看3.13.4小节,『web应用中ApplicationContext的方便实例化』)。如果你正在使用Eclipse支持的Spring Tool Suite开发环境,可以很容易的通过点几下鼠标或键盘来创建样本配置。
The following diagram is a high-level view of how Spring works. Your application classes are combined with configuration metadata so that after the ApplicationContext
is created and initialized, you have a fully configured and executable system or application.
下面的图是从一个高层次的视野来看Spring是如何工作的。你的应用类与配置元数据结合起来为的是在ApplicationContext
创建和初始化之后,你有一个完整配置并可执行的系统或应用。
Figure 3.1. The Spring IoC container
3.2.1 Configuration metadata
As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata; this configuration metadata represents how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application.
如上图所示,Spring IoC容器使用了一种配置元数据的方式;配置元数据表示你作为一个应用开发者应该告诉Spring容器怎样去实例化、配置并组装应用中的对象。
Configuration metadata is traditionally supplied in a simple and intuitive XML format, which is what most of this chapter uses to convey key concepts and features of the Spring IoC container.
习惯上用简单直观下XML形式来提供配置元数据,这一章大部分使用XML文件来表达Spring IoC容器的核心概念及功能。
XML-based metadata is not the only allowed form of configuration metadata. The Spring IoC container itself is totally decoupled from the format in which this configuration metadata is actually written. These days many developers choose Java-based configuration for their Spring applications.
基于XML的元数据不是配置元数据的唯一许可形式。Spring IoC容器本身与配置元数据的实际书写形式是完全解构的。目前许多开发者在他们的Spring应用中选用基于Java配置的元数据形式。
For information about using other forms of metadata with the Spring container, see:
- Annotation-based configuration: Spring 2.5 introduced support for annotation-based configuration metadata.
- Java-based configuration: Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus you can define beans external to your application classes by using Java rather than XML files. To use these new features, see the
@Configuration
,@Bean
,@Import
and@DependsOn
annotations.
关于Spring容器中使用其它元数据形式的信息,请看:
- 基于注解的配置:Spring 2.5引入对了基于注解的配置元数据的支持。
- 基于Java的配置:从Spring 3.0开始,Spring JavaConfig工程提供的许多功能开始成为Spring框架核心中的一部分。因此你可以通过Java而不是XML文件来定义外部应用程序的beans。为了使用这些新功能,请看
@Configuration
,@Bean
,@Import
和@DependsOn
注解。
Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata shows these beans configured as <bean/>
elements inside a top-level <beans/>
element. Java configuration typically uses @Bean
annotated methods within a @Configuration
class.
Spring配置包括至少一个且通常不止一个容器必须管理的bean定义。基于XML的配置元数据中,这些beans作为<bean>
元素被配置在顶层<beans/>
元素中。Java配置通常在@Configuration
类中使用@Bean
注解的方法。
These bean definitions correspond to the actual objects that make up your application. Typically you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action
instances, infrastructure objects such as Hibernate SessionFactories
, JMS Queues
, and so forth. Typically one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container. See Using AspectJ to dependency-inject domain objects with Spring.
这些bean定义与组成你应用的实际对象相对应。通常你会定义服务层对象,数据访问层对象(DAOs),描述对象例如Struts的Action
实例,底层对象例如Hibernate的SessionFactories
,JMS的Queues
等等。容器中细粒度的领域对象通常是不配置的,因为一般是由DAOs和业务逻辑负责创建和加载领域对象。然而你可以使用Spring集成的AspectJ去配置IoC容器控制之外创建的对象。请看"使用Spring的AspectJ来依赖注入领域对象"。
The following example shows the basic structure of XML-based configuration metadata:
下面的例子展示了基于XML配置元数据的基本结构:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
The id
attribute is a string that you use to identify the individual bean definition. The class
attribute defines the type of the bean and uses the fully qualified classname. The value of the id
attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example; see Dependencies for more information.
id
属性是一个你用来识别私有bean定义的字符串。class
属性定义了bean的类型并且使用了完全限定类型名称(全限定名称或完全限定名)。id
属性的值指的是协作对象。这个例子的中没有展示如何引用协作对象,更多信息请查看『依赖』。
3.2.2 Instantiating a container
Instantiating a Spring IoC container is straightforward. The location path or paths supplied to an ApplicationContext
constructor are actually resource strings that allow the container to load configuration metadata from a variety of external resources such as the local file system, from the Java CLASSPATH
, and so on.
实例化一个Spring IoC容器是简单的。一个或多个提供给ApplicationContext
构造函数的定位路径实际上是资源字符串,可以让容器从各种例如局部文件系统,Java的CLASSPATH
等外部资源中加载配置元数据。
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
After you learn about Spring’s IoC container, you may want to know more about Spring’s
Resource
abstraction, as described in Chapter 4, Resources, which provides a convenient mechanism for reading an InputStream from locations defined in a URI syntax. In particular,Resource
paths are used to construct applications contexts as described in Section 4.7, “Application contexts and Resource paths”.
在你学习Spring IoC容器之后,你可能想知道更多关于Spring的
Resource
抽象信息,介绍信息在『第四章 资源』中,Resource
抽象提供了一种方便的机制从URI语法定义的位置中读取输入流。Resource
路径通常被用来构建应用程序上下文,正如4.7 小节『应用上下文和资源路径』描述的那样。
The following example shows the service layer objects (services.xml
) configuration file:
下面的例子是服务层对象(services.xml
)的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- services -->
<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for services go here -->
</beans>
The following example shows the data access objects daos.xml
file:
下面的例子是数据访问对象daos.xml
的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for data access objects go here -->
</beans>
In the preceding example, the service layer consists of the class PetStoreServiceImpl
, and two data access objects of the type JpaAccountDao
and JpaItemDao
(based on the JPA Object/Relational mapping standard). The property name
element refers to the name of the JavaBean property, and the ref
element refers to the name of another bean definition. This linkage between id
and ref
elements expresses the dependency between collaborating objects. For details of configuring an object’s dependencies, see Dependencies.
在之前的例子中,服务层包括类PetStoreServiceImpl
和两个类型为JpaAccountDao
和JpaItemDao
数据访问对象(基于JPA对象/关系映射标准)。property name
元素指的是JavaBean属性的名称,ref
元素指的是另一个bean定义的名称。id
和ref
之间的连接表明了协作对象之间的关系。配置对象依赖的更详细信息请看『依赖』。
Composing XML-based configuration metadata
It can be useful to have bean definitions span multiple XML files. Often each individual XML configuration file represents a logical layer or module in your architecture.
bean定义跨越多个XML文件是非常有用的。通常每一个独立的XML配置文件表示你架构中的一个逻辑层或模块。
You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource
locations, as was shown in the previous section. Alternatively, use one or more occurrences of the <import/>
element to load bean definitions from another file or files. For example:
你可以使用应用上下文构造函数从所有XML片段中加载bean定义。如上小节所示,构造函数可以接收多个Resource
位置。也可以使用一个或同时使用多个<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>
In the preceding example, external bean definitions are loaded from three files: services.xml
, messageSource.xml
, and themeSource.xml
. All location paths are relative to the definition file doing the importing, so services.xml
must be in the same directory or classpath location as the file doing the importing, while messageSource.xml
and themeSource.xml
must be in a resources
location below the location of the importing file. As you can see, a leading slash is ignored, but given that these paths are relative, it is better form not to use the slash at all. The contents of the files being imported, including the top level <beans/>
element, must be valid XML bean definitions according to the Spring Schema.
在上面的例子中,外部bean定义从services.xml
、messageSource.xml
和themeSource.xml
三个文件中加载。所有位置路径都是相对于进行导入的定义文件的,因此services.xml
必须跟进行导入的文件在同一个目录下或同一个classpath位置下。如你所见,忽略了最前面的反斜杠,但给定的这些路径是相对的,最好是一点都不使用反斜杠。包括顶层的<beans/>
元素在内,被导入的文件内容必须是依据Spring Schema有效的XML bean定义。
It is possible, but not recommended, to reference files in parent directories using a relative "../" path. Doing so creates a dependency on a file that is outside the current application. In particular, this reference is not recommended for "classpath:" URLs (for example, "classpath:../services.xml"), where the runtime resolution process chooses the "nearest" classpath root and then looks into its parent directory. Classpath configuration changes may lead to the choice of a different, incorrect directory.
You can always use fully qualified resource locations instead of relative paths: for example, "file:C:/config/services.xml" or "classpath:/config/services.xml". However, be aware that you are coupling your application’s configuration to specific absolute locations. It is generally preferable to keep an indirection for such absolute locations, for example, through "${…}" placeholders that are resolved against JVM system properties at runtime.
在父目录的引用文件使用"../"相对路径是可以的,但不推荐这样做。这样做会产生一个当前应用之外文件依赖。引用文件特别不推荐在"classpath:" URLs中(例如"classpath:../services.xml"),运行时解析处理会选择"最近的"classpath根目录,然后去寻找它的父目录。Classpath配置的更改可能会导致进入一个不同且不正确的目录。
你可以总是使用完全限定资源位置代替相对路径:例如,"file:C:/config/services.xml"或"classpath:/config/services.xml"。但是要注意你正在将你的应用配置与特定的绝对路径耦合。通常更可取的方式是间接的访问绝对路径,例如,通过"${…}"占位符在运行时解析JVM系统属性。
3.2.3 Using the container
The ApplicationContext
is the interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. Using the method T getBean(String name, Class<T> requiredType)
you can retrieve instances of your beans.
ApplicationContext
是一个更高级的工厂接口,它能维护不同beans及其依赖的注册表。使用方法T getBean(String name, Class<T> requiredType)
你可以取回你的beans实例。
The ApplicationContext
enables you to read bean definitions and access them as follows:
ApplicationContext
能让你用下面的方式读取bean定义及访问它们:
// create and configure beans
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();
You use getBean()
to retrieve instances of your beans. The ApplicationContext
interface has a few other methods for retrieving beans, but ideally your application code should never use them. Indeed, your application code should have no calls to the getBean()
method at all, and thus no dependency on Spring APIs at all. For example, Spring’s integration with web frameworks provides for dependency injection for various web framework classes such as controllers and JSF-managed beans.
你可以用getBean()
取回你的beans实例。ApplicationContext
接口有一些其它的方法来取回beans,但理想的应用代码应该绝不使用它们。事实上,你的应用代码应该完全不调用getBean()
方法,因此完全不依赖Spring APIs。例如,Spring的集成web框架提供了各种web框架类的依赖注入,例如控制器和JSF管理的beans。