文章作者:Tyan
博客:noahsnail.com | CSDN | 简书
3.8 Container Extension Points
Typically, an application developer does not need to subclass ApplicationContext
implementation classes. Instead, the Spring IoC container can be extended by plugging in implementations of special integration interfaces. The next few sections describe these integration interfaces.
通常情况下,应用开发者不需要继承ApplicationContext
的实现类。反而是Spring的IoC容器可以通过插入特定集成接口的实现来进行扩展。下面几节将描述这些集成接口。
3.8.1 Customizing beans using a BeanPostProcessor
The BeanPostProcessor
interface defines callback methods that you can implement to provide your own (or override the container’s default) instantiation logic, dependency-resolution logic, and so forth. If you want to implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, you can plug in one or more BeanPostProcessor
implementations.
BeanPostProcessor
接口定义了回调方法,你可以实现这个方法来提供你自己的(或覆盖容器默认的)实例化逻辑,依赖解析逻辑等等。如果你想在Spring容器完成实例化,配置和初始化bean之后实现一些定制的业务逻辑,你可以插入一个或多个BeanPostProcessor
实现。
You can configure multiple BeanPostProcessor
instances, and you can control the order in which these BeanPostProcessors
execute by setting the order
property. You can set this property only if the BeanPostProcessor
implements the Ordered
interface; if you write your own BeanPostProcessor
you should consider implementing the Ordered
interface too. For further details, consult the javadocs of the BeanPostProcessor
and Ordered
interfaces. See also the note below on programmatic registration of BeanPostProcessors
.
你可以配置多个BeanPostProcessor
实例,通过设置order
属性你可以控制BeanPostProcessors
的执行顺序。只有BeanPostProcessor
实现了Ordered
接口时你才可以设置这个属性;如果你编写了你自己的BeanPostProcessor
,你也应该考虑实现Ordered
接口。更多细节请参考BeanPostProcessor
接口和Ordered
接口的Java文档。也可以查看下面的BeanPostProcessors
编程注册的笔记。
BeanPostProcessors
operate on bean (or object) instances; that is to say, the Spring IoC container instantiates a bean instance and thenBeanPostProcessors
do their work.
BeanPostProcessors
are scoped per-container. This is only relevant if you are using container hierarchies. If you define aBeanPostProcessor
in one container, it will only post-process the beans in that container. In other words, beans that are defined in one container are not post-processed by aBeanPostProcessor
defined in another container, even if both containers are part of the same hierarchy.
To change the actual bean definition (i.e., the blueprint that defines the bean), you instead need to use a
BeanFactoryPostProcessor
as described in Section 3.8.2, “Customizing configuration metadata with a BeanFactoryPostProcessor”.
BeanPostProcessors
操作一个bean(或对象)实例;也就是说,Spring Ioc容器实例化一个bean实例,然后BeanPostProcessors
完成它们的工作。
BeanPostProcessors
的作用域是每个容器。只有你在使用容器分层的情况下,这才是相关的。如果你在一个容器中定义了一个BeanPostProcessor
,它将只后处理容器中的beans。换句话说,某个容器中定义的beans不能被另一个容器中定义的BeanPostProcessor
进行后处理,即使这两个容器是同一层上的一部分。
为了改变实际的bean定义(例如,定义bean的蓝图),你可以使用3.8.2小节中描述的
BeanFactoryPostProcessor
。
The org.springframework.beans.factory.config.BeanPostProcessor
interface consists of exactly two callback methods. When such a class is registered as a post-processor with the container, for each bean instance that is created by the container, the post-processor gets a callback from the container both before container initialization methods (such as InitializingBean’s afterPropertiesSet() and any declared init method) are called as well as after any bean initialization callbacks. The post-processor can take any action with the bean instance, including ignoring the callback completely. A bean post-processor typically checks for callback interfaces or may wrap a bean with a proxy. Some Spring AOP infrastructure classes are implemented as bean post-processors in order to provide proxy-wrapping logic.
org.springframework.beans.factory.config.BeanPostProcessor
接口包含恰好两个回调方法。当这样一个类在容器中注册为后处理器时,对于容器中创建的每一个bean实例,在容器初始化方法(例如InitializingBean
的afterPropertiesSet()
方法和任何已声明的初始化方法)被调用之前和任何bean初始化回调函数之后,后处理器会从容器中得到一个回调函数。后处理器可以对bean实例进行任何操作,包括完全忽略回调方法。bean后处理器通常检查回调接口或将bean包裹到代理中。为了提供代理包裹逻辑,一些Spring AOP基础结构类被实现为bean后处理器。
An ApplicationContext
automatically detects any beans that are defined in the configuration metadata which implement the BeanPostProcessor
interface. The ApplicationContext
registers these beans as post-processors so that they can be called later upon bean creation. Bean post-processors can be deployed in the container just like any other beans.
ApplicationContext
会自动检测任何配置元数据中定义的实现了BeanPostProcessor
接口的bean。为了能在后面bean创建时调用这些bean,ApplicationContext
会将这些bean注册为后处理器。bean后处理器可以像其它bean一样在容器进行部署。
Note that when declaring a BeanPostProcessor
using an @Bean
factory method on a configuration class, the return type of the factory method should be the implementation class itself or at least the org.springframework.beans.factory.config.BeanPostProcessor
interface, clearly indicating the post-processor nature of that bean. Otherwise, the ApplicationContext
won’t be able to autodetect it by type before fully creating it. Since a BeanPostProcessor
needs to be instantiated early in order to apply to the initialization of other beans in the context, this early type detection is critical.
注意当在一个配置类上使用@Bean
声明一个BeanPostProcessor
时,工厂方法的返回值应该是实现类本身或是org.springframework.beans.factory.config.BeanPostProcessor
接口,这能清晰的表明bean的后处理器特性。此外,在完整的创建它之前,ApplicationContext
不能通过类型自动检测它。由于BeanPostProcessor
需要早一点实例化,为了在上下文中初始化其它的beans,早期的类型检测是非常关键的。
While the recommended approach for
BeanPostProcessor
registration is throughApplicationContext
auto-detection (as described above), it is also possible to register them programmatically against aConfigurableBeanFactory
using theaddBeanPostProcessor
method. This can be useful when needing to evaluate conditional logic before registration, or even for copying bean post processors across contexts in a hierarchy. Note however thatBeanPostProcessors
added programmatically do not respect theOrdered
interface. Here it is the order of registration that dictates the order of execution. Note also thatBeanPostProcessors
registered programmatically are always processed before those registered through auto-detection, regardless of any explicit ordering.
虽然推荐的注册
BeanPostProcessor
的方法是通过ApplicationContext
自动检测(像前面描述的那样),但也可以通过以编程方法通过使用ConfigurableBeanFactory
的addBeanPostProcessor
方法来注册。在注册之前需要评估条件逻辑时,这是非常有用的,或者通过分层中的上下文来复制bean后处理器。注意以编程方式添加的BeanPostProcessors
不需要Ordered
接口。这种情况下注册顺序意味着执行顺序。注意以编程方式注册的BeanPostProcessors
中是在那些通过自动检测注册的BeanPostProcessors
之前进行处理,不管任何显式的顺序指定。
Classes that implement the
BeanPostProcessor
interface are special and are treated differently by the container. AllBeanPostProcessors
and beans that they reference directly are instantiated on startup, as part of the special startup phase of theApplicationContext
. Next, allBeanPostProcessors
are registered in a sorted fashion and applied to all further beans in the container. Because AOP auto-proxying is implemented as aBeanPostProcessor
itself, neitherBeanPostProcessors
nor the beans they reference directly are eligible for auto-proxying, and thus do not have aspects woven into them.
For any such bean, you should see an informational log message: "Bean foo is not eligible for getting processed by all
BeanPostProcessor
interfaces (for example: not eligible for auto-proxying)".
Note that if you have beans wired into your
BeanPostProcessor
using autowiring or@Resource
(which may fall back to autowiring), Spring might access unexpected beans when searching for type-matching dependency candidates, and therefore make them ineligible for auto-proxying or other kinds of bean post-processing. For example, if you have a dependency annotated with@Resource
where thefield/setter
name does not directly correspond to the declared name of a bean and no name attribute is used, then Spring will access other beans for matching them by type.
实现
BeanPostProcessor
接口的类是特别的并被容器不同对待。所有的BeanPostProcessors
和它们直接引用的beans在启动时进行实例化,它们是ApplicationContext
特定启动阶段的一部分。接下来,所有BeanPostProcessors
以有序形式进行注册,并适用于容器中所有更进一步的beans。由于AOP自动代理是作为BeanPostProcessor
本身实现的,既不是BeanPostProcessors
也不是它们直接引用的beans适合进行自动代理,因此没有融入它们的方面。
对于这样的bean,你应该看到一个信息日志消息:"Bean foo没资格被所有的
BeanPostProcessor
接口进行处理(例如,不适合自动代理)。"。
注意如果有beans使用自动装配或
@Resource
(可能回到自动装配)注入你的BeanPostProcessor
,当搜索类型匹配的依赖候选者时,Spring可能访问未预料到beans,因此使它们不适合自动代理或其他类型的进行后处理的bean。例如,如果你有一个带有@Resource
注解的依赖,field/setter
名称不能直接对应bean声明的名字,也没有使用name特性,Spring将通过类型匹配来访问其它的bean。
The following examples show how to write, register, and use BeanPostProcessors
in an ApplicationContext
.
下面的例子展示了在ApplicationContext
中如何编写,注册和使用BeanPostProcessors
。
Example: Hello World, BeanPostProcessor-style
This first example illustrates basic usage. The example shows a custom BeanPostProcessor
implementation that invokes the toString()
method of each bean as it is created by the container and prints the resulting string to the system console.
第一个例子阐述了基本用法。这个例子展示了一个定制BeanPostProcessor
实现,实现中调用了每一个bean的toString()
方法。当容器创建它时,会将结果字符串输出到系统控制台。
Find below the custom BeanPostProcessor
implementation class definition:
下面是定制BeanPostProcessor
实现的类定义:
package scripting;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
// simply return the instantiated bean as-is
public Object postProcessBeforeInitialization(Object bean,
String beanName) throws BeansException {
return bean; // we could potentially return any object reference here...
}
public Object postProcessAfterInitialization(Object bean,
String beanName) throws BeansException {
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.xsd">
<lang:groovy id="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
<lang:property name="message" value="Fiona Apple Is Just So Dreamy."/>
</lang:groovy>
<!--
when the above bean (messenger) is instantiated, this custom
BeanPostProcessor implementation will output the fact to the system console
-->
<bean class="scripting.InstantiationTracingBeanPostProcessor"/>
</beans>
Notice how the InstantiationTracingBeanPostProcessor
is simply defined. It does not even have a name, and because it is a bean it can be dependency-injected just like any other bean. (The preceding configuration also defines a bean that is backed by a Groovy script. The Spring dynamic language support is detailed in the chapter entitled Chapter 31, Dynamic language support.)
注意InstantiationTracingBeanPostProcessor
是怎样简单定义的。它甚至没有一个名字,因为它是一个bean,它能像其它bean一样进行依赖注入。(前面的配置也定义了一个bean,它被Groovy脚本支持。Spring动态语言支持在31章『动态语言支持』中进行了详细描述。)
The following simple Java application executes the preceding code and configuration:
下面的简单Java应用执行了前面的代码和配置:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scripting.Messenger;
public final class Boot {
public static void main(final String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
Messenger messenger = (Messenger) ctx.getBean("messenger");
System.out.println(messenger);
}
}
The output of the preceding application resembles the following:
前面的应用输出结果如下:
Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961
Example: The RequiredAnnotationBeanPostProcessor
Using callback interfaces or annotations in conjunction with a custom BeanPostProcessor
implementation is a common means of extending the Spring IoC container. An example is Spring’s RequiredAnnotationBeanPostProcessor
- a BeanPostProcessor
implementation that ships with the Spring distribution which ensures that JavaBean
properties on beans that are marked with an (arbitrary) annotation are actually (configured to be) dependency-injected with a value.
使用回调函数接口或注解结合定制BeanPostProcessor
实现是扩展Spring IoC容器的常见方法。一个例子是Spring的RequiredAnnotationBeanPostProcessor
——一个BeanPostProcessor
实现附带在Spring发行中,它保证了标记有(任意)注解的beans上的JavaBean
属性能真正(配置成)通过值进行依赖注入。
3.8.2 Customizing configuration metadata with a BeanFactoryPostProcessor
The next extension point that we will look at is the org.springframework.beans.factory.config.BeanFactoryPostProcessor
. The semantics of this interface are similar to those of the BeanPostProcessor
, with one major difference: BeanFactoryPostProcessor
operates on the bean configuration metadata; that is, the Spring IoC container allows a BeanFactoryPostProcessor
to read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessors
.
接下来我们要看到的扩展点是org.springframework.beans.factory.config.BeanFactoryPostProcessor
。这个接口的语义与那些BeanPostProcessor
类似,但有一个主要的不同:BeanFactoryPostProcessor
可以操作配置元数据;也就是说,Spring IoC容器允许在容器实例化除了BeanFactoryPostProcessor
之外的任何beans之前,BeanFactoryPostProcessor
读取配置元数据并可能修改它们。
You can configure multiple BeanFactoryPostProcessors
, and you can control the order in which these BeanFactoryPostProcessors
execute by setting the order
property. However, you can only set this property if the BeanFactoryPostProcessor
implements the Ordered
interface. If you write your own BeanFactoryPostProcessor
, you should consider implementing the Ordered
interface too. Consult the javadocs of the BeanFactoryPostProcessor
and Ordered
interfaces for more details.
你可以配置多个BeanFactoryPostProcessors
,你可以通过设置order
属性来控制这些BeanFactoryPostProcessors
的执行顺序。但是,只有BeanFactoryPostProcessor
实现了Ordered
接口时你才可以设置这个属性。如果你编写了你自己的BeanFactoryPostProcessor
,你也应该考虑实现Ordered
接口。关于BeanFactoryPostProcessor
和Ordered
的更多细节请看文档。
If you want to change the actual bean instances (i.e., the objects that are created from the configuration metadata), then you instead need to use a
BeanPostProcessor
(described above in Section 3.8.1, “Customizing beans using a BeanPostProcessor”). While it is technically possible to work with bean instances within aBeanFactoryPostProcessor
(e.g., usingBeanFactory.getBean()
), doing so causes premature bean instantiation, violating the standard container lifecycle. This may cause negative side effects such as bypassing bean post processing.
Also,
BeanFactoryPostProcessors
are scoped per-container. This is only relevant if you are using container hierarchies. If you define aBeanFactoryPostProcessor
in one container, it will only be applied to the bean definitions in that container. Bean definitions in one container will not be post-processed byBeanFactoryPostProcessors
in another container, even if both containers are part of the same hierarchy.
如果你想改变真正的bean实例(例如,从配置元数据中创建的对象),你应该需要使用
BeanPostProcessor
(3.8.1小节中描述的)。尽管在BeanFactoryPostProcessor
中处理bean实例在技术上是可能的(例如使用BeanFactory.getBean()
),但这样做会引起过早的bean实例化,违背标准的容器生命周期。这可能会产生负面影响例如绕过bean后处理。
BeanFactoryPostProcessors
的作用域也是在每个容器中。这仅对于容器分层而言。如果在一个容器中你定义了一个BeanFactoryPostProcessor
,它将适用于那个容器中的bean定义。一个容器中的bean定义不能被另一个容器中的BeanFactoryPostProcessors
进行后处理,即使两个容器是在同一个分层中。
A bean factory post-processor is executed automatically when it is declared inside an ApplicationContext
, in order to apply changes to the configuration metadata that define the container. Spring includes a number of predefined bean factory post-processors, such as PropertyOverrideConfigurer
and PropertyPlaceholderConfigurer
. A custom BeanFactoryPostProcessor
can also be used, for example, to register custom property editors.
为了修改定义在容器中的配置元数据,当一个bean工厂后处理器在ApplicationContext
中声明时,它会自动执行。Spring包含许多预先定义的bean工厂后处理器,例如PropertyOverrideConfigurer
和PropertyPlaceholderConfigurer
。定制的BeanFactoryPostProcessor
也可以使用,例如,为了注册定制的属性编辑器。
An ApplicationContext
automatically detects any beans that are deployed into it that implement the BeanFactoryPostProcessor
interface. It uses these beans as bean factory post-processors, at the appropriate time. You can deploy these post-processor beans as you would any other bean.
ApplicationContext
会自动检测任何部署在它之内的实现了BeanFactoryPostProcessor
接口的bean。在合适的时间,它会使用这些beans作为bean工厂后处理器。你可以像任何你使用的bean那样部署这些后处理器beans。
As with
BeanPostProcessors
, you typically do not want to configureBeanFactoryPostProcessors
for lazy initialization. If no other bean references aBean(Factory)PostProcessor
, that post-processor will not get instantiated at all. Thus, marking it for lazy initialization will be ignored, and theBean(Factory)PostProcessor
will be instantiated eagerly even if you set the default-lazy-init attribute totrue
on the declaration of your<beans/>
element.
关于
BeanPostProcessors
, 通常情况下你不想配置BeanFactoryPostProcessors
为延迟初始化。 如果没有别的bean引用Bean(Factory)PostProcessor
,后处理器将不会实例化。因此,对它进行延迟初始化会被忽略,即使你将<beans/>
元素中的default-lazy-init
特性设置为true
,Bean(Factory)PostProcessor
也会急切的初始化。
Example: the Class name substitution PropertyPlaceholderConfigurer
You use the PropertyPlaceholderConfigurer
to externalize property values from a bean definition in a separate file using the standard Java Properties
format. Doing so enables the person deploying an application to customize environment-specific properties such as database URLs and passwords, without the complexity or risk of modifying the main XML definition file or files for the container.
你可以使用PropertyPlaceholderConfigurer
读取单独文件中的bean定义来使属性具体化,这个单独文件使用标准的Java Properties
格式。这样做可以在部署应用时定制特定环境属性例如数据库URLs和密码,没有复杂性或修改主XML定义文件及容器相关文件的风险。
Consider the following XML-based configuration metadata fragment, where a DataSource
with placeholder values is defined. The example shows properties configured from an external Properties
file. At runtime, a PropertyPlaceholderConfigurer
is applied to the metadata that will replace some properties of the DataSource
. The values to replace are specified as placeholders of the form ${property-name}
which follows the Ant/log4j/JSP EL style.
考虑一下下面的基于XML定义的配置元数据片段,其中定义了一个带有占位符的DataSource
。这个例子展示了从外部Properties
文件进行属性配置。在运行时,PropertyPlaceholderConfigurer
会应用到元数据中,将会替换DataSource
中的一些属性。通过${property-name}
形式的占位符指定要替换的值,这遵循了Ant/log4j/JSP EL风格。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The actual values come from another file in the standard Java Properties
format:
真正的属性值来自于另一个以标准Java Properties
形式编写的文件:
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
Therefore, the string ${jdbc.username}
is replaced at runtime with the value 'sa', and the same applies for other placeholder values that match keys in the properties file. The PropertyPlaceholderConfigurer
checks for placeholders in most properties and attributes of a bean definition. Furthermore, the placeholder prefix and suffix can be customized.
因此,在运行是字符串${jdbc.username}
被替换为sa
,其它的匹配属性文件中的key的占位符的值以同样方式替换。PropertyPlaceholderConfigurer
会检查bean中大多数属性和特性的占位符。此外,占位符的前缀和后缀都可以定制。
With the context namespace introduced in Spring 2.5, it is possible to configure property placeholders with a dedicated configuration element. One or more locations can be provided as a comma-separated list in the location
attribute.
Spring 2.5中引入了上下文命名空间,可以通过专用配置元素配置属性占位符。在location
特性可以提供一个或多个位置,多个位置用逗号分开。
<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>
The PropertyPlaceholderConfigurer
not only looks for properties in the Properties
file you specify. By default it also checks against the Java System
properties if it cannot find a property in the specified properties files. You can customize this behavior by setting the systemPropertiesMode
property of the configurer with one of the following three supported integer values:
never (0): Never check system properties
fallback (1): Check system properties if not resolvable in the specified properties files. This is the default.
override (2): Check system properties first, before trying the specified properties files. This allows system properties to override any other property source.
PropertyPlaceholderConfigurer
不仅仅查找指定Properties
文件中的属性。默认情况下,如果不能在指定属性文件中找到属性,它也检查Java System
属性。你可以通过下面三个支持的整数值中的一个设置配置器的systemPropertiesMode
属性,从而定制查找行为。
never (0): 从不检查
system
属性fallback (1): 如果不能在指定文件中解析属性,检查
system
属性,这是默认值。override (2): 在查找指定文件之前,首先检查
system
属性,这可以使系统属性覆盖任何其它属性源。
Consult the PropertyPlaceholderConfigurer
javadocs for more information.
更多信息请看PropertyPlaceholderConfigurer
文档。
You can use the
PropertyPlaceholderConfigurer
to substitute class names, which is sometimes useful when you have to pick a particular implementation class at runtime. For example:
你可以
PropertyPlaceholderConfigurer
替换类名,有时候非常有用,特别是运行时你必须选择一个特别的实现类的情况下。例如:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:com/foo/strategy.properties</value>
</property>
<property name="properties">
<value>custom.strategy.class=com.foo.DefaultStrategy</value>
</property>
</bean>
<bean id="serviceStrategy" class="${custom.strategy.class}"/>
If the class cannot be resolved at runtime to a valid class, resolution of the bean fails when it is about to be created, which is during the
preInstantiateSingletons()
phase of anApplicationContext
for a non-lazy-init bean.
如果这个类不能在运行时解析成一个有效类,对于一个非懒惰初始化的bean,当它要创建时,在
ApplicationContext
的preInstantiateSingletons()
期间,bean会解析失败。
Example: the PropertyOverrideConfigurer
The PropertyOverrideConfigurer
, another bean factory post-processor, resembles the PropertyPlaceholderConfigurer
, but unlike the latter, the original definitions can have default values or no values at all for bean properties. If an overriding Properties
file does not have an entry for a certain bean property, the default context definition is used.
PropertyOverrideConfigurer
,另一个bean工厂后处理器,类似于PropertyPlaceholderConfigurer
,但不像后者,最初的定义可以有默认值或bean属性一点也没有值。如果一个覆写的Properties
文件对于某个bean属性没有任何输入,会使用默认的上下文定义。
Note that the bean definition is not aware of being overridden, so it is not immediately obvious from the XML definition file that the override configurer is being used. In case of multiple PropertyOverrideConfigurer
instances that define different values for the same bean property, the last one wins, due to the overriding mechanism.
注意bean定义没有意识到被覆写了,因此从XML定义文件中它不能立刻很明显的看出在使用覆写的配置器。为了防止多个PropertyOverrideConfigurer
实例对于同一个bean属性定义不同的值,根据覆写机制,使用最后一个定义的值。
Properties file configuration lines take this format:
属性文件配置形式如下:
beanName.property=value
For example:
例如:
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb
This example file can be used with a container definition that contains a bean called dataSource
, which has driver
and url
properties.
例子文件可以被包含名为dataSource
bean的容器定义使用,它有一个driver
和url
属性。
Compound property names are also supported, as long as every component of the path except the final property being overridden is already non-null (presumably initialized by the constructors). In this example…
混合属性命名也支持,除了最后被覆写的属性,只要路径的每部分都已经是非空(假设构造函数进行初始化)。在这个例子中:
foo.fred.bob.sammy=123
the sammy
property of the bob
property of the fred
property of the foo
bean is set to the scalar value 123
.
foo
bean中的fred
属性的bob
属性的sammy
属性设为标量值123
。
Specified override values are always literal values; they are not translated into bean references. This convention also applies when the original value in the XML bean definition specifies a bean reference.
指定的覆写值总是字面值;它们不能转成bean引用。当XML bean定义中的初始值指定了一个bean引用时,这个规范同样有效。
With the context namespace introduced in Spring 2.5, it is possible to configure property overriding with a dedicated configuration element:
Spring 2.5引入了上下文命名空间,可以用专用配置元素配置属性覆写:
<context:property-override location="classpath:override.properties"/>
3.8.3 Customizing instantiation logic with a FactoryBean
Implement the org.springframework.beans.factory.FactoryBean
interface for objects that are themselves factories.
为对象实现org.springframework.beans.factory.FactoryBean
接口的是工厂本身。
The FactoryBean
interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean
, write the complex initialization inside that class, and then plug your custom FactoryBean
into the container.
FactoryBean
接口是Spring IoC的实例化逻辑可插入性的一个点。如果你有复杂的初始化代码,相比于大量的冗余的XML代码用Java语言来表达会更好,那么你可以创建你自己的FactoryBean
,在类里面编写复杂的初始化逻辑,并将你定制的FactoryBean
插入到容器中。
The FactoryBean
interface provides three methods:
Object getObject()
: returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.boolean isSingleton()
: returns true if this FactoryBean returns singletons, false otherwise.Class getObjectType()
: returns the object type returned by the getObject() method or null if the type is not known in advance.
FactoryBean
接口提供了三个方法:
Object getObject()
: 返回一个工厂创建的对象实例。这个实例可能被共享, 依赖于工厂是否返回一个单例或原型。boolean isSingleton()
: 如果FactoryBean
返回单例,返回true,否则返回false。Class getObjectType()
: 返回getObject()
方法返回的类型,如果类型不能提前知道则返回null。
The FactoryBean
concept and interface is used in a number of places within the Spring Framework; more than 50 implementations of the FactoryBean
interface ship with Spring itself.
FactoryBean
的概念和接口在Spring框架中的许多地方都使用了;Spring本身中有不止50个FactoryBean
接口的实现。
When you need to ask a container for an actual FactoryBean
instance itself instead of the bean it produces, preface the bean’s id with the ampersand symbol (&) when calling the getBean()
method of the ApplicationContext
. So for a given FactoryBean
with an id of myBean
, invoking getBean("myBean")
on the container returns the product of the FactoryBean
; whereas, invoking getBean("&myBean")
returns the FactoryBean
instance itself.
当你需要向容器请求一个真正的FactoryBean
实例本身来代替它产生的bean时,调用ApplicationContext
的getBean()
方法时,bean的id前面要加上一个$
符。因此给定一个id为myBean
的FactoryBean
,在容器中调用getBean("myBean")
,返回FactoryBean
的产品,但调用getBean("&myBean")
会返回FactoryBean
实例本身。