This part of the appendix lists XML schemas related to the core container.
附录的这一部分列出了与核心容器相关的 XML 模式。
util Schema 10.1.1.util 架构As the name implies, the util tags deal with common, utility configuration issues, such as configuring collections,
referencing constants, and so forth. To use the tags in the util schema, you need to have the following preamble at
the top of your Spring XML configuration file (the text in the snippet references the correct schema so that the tags in
the util namespace are available to you):
如名称所示, util 标签处理常见的实用配置问题,例如配置集合、引用常量等。要在 util 架构中使用这些标签,您需要在 Spring XML
配置文件的顶部包含以下前缀(片段中的文本引用了正确的架构,以便您可以使用 util 命名空间中的标签):
<util:constant/> 使用<util:constant/>Consider the following bean definition:
考虑以下 Bean 定义:
The preceding configuration uses a Spring FactoryBean implementation (the FieldRetrievingFactoryBean) to set the
value of the isolation property on a bean to the value of the java.sql.Connection.TRANSACTION_SERIALIZABLE constant.
This is all well and good, but it is verbose and (unnecessarily) exposes Spring’s internal plumbing to the end user.
前一个配置使用 Spring FactoryBean 实现( FieldRetrievingFactoryBean )将 bean 的 isolation 属性值设置为
java.sql.Connection.TRANSACTION_SERIALIZABLE 常量的值。这很好,但是它很冗长,并且(不必要地)将 Spring 的内部结构暴露给了最终用户。
The following XML Schema-based version is more concise, clearly expresses the developer’s intent (“inject this constant
value”), and it reads better:
以下基于 XML Schema 的版本更简洁,清楚地表达了开发者的意图(“注入此常量值”),并且读起来更好:
设置从字段值设置 Bean 属性或构造函数参数
FieldRetrievingFactoryBean
is a FactoryBean that retrieves a static or non-static field value. It is typically used for retrieving public
static final constants, which may then be used to set a property value or constructor argument for another bean.
FieldRetrievingFactoryBean 是一个用于检索 FactoryBean 或非静态字段值的 static 。它通常用于检索 public static
final 常量,这些常量随后可用于设置另一个 bean 的属性值或构造函数参数。
The following example shows how a static field is exposed, by using the
staticField
property:
以下示例展示了如何通过使用 staticField 属性来暴露 static 字段:
There is also a convenience usage form where the static field is specified as the bean name, as the following example
shows:
这里还有一个方便的用法形式,其中 static 字段被指定为 bean 名称,如下例所示:
This does mean that there is no longer any choice in what the bean id is (so any other bean that refers to it also has
to use this longer name), but this form is very concise to define and very convenient to use as an inner bean since the
id does not have to be specified for the bean reference, as the following example shows:
这意味着不再有选择来指定 bean id 的名称(因此任何引用它的其他 bean 也必须使用这个较长的名称),但这种形式在定义时非常简洁,作为内部
bean 使用也非常方便,因为不需要指定 id 来引用 bean,如下面的示例所示:
You can also access a non-static (instance) field of another bean, as described in the API documentation for the
FieldRetrievingFactoryBean
class.
您还可以访问另一个 bean 的非静态(实例)字段,如 FieldRetrievingFactoryBean 类的 API 文档中所述。
Injecting enumeration values into beans as either property or constructor arguments is easy to do in Spring. You do not
actually have to do anything or know anything about the Spring internals (or even about classes such as the
FieldRetrievingFactoryBean). The following example enumeration shows how easy injecting an enum value is:
将枚举值注入到 Bean 中作为属性或构造函数参数在 Spring 中很容易实现。实际上,您不需要做任何事情或了解任何关于 Spring
内部(甚至关于像 FieldRetrievingFactoryBean 这样的类)的信息。以下示例枚举展示了注入枚举值是多么简单:
Now consider the following setter of type PersistenceContextType and the corresponding bean definition:
现在考虑以下类型为 PersistenceContextType 的 setter 以及相应的 bean 定义:
<util:property-path/> 使用<util:property-path/>Consider the following example:
考虑以下示例:
The preceding configuration uses a Spring FactoryBean implementation (the PropertyPathFactoryBean) to create a
bean (of type int) called testBean.age that has a value equal to the age property of the testBean bean.
前一个配置使用 Spring FactoryBean 实现( PropertyPathFactoryBean )创建一个名为 testBean.age 的 bean(类型为 int
),其值等于 testBean bean 的 age 属性。
Now consider the following example, which adds a <util:property-path/> element:
现在考虑以下示例,其中添加了一个 <util:property-path/> 元素:
The value of the path attribute of the <property-path/> element follows the form of beanName.beanProperty. In this
case, it picks up the age property of the bean named testBean. The value of that age property is 10.
该 <property-path/> 元素的 path 属性值遵循 beanName.beanProperty 格式。在这种情况下,它获取名为 testBean 的 bean 的
age 属性。该 age 属性的值是 10 。
<util:property-path/> to Set a Bean Property or Constructor Argument
使用 <util:property-path/> 设置 Bean 属性或构造函数参数
PropertyPathFactoryBean is a FactoryBean that evaluates a property path on a given target object. The target object
can be specified directly or by a bean name. You can then use this value in another bean definition as a property value
or constructor argument.
PropertyPathFactoryBean 是一个用于在给定的目标对象上评估属性路径的 FactoryBean 。目标对象可以直接指定或通过 bean
名称指定。然后您可以使用此值在另一个 bean 定义中作为属性值或构造函数参数。
The following example shows a path being used against another bean, by name:
以下示例展示了使用路径针对另一个名为的 bean:
In the following example, a path is evaluated against an inner bean:
在以下示例中,一条路径被与内部 bean 进行比较:
There is also a shortcut form, where the bean name is the property path. The following example shows the shortcut
form:
也存在一种快捷形式,其中 bean 名称是属性路径。以下示例展示了快捷形式:
This form does mean that there is no choice in the name of the bean. Any reference to it also has to use the same id,
which is the path. If used as an inner bean, there is no need to refer to it at all, as the following example shows:
这个表单确实意味着在 bean 的名称上没有选择。任何对其的引用也必须使用相同的 id ,即路径。如果用作内部 bean,根本不需要引用它,如下例所示:
You can specifically set the result type in the actual definition. This is not necessary for most use cases, but it can
sometimes be useful. See the javadoc for more info on this feature.
您可以在实际定义中具体设置结果类型。对于大多数用例来说,这不是必需的,但有时可能很有用。有关此功能的更多信息,请参阅 javadoc。
<util:properties/> 使用<util:properties/>Consider the following example:
考虑以下示例:
The preceding configuration uses a Spring FactoryBean implementation (the PropertiesFactoryBean) to instantiate a
java.util.Properties instance with values loaded from the supplied Resource location).
前一个配置使用 Spring FactoryBean 实现( PropertiesFactoryBean )来实例化一个从提供的 Resource 位置加载值的
java.util.Properties 实例)。
The following example uses a util:properties element to make a more concise representation:
以下示例使用 util:properties 元素来创建更简洁的表示:
<util:list/> 使用<util:list/>Consider the following example:
考虑以下示例:
The preceding configuration uses a Spring FactoryBean implementation (the ListFactoryBean) to create a
java.util.List instance and initialize it with values taken from the supplied sourceList.
前一个配置使用 Spring FactoryBean 实现( ListFactoryBean )来创建一个 java.util.List 实例,并用从提供的 sourceList
中取出的值来初始化它。
The following example uses a <util:list/> element to make a more concise representation:
以下示例使用 <util:list/> 元素来创建更简洁的表示:
You can also explicitly control the exact type of List that is instantiated and populated by using the list-class
attribute on the <util:list/> element. For example, if we really need a java.util.LinkedList to be instantiated, we
could use the following configuration:
您也可以通过在 <util:list/> 元素上使用 list-class 属性来显式控制实例化和填充的 List 的确切类型。例如,如果我们确实需要实例化一个
java.util.LinkedList ,我们可以使用以下配置:
If no list-class attribute is supplied, the container chooses a List implementation.
如果没有提供 list-class 属性,容器将选择 List 实现。
<util:map/> 使用<util:map/>Consider the following example:
考虑以下示例:
The preceding configuration uses a Spring FactoryBean implementation (the MapFactoryBean) to create a
java.util.Map instance initialized with key-value pairs taken from the supplied 'sourceMap'.
前一个配置使用 Spring FactoryBean 实现( MapFactoryBean )来创建一个实例,该实例使用从提供的 'sourceMap'
中获取的键值对进行初始化。
The following example uses a <util:map/> element to make a more concise representation:
以下示例使用 <util:map/> 元素来创建更简洁的表示:
You can also explicitly control the exact type of Map that is instantiated and populated by using the 'map-class'
attribute on the <util:map/> element. For example, if we really need a java.util.TreeMap to be instantiated, we
could use the following configuration:
您也可以通过在 <util:map/> 元素上使用 'map-class' 属性来显式控制实例化和填充的 Map 的确切类型。例如,如果我们确实需要实例化一个
java.util.TreeMap ,我们可以使用以下配置:
If no 'map-class' attribute is supplied, the container chooses a Map implementation.
如果没有提供 'map-class' 属性,容器将选择 Map 实现。
<util:set/> 使用<util:set/>Consider the following example:
考虑以下示例:
The preceding configuration uses a Spring FactoryBean implementation (the SetFactoryBean) to create a
java.util.Set instance initialized with values taken from the supplied sourceSet.
前一个配置使用 Spring FactoryBean 实现( SetFactoryBean )来创建一个初始化自提供的 sourceSet 的 java.util.Set 实例。
The following example uses a <util:set/> element to make a more concise representation:
以下示例使用 <util:set/> 元素来创建更简洁的表示:
You can also explicitly control the exact type of Set that is instantiated and populated by using the set-class
attribute on the <util:set/> element. For example, if we really need a java.util.TreeSet to be instantiated, we
could use the following configuration:
您也可以通过在 <util:set/> 元素上使用 set-class 属性来显式控制实例化和填充的 Set 的确切类型。例如,如果我们确实需要实例化一个
java.util.TreeSet ,我们可以使用以下配置:
If no set-class attribute is supplied, the container chooses a Set implementation.
如果没有提供 set-class 属性,容器将选择 Set 实现。
aop Schema 10.1.2.aop 架构The aop tags deal with configuring all things AOP in Spring, including Spring’s own proxy-based AOP framework and
Spring’s integration with the AspectJ AOP framework. These tags are comprehensively covered in the chapter
entitled Aspect Oriented Programming with Spring.
aop 标签用于配置 Spring 中所有 AOP 相关内容,包括 Spring 自带的基于代理的 AOP 框架以及 Spring 与 AspectJ AOP
框架的集成。这些标签在名为《Spring 中的面向切面编程》的章节中有全面介绍。
In the interest of completeness, to use the tags in the aop schema, you need to have the following preamble at the top
of your Spring XML configuration file (the text in the snippet references the correct schema so that the tags in the
aop namespace are available to you):
为了完整性,要在 Spring XML 配置文件的顶部包含以下前缀,以便使用 aop 模式中的标签(片段中的文本引用了正确的模式,以便您可以使用
aop 命名空间中的标签):
context Schema 10.1.3.context 架构The context tags deal with ApplicationContext configuration that relates to plumbing — that is, not usually beans
that are important to an end-user but rather beans that do a lot of the “grunt” work in Spring, such as
BeanfactoryPostProcessors. The following snippet references the correct schema so that the elements in the context
namespace are available to you:
context 标签处理与管道相关的 ApplicationContext 配置——也就是说,通常不是对最终用户重要的豆子,而是 Spring
中做大量“苦力”工作的豆子,例如 BeanfactoryPostProcessors 。以下代码片段引用了正确的模式,以便您可以使用 context
命名空间中的元素:
<property-placeholder/> 使用<property-placeholder/>This element activates the replacement of ${…} placeholders, which are resolved against a specified properties file (
as a Spring resource location). This element is a convenience mechanism that sets up a
PropertySourcesPlaceholderConfigurer for you. If you need more control over the
specific PropertySourcesPlaceholderConfigurer setup, you can explicitly define it as a bean yourself.
此元素激活了 ${…} 占位符的替换,这些占位符将针对指定的属性文件(作为 Spring 资源位置)进行解析。此元素是一个便利机制,为您设置
PropertySourcesPlaceholderConfigurer 。如果您需要更多控制特定的 PropertySourcesPlaceholderConfigurer 设置,您可以自己显式地将其定义为
bean。
<annotation-config/> 使用<annotation-config/>This element activates the Spring infrastructure to detect annotations in bean classes:
此元素激活 Spring 基础设施以检测 bean 类中的注解:
Spring’s @Configuration model 春季的 @Configuration 模型
@Autowired/@Inject, @Value, and @Lookup
@Autowired / @Inject , @Value ,和 @Lookup
JSR-250’s @Resource, @PostConstruct, and @PreDestroy (if available)
JSR-250 的 @Resource 、 @PostConstruct 和 @PreDestroy (如有)
JAX-WS’s @WebServiceRef and EJB 3’s @EJB (if available)
JAX-WS 的 @WebServiceRef 和 EJB 3 的 @EJB (如有)
JPA’s @PersistenceContext and @PersistenceUnit (if available)
JPA 的 @PersistenceContext 和 @PersistenceUnit (如有)
Spring’s @EventListener春季的 @EventListener
Alternatively, you can choose to explicitly activate the individual BeanPostProcessors for those annotations.
或者,您可以选择显式激活这些注释的个别 BeanPostProcessors 。
This element does not activate processing of Spring’s
@Transactional
annotation; you can use the
<tx:annotation-driven/>
element for that purpose. Similarly,
Spring’s caching annotations
need to be
explicitly enabled
as well.
此元素不会激活 Spring 的 @Transactional 注解的处理;您可以使用 <tx:annotation-driven/> 元素来实现该目的。同样,Spring
的缓存注解也需要显式启用。
<component-scan/> 使用<component-scan/>This element is detailed in the section on annotation-based container configuration.
此元素在基于注解的容器配置部分有详细说明。
<load-time-weaver/> 使用<load-time-weaver/>This element is detailed in the section on load-time weaving with AspectJ in the Spring Framework.
此元素在 Spring 框架中关于 AspectJ 加载时织入的章节中有详细说明。
<spring-configured/> 使用<spring-configured/>This element is detailed in the section
on using AspectJ to dependency inject domain objects with Spring.
此元素在关于使用 AspectJ 通过 Spring 依赖注入领域对象的章节中有详细说明。
<mbean-export/> 使用<mbean-export/>10.1.4. The Beans Schema 豆子模式
Last but not least, we have the elements in the beans schema. These elements have been in Spring since the very dawn
of the framework. Examples of the various elements in the beans schema are not shown here because they are quite
comprehensively covered in dependencies and configuration in detail (and, indeed,
in that entire chapter).
最后但同样重要的是,我们有 beans 架构中的元素。这些元素自从框架的诞生之初就存在于 Spring 中。这里没有展示 beans
架构中各种元素的示例,因为它们在依赖和配置的详细描述中已经得到了相当全面的覆盖(实际上,在整个那一章中都有涉及)。
Note that you can add zero or more key-value pairs to <bean/> XML definitions. What, if anything, is done with this
extra metadata is totally up to your own custom logic (and so is typically only of use if you write your own custom
elements as described in the appendix entitled XML Schema Authoring).
请注意,您可以为 <bean/> XML 定义添加零个或多个键值对。至于如何处理这些额外的元数据,完全取决于您自己的自定义逻辑(同样,这也通常仅在您编写自己的自定义元素时才有用,如附录中所述的
XML Schema Authoring)。
The following example shows the <meta/> element in the context of a surrounding <bean/> (note that, without any
logic to interpret it, the metadata is effectively useless as it stands).
以下示例展示了在周围 <bean/> 的上下文中 <meta/> 元素(请注意,如果没有任何逻辑来解释它,元数据就实际上毫无用处)。
1
This is the example meta element
这是示例 meta 元素
In the case of the preceding example, you could assume that there is some logic that consumes the bean definition and
sets up some caching infrastructure that uses the supplied metadata.
在这种情况下,您可以假设存在某种逻辑,它消耗豆定义并设置一些使用提供的元数据的缓存基础设施。
10.2. XML 模式编写
Since version 2.0, Spring has featured a mechanism for adding schema-based extensions to the basic Spring XML format for
defining and configuring beans.
自 2.0 版本以来,Spring 引入了一种机制,用于向基本的 Spring XML 格式添加基于模式的扩展,以定义和配置 bean。
This section covers how to write your own custom XML bean definition parsers and integrate such parsers into the Spring
IoC container.
本节介绍如何编写自定义的 XML Bean 定义解析器,并将这些解析器集成到 Spring IoC 容器中。
To facilitate authoring configuration files that use a schema-aware XML editor, Spring’s extensible XML configuration
mechanism is based on XML Schema.
为了便于使用模式感知的 XML 编辑器编写配置文件,Spring 的可扩展 XML 配置机制基于 XML Schema。
If you are not familiar with Spring’s current XML configuration extensions that come with the standard Spring
distribution, you should first read the previous section on XML Schemas.
如果您不熟悉随标准 Spring 发行版一起提供的 Spring 当前 XML 配置扩展,您应该首先阅读关于 XML 模式的上一节。
To create new XML configuration extensions:
创建新的 XML 配置扩展:
Author an XML schema to describe your custom element(s).
定义一个 XML 模式来描述您的自定义元素(们)。
Code a custom NamespaceHandler implementation.
编写自定义 NamespaceHandler 实现。
Code one or more BeanDefinitionParser implementations (this is where the real work is
done).
代码一个或多个 BeanDefinitionParser 实现(这里才是真正的功夫所在)。
Register your new artifacts with Spring.
注册您的全新工件与 Spring。
For a unified example, we create an XML extension (a custom XML element) that lets us configure objects of the type
SimpleDateFormat (from the java.text package). When we are done, we will be able to define bean definitions of type
SimpleDateFormat as follows:
为了统一示例,我们创建了一个 XML 扩展(一个自定义 XML 元素),允许我们配置类型为 SimpleDateFormat (来自 java.text
包)的对象。完成之后,我们将能够按照以下方式定义类型为 SimpleDateFormat 的 bean 定义:
(We include much more detailed examples follow later in this appendix. The intent of this first simple example is to
walk you through the basic steps of making a custom extension.)
(我们将在附录的后续部分提供更多详细的示例。本节第一个简单示例的目的是向您展示制作自定义扩展的基本步骤。)
10.2.1. 编写模式
Creating an XML configuration extension for use with Spring’s IoC container starts with authoring an XML Schema to
describe the extension. For our example, we use the following schema to configure SimpleDateFormat objects:
创建用于与 Spring 的 IoC 容器一起使用的 XML 配置扩展,首先需要编写一个 XML Schema 来描述该扩展。在我们的示例中,我们使用以下
Schema 来配置 SimpleDateFormat 对象:
1
The indicated line contains an extension base for all identifiable tags (meaning they have an id attribute that we can
use as the bean identifier in the container). We can use this attribute because we imported the Spring-provided beans
namespace.
指示的行包含所有可识别标签的扩展基 (意味着它们有一个 id 属性,我们可以将其用作 bean 标识符) 容器)。我们可以使用这个属性,因为我们导入了
Spring 提供的 beans 命名空间。
The preceding schema lets us configure SimpleDateFormat objects directly in an XML application context file by using
the <myns:dateformat/> element, as the following example shows:
前一个模式允许我们通过使用 <myns:dateformat/> 元素,在 XML 应用程序上下文文件中直接配置 SimpleDateFormat 对象,如下例所示:
Note that, after we have created the infrastructure classes, the preceding snippet of XML is essentially the same as the
following XML snippet:
请注意,在创建基础设施类之后,前面的 XML 片段基本上与以下 XML 片段相同:
The second of the two preceding snippets creates a bean in the container (identified by the name dateFormat of type
SimpleDateFormat) with a couple of properties set.
第二个前一个片段在容器中创建了一个 bean(通过名称 dateFormat 标识,类型为 SimpleDateFormat ),并设置了几个属性。
The schema-based approach to creating configuration format allows for tight integration with an IDE that has a
schema-aware XML editor.
基于模式的创建配置格式的方案允许与具有模式感知的 XML 编辑器的 IDE 紧密集成。
By using a properly authored schema, you can use autocompletion to let a user choose between several configuration
options defined in the enumeration.
通过使用正确编写的模式,您可以使用自动完成功能,让用户在枚举中定义的几个配置选项之间进行选择。
NamespaceHandler 10.2.2. 编码NamespaceHandlerIn addition to the schema, we need a NamespaceHandler to parse all elements of this specific namespace that Spring
encounters while parsing configuration files. For this example, the NamespaceHandler should take care of the parsing
of the myns:dateformat element.
除了模式,我们还需要一个 NamespaceHandler 来解析 Spring 在解析配置文件时遇到的该特定命名空间的所有元素。对于这个例子,
NamespaceHandler 应该负责解析 myns:dateformat 元素。
The NamespaceHandler interface features three methods:
The NamespaceHandler interface features three methods: 该NamespaceHandler接口具有三种方法:
init(): Allows for initialization of the NamespaceHandler and is called by Spring before the handler is used.
init() :允许初始化 NamespaceHandler ,在处理器被使用之前由 Spring 调用。
BeanDefinition parse(Element, ParserContext): Called when Spring encounters a top-level element (not nested inside a
bean definition or a different namespace). This method can itself register bean definitions, return a bean definition,
or both.
当 Spring 遇到顶级元素(不在 bean 定义或不同命名空间内部嵌套)时调用。此方法本身可以注册 bean 定义,返回一个 bean
定义,或者两者兼而有之。
BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext): Called when Spring encounters an attribute
or nested element of a different namespace. The decoration of one or more bean definitions is used (for example) with
the scopes that Spring supports. We start by highlighting a simple example, without using
decoration, after which we show decoration in a somewhat more advanced example.
当 Spring 遇到不同命名空间的属性或嵌套元素时被调用。使用一个或多个 bean 定义的装饰(例如)与 Spring
支持的范围一起使用。我们首先通过一个简单的示例来突出显示,该示例不使用装饰,之后我们将在一个稍微复杂一些的示例中展示装饰。
Although you can code your own NamespaceHandler for the entire namespace (and hence provide code that parses each and
every element in the namespace), it is often the case that each top-level XML element in a Spring XML configuration file
results in a single bean definition (as in our case, where a single <myns:dateformat/> element results in a single
SimpleDateFormat bean definition). Spring features a number of convenience classes that support this scenario. In the
following example, we use the NamespaceHandlerSupport class:
尽管您可以为自己的整个命名空间编写自己的 NamespaceHandler (因此提供解析命名空间中每个元素的代码),但通常情况下,Spring
XML 配置文件中的每个顶级 XML 元素都会导致一个单独的 bean 定义(就像在我们的例子中,一个单独的 <myns:dateformat/>
元素导致一个单独的 SimpleDateFormat bean 定义)。Spring 提供了一些便利类来支持这种场景。在以下示例中,我们使用
NamespaceHandlerSupport 类:
You may notice that there is not actually a whole lot of parsing logic in this class. Indeed, the
NamespaceHandlerSupport class has a built-in notion of delegation. It supports the registration of any number of
BeanDefinitionParser instances, to which it delegates to when it needs to parse an element in its namespace. This
clean separation of concerns lets a NamespaceHandler handle the orchestration of the parsing of all of the custom
elements in its namespace while delegating to BeanDefinitionParsers to do the grunt work of the XML parsing. This
means that each BeanDefinitionParser contains only the logic for parsing a single custom element, as we can see in the
next step.
您可能会注意到,这个类实际上并没有太多解析逻辑。确实, NamespaceHandlerSupport 类内置了委派的概念。它支持注册任意数量的
BeanDefinitionParser 实例,当它需要解析其命名空间中的元素时,就会委派给这些实例。这种清晰的关注点分离允许一个
NamespaceHandler 处理其命名空间中所有自定义元素的解析协调,同时将 XML 解析的繁琐工作委派给 BeanDefinitionParsers
。这意味着每个 BeanDefinitionParser 只包含解析单个自定义元素的逻辑,正如我们将在下一步看到的那样。
BeanDefinitionParser 10.2.3. 使用BeanDefinitionParserA BeanDefinitionParser is used if the NamespaceHandler encounters an XML element of the type that has been mapped to
the specific bean definition parser (dateformat in this case). In other words, the BeanDefinitionParser is
responsible for parsing one distinct top-level XML element defined in the schema. In the parser, we' have access to the
XML element (and thus to its subelements, too) so that we can parse our custom XML content, as you can see in the
following example:
如果一个 BeanDefinitionParser 遇到一个映射到特定 bean 定义解析器(在这种情况下为 dateformat )的 XML 元素类型,则会使用
NamespaceHandler 。换句话说, BeanDefinitionParser 负责解析在模式中定义的一个特定的顶级 XML 元素。在解析器中,我们可以访问
XML 元素(以及其子元素),这样我们就可以解析我们的自定义 XML 内容,如下面的示例所示:
1
We use the Spring-provided AbstractSingleBeanDefinitionParser to handle a lot of the basic grunt work of creating a
single BeanDefinition.
我们使用 Spring 提供的 AbstractSingleBeanDefinitionParser 来处理很多 基本的单条 BeanDefinition 创建的苦力工作
2
We supply the AbstractSingleBeanDefinitionParser superclass with the type that our single BeanDefinition
represents.
我们为 AbstractSingleBeanDefinitionParser 超类提供我们的类型 单 BeanDefinition 表示。
1
We use the Spring-provided AbstractSingleBeanDefinitionParser to handle a lot of the basic grunt work of creating a
single BeanDefinition.
2
We supply the AbstractSingleBeanDefinitionParser superclass with the type that our single BeanDefinition represents.
In this simple case, this is all that we need to do. The creation of our single BeanDefinition is handled by the
AbstractSingleBeanDefinitionParser superclass, as is the extraction and setting of the bean definition’s unique
identifier.
在这种情况下,我们只需要做这些。我们的单个 BeanDefinition 的创建由 AbstractSingleBeanDefinitionParser 超类处理,同样还有提取和设置
bean 定义的唯一标识符。
10.2.4. 注册处理程序和模式
The coding is finished. All that remains to be done is to make the Spring XML parsing infrastructure aware of our custom
element. We do so by registering our custom namespaceHandler and custom XSD file in two special-purpose properties
files. These properties files are both placed in a META-INF directory in your application and can, for example, be
distributed alongside your binary classes in a JAR file.
编码已完成。剩下要做的就是让 Spring XML 解析基础设施知道我们的自定义元素。我们通过在两个专用属性文件中注册我们的自定义
namespaceHandler 和自定义 XSD 文件来实现这一点。这两个属性文件都放在您的应用程序的 META-INF 目录中,例如,可以与您的二进制类一起打包在
JAR 文件中。
The Spring XML parsing infrastructure automatically picks up your new extension by consuming these special properties
files, the formats of which are detailed in the next two sections.
Spring XML 解析基础设施会自动通过消费这些特殊属性文件来识别您的新扩展,这些文件的格式在下一两节中详细说明。
META-INF/spring.handlers 编写META-INF/spring.handlersThe properties file called spring.handlers contains a mapping of XML Schema URIs to namespace handler classes. For our
example, we need to write the following:
The properties file called spring.handlers contains a mapping of XML Schema URIs to namespace handler classes. For our
example, we need to write the following: 属性文件spring.handlers包含 XML Schema URIs 到命名空间处理类的映射。对于我们的示例,我们需要编写以下内容:
http\://www.mycompany.example/schema/myns=org.springframework.samples.xml.MyNamespaceHandler
(The : character is a valid delimiter in the Java properties format, so : character in the URI needs to be escaped
with a backslash.)
( : 字符在 Java 属性格式中是一个有效的分隔符,因此 URI 中的 : 字符需要用反斜杠转义。)
The first part (the key) of the key-value pair is the URI associated with your custom namespace extension and needs to
exactly match exactly the value of the targetNamespace attribute, as specified in your custom XSD schema.
键值对的第一部分(键)是与您的自定义命名空间扩展关联的 URI,需要与自定义 XSD 模式中指定的 targetNamespace 属性的值完全匹配。
编写 'META-INF/spring.schemas'
The properties file called spring.schemas contains a mapping of XML Schema locations (referred to, along with the
schema declaration, in XML files that use the schema as part of the xsi:schemaLocation attribute) to classpath
resources. This file is needed to prevent Spring from absolutely having to use a default EntityResolver that requires
Internet access to retrieve the schema file. If you specify the mapping in this properties file, Spring searches for the
schema (in this case, myns.xsd in the org.springframework.samples.xml package) on the classpath. The following
snippet shows the line we need to add for our custom schema:
属性文件名为 spring.schemas ,其中包含 XML 模式位置(在 XML 文件中,与模式声明一起,作为 xsi:schemaLocation
属性的组成部分)到类路径资源的映射。此文件需要防止 Spring 绝对必须使用需要通过互联网访问来检索模式文件的默认
EntityResolver 。如果您在此属性文件中指定映射,Spring 将在类路径上搜索模式(在这种情况下, myns.xsd 位于
org.springframework.samples.xml 包中)。以下代码片段显示了我们需要添加的自定义模式行:
http\://www.mycompany.example/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
(Remember that the : character must be escaped.)
(请记住, : 字符必须进行转义。)
You are encouraged to deploy your XSD file (or files) right alongside the NamespaceHandler and BeanDefinitionParser
classes on the classpath.
鼓励您将您的 XSD 文件(或文件)直接部署在与 NamespaceHandler 和 BeanDefinitionParser 类相同的类路径上。
10.2.5. 在您的 Spring XML 配置中使用自定义扩展
Using a custom extension that you yourself have implemented is no different from using one of the “custom” extensions
that Spring provides. The following example uses the custom <dateformat/> element developed in the previous steps in a
Spring XML configuration file:
使用你自己实现的自定义扩展与使用 Spring 提供的“自定义”扩展没有区别。以下示例使用在前面步骤中开发的自定义 <dateformat/>
元素在 Spring XML 配置文件中:
1
Our custom bean. 我们的定制豆。
10.2.6. 更详细的示例
This section presents some more detailed examples of custom XML extensions.
本节展示了更多自定义 XML 扩展的详细示例。
嵌套自定义元素在内置元素中
The example presented in this section shows how you to write the various artifacts required to satisfy a target of the
following configuration:
本节中提供的示例展示了如何编写满足以下配置目标的各种工件:
The preceding configuration nests custom extensions within each other. The class that is actually configured by the
<foo:component/> element is the Component class (shown in the next example). Notice how the Component class does
not expose a setter method for the components property. This makes it hard (or rather impossible) to configure a bean
definition for the Component class by using setter injection. The following listing shows the Component class:
前一个配置将自定义扩展嵌套在彼此之中。实际由 <foo:component/> 元素配置的类是 Component 类(如下一个示例所示)。注意
Component 类没有为 components 属性提供 setter 方法。这使得通过 setter 注入配置 Component 类的 bean
定义变得困难(或者更确切地说,是不可能的)。以下列表显示了 Component 类:
The typical solution to this issue is to create a custom FactoryBean that exposes a setter property for the
components property. The following listing shows such a custom FactoryBean:
该问题的典型解决方案是创建一个自定义的 FactoryBean ,该自定义 FactoryBean 公开了 components 属性的 setter
属性。以下列表显示了这样的自定义 FactoryBean :
This works nicely, but it exposes a lot of Spring plumbing to the end user. What we are going to do is write a custom
extension that hides away all of this Spring plumbing. If we stick
to the steps described previously, we start off by creating the XSD schema to define the
structure of our custom tag, as the following listing shows:
这工作得很好,但它将大量的 Spring 内部结构暴露给了最终用户。我们将要做的是编写一个自定义扩展,隐藏掉所有的这些 Spring
内部结构。如果我们坚持之前描述的步骤,我们首先会创建一个 XSD 模式来定义我们自定义标签的结构,如下所示:
Again following the process described earlier, we then create a custom NamespaceHandler:
再次遵循前面描述的过程,我们随后创建一个自定义的 NamespaceHandler :
Next up is the custom BeanDefinitionParser. Remember that we are creating a BeanDefinition that describes a
ComponentFactoryBean. The following listing shows our custom BeanDefinitionParser implementation:
接下来是自定义 BeanDefinitionParser 。记住,我们正在创建一个 BeanDefinition 来描述一个 ComponentFactoryBean
。以下列表展示了我们的自定义 BeanDefinitionParser 实现:
Finally, the various artifacts need to be registered with the Spring XML infrastructure, by modifying the
META-INF/spring.handlers and META-INF/spring.schemas files, as follows:
最后,需要将各种工件注册到 Spring XML 基础设施中,通过修改 META-INF/spring.handlers 和 META-INF/spring.schemas
文件,如下所示:
# in 'META-INF/spring.handlers' http\://www.foo.example/schema/component=com.foo.ComponentNamespaceHandler
# in 'META-INF/spring.schemas' http\://www.foo.example/schema/component/component.xsd=com/foo/component.xsd
自定义“常规”元素的属性
Writing your own custom parser and the associated artifacts is not hard. However, it is sometimes not the right thing to
do. Consider a scenario where you need to add metadata to already existing bean definitions.
编写自己的自定义解析器和相关工件并不难。然而,有时这样做可能并不正确。考虑这样一个场景,你需要向已经存在的 bean
定义中添加元数据。
In this case, you certainly do not want to have to write your own entire custom extension. Rather, you merely want to
add an additional attribute to the existing bean definition element.
在这种情况下,你当然不希望不得不编写自己的整个自定义扩展。相反,你只想向现有的 bean 定义元素添加一个额外的属性。
By way of another example, suppose that you define a bean definition for a service object that (unknown to it) accesses
a clustered JCache, and you want to ensure that the named JCache instance is
eagerly started within the surrounding cluster. The following listing shows such a definition:
通过另一个例子,假设您定义了一个服务对象的 bean 定义,该对象(它自己并不知道)访问一个集群化的 JCache,并且您想确保在周围的集群中,名为
JCache 的实例被积极启动。以下列表显示了这样的定义:
We can then create another BeanDefinition when the 'jcache:cache-name' attribute is parsed. This BeanDefinition
then initializes the named JCache for us. We can also modify the existing BeanDefinition for the
'checkingAccountService' so that it has a dependency on this new JCache-initializing BeanDefinition. The following
listing shows our JCacheInitializer:
我们可以在解析 'jcache:cache-name' 属性时创建另一个 BeanDefinition 。然后,这个 BeanDefinition 为我们初始化命名
JCache。我们还可以修改现有的 BeanDefinition 以使它依赖于这个新的初始化 JCache 的 BeanDefinition 。以下列表显示了我们的
JCacheInitializer :
Now we can move onto the custom extension. First, we need to author the XSD schema that describes the custom attribute,
as follows:
现在我们可以继续到自定义扩展。首先,我们需要编写描述自定义属性的 XSD 模式,如下所示:
Next, we need to create the associated NamespaceHandler, as follows:
接下来,我们需要创建相关的 NamespaceHandler ,如下所示:
Next, we need to create the parser. Note that, in this case, because we are going to parse an XML attribute, we write a
BeanDefinitionDecorator rather than a BeanDefinitionParser. The following listing shows our
BeanDefinitionDecorator implementation:
接下来,我们需要创建解析器。注意,在这种情况下,因为我们将要解析一个 XML 属性,所以我们写的是 BeanDefinitionDecorator 而不是
BeanDefinitionParser 。下面的列表显示了我们的 BeanDefinitionDecorator 实现:
Finally, we need to register the various artifacts with the Spring XML infrastructure by modifying the
META-INF/spring.handlers and META-INF/spring.schemas files, as follows:
最后,我们需要通过修改 META-INF/spring.handlers 和 META-INF/spring.schemas 文件,将各种工件注册到 Spring XML
基础设施中,如下所示:
# in 'META-INF/spring.handlers' http\://www.foo.example/schema/jcache=com.foo.JCacheNamespaceHandler
# in 'META-INF/spring.schemas' http\://www.foo.example/schema/jcache/jcache.xsd=com/foo/jcache.xsd
10.3. 应用启动步骤
This part of the appendix lists the existing StartupSteps that the core container is instrumented with.
此附录部分列出了核心容器所使用的现有 StartupSteps 。
The name and detailed information about each startup step is not part of the public contract and is subject to change;
this is considered as an implementation detail of the core container and will follow its behavior changes.
每个启动步骤的名称和详细信息不属于公共合同,且可能发生变化;这被视为核心容器的实现细节,并将遵循其行为变化。
Table 15. Application startup steps defined in the core container
表 15. 核心容器中定义的应用启动步骤
Name 姓名
Description 描述
Tags 标签
spring.beans.instantiate
Instantiation of a bean and its dependencies.
实例化一个 bean 及其依赖项。
beanName the name of the bean, beanType the type required at the injection point.
beanName 豆子的名称, beanType 注入点所需的数据类型。
spring.beans.smart-initialize
Initialization of SmartInitializingSingleton beans.
初始化 SmartInitializingSingleton 豆子。
beanName the name of the bean.
beanName 豆子的名称。
spring.context.annotated-bean-reader.create
Creation of the AnnotatedBeanDefinitionReader.
创建 AnnotatedBeanDefinitionReader 。
spring.context.base-packages.scan
Scanning of base packages.
扫描基本包。
packages array of base packages for scanning.
packages 扫描的基础包数组。
spring.context.beans.post-process
Beans post-processing phase.
豆类后处理阶段。
spring.context.bean-factory.post-process
Invocation of the BeanFactoryPostProcessor beans.
调用 BeanFactoryPostProcessor beans。
postProcessor the current post-processor.
postProcessor 当前后处理器。
spring.context.beandef-registry.post-process
Invocation of the BeanDefinitionRegistryPostProcessor beans.
调用 BeanDefinitionRegistryPostProcessor beans。
postProcessor the current post-processor.
postProcessor 当前后处理器。
spring.context.component-classes.register
Registration of component classes through AnnotationConfigApplicationContext#register.
组件类通过 AnnotationConfigApplicationContext#register 进行注册
classes array of given classes for registration.
classes 注册的给定类数组。
spring.context.config-classes.enhance
Enhancement of configuration classes with CGLIB proxies.
增强配置类使用 CGLIB 代理。
classCount count of enhanced classes.
classCount 增强类计数
spring.context.config-classes.parse
Configuration classes parsing phase with the ConfigurationClassPostProcessor.
配置类解析阶段与 ConfigurationClassPostProcessor 。
classCount count of processed classes.
classCount 处理过的类计数。
spring.context.refresh
Application context refresh phase.
应用上下文刷新阶段。