Container Extension Points

1.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容器。接下来的几节将描述这些集成接口。

1.8.1. Customizing Beans by 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 custom BeanPostProcessor implementations.

BeanPostProcessor接口定义了回调方法,您可以实现这些方法来提供自己的(或覆盖容器的默认)实例化逻辑、依赖解析逻辑,等等。如果您想在Spring容器完成bean的实例化、配置和初始化之后实现一些自定义逻辑,您可以插入一个或多个自定义BeanPostProcessor实现。

You can configure multiple BeanPostProcessor instances, and you can control the order in which these BeanPostProcessor instances run 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, see the javadoc of the BeanPostProcessor and Ordered interfaces. See also the note on programmatic registration of BeanPostProcessor instances.

您可以配置多个BeanPostProcessor实例,并且可以通过设置order属性来控制这些BeanPostProcessor实例的运行顺序。只有当BeanPostProcessor实现了Ordered接口时,才能设置此属性。如果您编写自己的BeanPostProcessor,也应该考虑实现Ordered接口。要了解更多的细节,请参阅BeanPostProcessor和Ordered接口的javadoc。另请参阅关于BeanPostProcessor实例编程注册的说明。

BeanPostProcessor instances operate on bean (or object) instances. That is, the Spring IoC container instantiates a bean instance and then BeanPostProcessor instances do their work.

BeanPostProcessor instances are scoped per-container. This is relevant only if you use container hierarchies. If you define a BeanPostProcessor in one container, it post-processes only the beans in that container. In other words, beans that are defined in one container are not post-processed by a BeanPostProcessor defined in another container, even if both containers are part of the same hierarchy.

To change the actual bean definition (that is, the blueprint that defines the bean), you instead need to use a BeanFactoryPostProcessor, as described in Customizing Configuration Metadata with a BeanFactoryPostProcessor.

BeanPostProcessor实例对bean(或对象)实例进行操作。也就是说,Spring IoC容器实例化一个bean实例,然后BeanPostProcessor实例执行它们的工作。

BeanPostProcessor实例的作用域是针对每个容器的。这只有在使用容器层次结构时才有用。如果在一个容器中定义BeanPostProcessor,它将只对该容器中的bean进行后处理。换句话说,在一个容器中定义的bean不会由在另一个容器中定义的BeanPostProcessor进行后处理,即使两个容器都属于相同的层次结构。

要更改实际的bean定义(即定义bean的蓝图),您需要使用BeanFactoryPostProcessor,如使用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.afterPropertiesSet() or any declared init method) are called, and 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 it 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.

beanpostprocessor接口由两个回调方法组成。当这样的类在容器中注册为后处理器时,对于容器创建的每个bean实例,在后处理器在调用容器初始化方法(如InitializingBean.afterPropertiesSet()或任何声明的初始化方法)之前和在任何bean初始化回调之后从容器获得回调。后处理器可以对bean实例执行任何操作,包括完全忽略回调。bean后处理器通常检查回调接口,或者它可以用代理包装bean。为了提供代理包装逻辑,一些Spring AOP基础结构类被实现为bean后处理器。

An ApplicationContext automatically detects any beans that are defined in the configuration metadata that 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 in the same fashion as any other beans.

ApplicationContext自动检测实现BeanPostProcessor接口的配置元数据中定义的任何bean。ApplicationContext将这些bean注册为后处理器,以便稍后在创建bean时调用它们。Bean后处理器可以像部署其他任何Bean一样部署在容器中。

Note that, when declaring a BeanPostProcessor by 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 cannot 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,以便应用于上下文中其他bean的初始化,因此这种早期类型检测是至关重要的。

Programmatically registering BeanPostProcessor instances

While the recommended approach for BeanPostProcessor registration is through ApplicationContext auto-detection (as described earlier), you can register them programmatically against a ConfigurableBeanFactory by using the addBeanPostProcessor method. This can be useful when you need to evaluate conditional logic before registration or even for copying bean post processors across contexts in a hierarchy. Note, however, that BeanPostProcessor instances added programmatically do not respect the Ordered interface. Here, it is the order of registration that dictates the order of execution. Note also that BeanPostProcessor instances registered programmatically are always processed before those registered through auto-detection, regardless of any explicit ordering.

以编程方式注册BeanPostProcessor实例

虽然推荐的BeanPostProcessor注册方法是通过ApplicationContext自动检测(如前所述),但是您可以通过使用addBeanPostProcessor方法以编程的方式针对ConfigurableBeanFactory注册它们。当您需要在注册前评估条件逻辑,甚至在层次结构中跨上下文复制bean post处理器时,这可能很有用。但是请注意,以编程方式添加的BeanPostProcessor实例不尊重Ordered接口。在这里,登记的顺序决定了执行的顺序。还要注意,无论如何,以编程方式注册的BeanPostProcessor实例总是在通过自动检测注册的实例之前处理任何显式的命令。

BeanPostProcessor instances and AOP auto-proxying

Classes that implement the BeanPostProcessor interface are special and are treated differently by the container. All BeanPostProcessor instances and beans that they directly reference are instantiated on startup, as part of the special startup phase of the ApplicationContext. Next, all BeanPostProcessor instances are registered in a sorted fashion and applied to all further beans in the container. Because AOP auto-proxying is implemented as a BeanPostProcessor itself, neither BeanPostProcessor instances nor the beans they directly reference 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 someBean is not eligible for getting processed by all BeanPostProcessor interfaces (for example: not eligible for auto-proxying).If you have beans wired into your BeanPostProcessor by 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 the field or setter name does not directly correspond to the declared name of a bean and no name attribute is used, Spring accesses other beans for matching them by type.

BeanPostProcessor实例和AOP自动代理

实现BeanPostProcessor接口的类是特殊的,容器对它们进行不同的处理。所有BeanPostProcessor实例和它们直接引用的bean都是在启动时实例化的,这是ApplicationContext特殊启动阶段的一部分。接下来,所有BeanPostProcessor实例以一种排序的方式注册,并应用于容器中的所有其他bean。因为AOP自动代理是作为BeanPostProcessor本身实现的,所以无论是BeanPostProcessor实例还是它们直接引用的bean都不符合自动代理的条件,因此,它们没有嵌入方面。对于任何这样的bean,您应该看到一条信息日志消息:bean someBean不适合由所有BeanPostProcessor接口处理(例如:不适合自动代理)。如果您使用自动装配或@Resource(可能会退回到自动装配)将bean连接到BeanPostProcessor中。Spring在搜索类型匹配的依赖候选项时可能会访问意想不到的bean,因此使它们不适合自动代理或其他类型的bean后处理。例如,如果您有一个带@Resource注释的依赖项,其中字段或setter名称不直接对应于bean声明的名称,并且没有使用name属性,那么Spring将访问其他bean以按类型匹配它们。

The following examples show how to write, register, and use BeanPostProcessor instances in an ApplicationContext.

下面的例子展示了如何在ApplicationContext中编写、注册和使用BeanPostProcessor实例。
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()方法,并将结果字符串打印到系统控制台。

The following listing shows the custom BeanPostProcessor implementation class definition:

下面的清单显示了自定义BeanPostProcessor实现类定义:
package scripting;

import org.springframework.beans.factory.config.BeanPostProcessor;

public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {

    // simply return the instantiated bean as-is
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean; // we could potentially return any object reference here...
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("Bean '" + beanName + "' created : " + bean.toString());
        return bean;
    }
}

The following beans element uses the InstantiationTracingBeanPostProcessor:

下面的bean元素使用了InstantiationTracingBeanPostProcessor:
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang
        https://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 merely defined. It does not even have a name, and, because it is a bean, it can be dependency-injected as you would 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 Dynamic Language Support.)

注意InstantiationTracingBeanPostProcessor是如何仅仅定义的。它甚至没有名称,而且,因为它是一个bean,所以可以像其他bean一样进行依赖注入。(前面的配置还定义了一个由Groovy脚本支持的bean。Spring动态语言支持在“动态语言支持”一章中有详细介绍。)

The following Java application runs 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 = ctx.getBean("messenger", Messenger.class);
        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 AutowiredAnnotationBeanPostProcessor

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 AutowiredAnnotationBeanPostProcessor — a BeanPostProcessor implementation that ships with the Spring distribution and autowires annotated fields, setter methods, and arbitrary config methods.

将回调接口或注释与自定义BeanPostProcessor实现结合使用是扩展Spring IoC容器的一种常见方法。一个例子是Spring的autowiwidannotationbeanpostprocessor——Spring分发版附带的BeanPostProcessor实现,可以自动连接注释字段、setter方法和任意配置方法。

1.8.2. Customizing Configuration Metadata with a `BeanFactoryPostProcessor`

The next extension point that we 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 lets a BeanFactoryPostProcessor read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessor instances.

我们要查看的下一个扩展点是org.springframework.beans.factory.config.BeanFactoryPostProcessor。这个接口的语义类似于BeanPostProcessor,有一个主要区别:BeanFactoryPostProcessor操作bean配置元数据。也就是说,Spring IoC容器允许BeanFactoryPostProcessor读取配置元数据,并可能在容器实例化BeanFactoryPostProcessor实例以外的任何bean之前更改它。

You can configure multiple BeanFactoryPostProcessor instances, and you can control the order in which these BeanFactoryPostProcessor instances run 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. See the javadoc of the BeanFactoryPostProcessor and Ordered interfaces for more details.

您可以配置多个BeanFactoryPostProcessor实例,并且可以通过设置order属性来控制这些BeanFactoryPostProcessor实例的运行顺序。但是,只有当BeanFactoryPostProcessor实现了Ordered接口时,才能设置此属性。如果您编写自己的BeanFactoryPostProcessor,您也应该考虑实现Ordered接口。有关更多细节,请参阅BeanFactoryPostProcessor和Ordered接口的javadoc。

If you want to change the actual bean instances (that is, the objects that are created from the configuration metadata), then you instead need to use a BeanPostProcessor (described earlier in Customizing Beans by Using a BeanPostProcessor). While it is technically possible to work with bean instances within a BeanFactoryPostProcessor (for example, by using BeanFactory.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, BeanFactoryPostProcessor instances are scoped per-container. This is only relevant if you use container hierarchies. If you define a BeanFactoryPostProcessor in one container, it is applied only to the bean definitions in that container. Bean definitions in one container are not post-processed by BeanFactoryPostProcessor instances in another container, even if both containers are part of the same hierarchy.

如果希望更改实际的bean实例(即从配置元数据创建的对象),则需要使用BeanPostProcessor(在前面使用BeanPostProcessor自定义bean中进行了描述)。虽然在技术上可以使用BeanFactoryPostProcessor中的bean实例(例如,通过使用BeanFactory.getBean()),但这样做会导致过早的bean实例化,违反标准容器生命周期。这可能会导致负面的副作用,如绕过bean后处理。

而且,BeanFactoryPostProcessor实例的作用域是针对每个容器的。这只与使用容器层次结构有关。如果您在一个容器中定义了BeanFactoryPostProcessor,那么它只应用于该容器中的bean定义。一个容器中的Bean定义不会由另一个容器中的BeanFactoryPostProcessor实例进行后处理,即使两个容器都是相同层次结构的一部分。

A bean factory post-processor is automatically run 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 PropertySourcesPlaceholderConfigurer. You can also use a custom BeanFactoryPostProcessor — for example, to register custom property editors.

当在ApplicationContext中声明bean工厂后处理器时,它会自动运行,以便将更改应用于定义容器的配置元数据。Spring包括许多预定义的bean工厂后处理器,例如PropertyOverrideConfigurer和PropertySourcesPlaceholderConfigurer。您还可以使用自定义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。在适当的时候,它使用这些bean作为bean工厂的后处理器。您可以像部署其他bean一样部署这些后处理器bean。

As with BeanPostProcessors , you typically do not want to configure BeanFactoryPostProcessors for lazy initialization. If no other bean references a Bean(Factory)PostProcessor, that post-processor will not get instantiated at all. Thus, marking it for lazy initialization will be ignored, and the Bean(Factory)PostProcessor will be instantiated eagerly even if you set the default-lazy-init attribute to true on the declaration of your <beans /> element.

与BeanPostProcessors一样,您通常不希望将BeanFactoryPostProcessors配置为惰性初始化。如果没有其他bean引用bean(工厂)PostProcessor,则该后处理器将根本不会实例化。因此,将其标记为延迟初始化将被忽略,并且即使您在<beans />元素的声明中将默认的-lazy-init属性设置为true, Bean(Factory)PostProcessor也会立即实例化。
Example: The Class Name Substitution PropertySourcesPlaceholderConfigurer

You can use the PropertySourcesPlaceholderConfigurer to externalize property values from a bean definition in a separate file by 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.

您可以使用propertysourcesplaceholderconfigururer通过使用标准Java Properties格式,将bean定义中的属性值外部化到单独的文件中。这样,部署应用程序的人员就可以定制特定于环境的属性,例如数据库url和密码,而无需修改主XML定义文件或容器文件的复杂性和风险。

Consider the following XML-based configuration metadata fragment, where a DataSource with placeholder values is defined:

考虑以下基于xml的配置元数据片段,其中定义了一个具有占位符值的数据源:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="locations" value="classpath:com/something/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 example shows properties configured from an external Properties file. At runtime, a PropertySourcesPlaceholderConfigurer is applied to the metadata that replaces some properties of the DataSource. The values to replace are specified as placeholders of the form ${property-name}, which follows the Ant and log4j and JSP EL style.

该示例显示了从外部properties文件配置的属性。在运行时,PropertySourcesPlaceholderConfigurer被应用于替换DataSource的一些属性的元数据。要替换的值被指定为形式${property-name}的占位符,它遵循Ant、log4j和JSP EL风格。

The actual values come from another file in the standard Java Properties format:

实际的值来自另一个标准Java属性格式的文件:
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root

Therefore, the ${jdbc.username} string is replaced at runtime with the value, 'sa', and the same applies for other placeholder values that match keys in the properties file. The PropertySourcesPlaceholderConfigurer checks for placeholders in most properties and attributes of a bean definition. Furthermore, you can customize the placeholder prefix and suffix.

因此,${jdbc.username}字符串在运行时被替换为值'sa',同样的情况也适用于属性文件中匹配键的其他占位符值。PropertySourcesPlaceholderConfigurer检查bean定义的大多数属性和属性中的占位符。此外,还可以自定义占位符前缀和后缀。

With the context namespace introduced in Spring 2.5, you can configure property placeholders with a dedicated configuration element. You can provide one or more locations as a comma-separated list in the location attribute, as the following example shows:

使用Spring 2.5中引入的上下文命名空间,您可以用专用的配置元素配置属性占位符。您可以在location属性中提供一个或多个位置,以逗号分隔,如下所示:
<context:property-placeholder location="classpath:com/something/jdbc.properties"/>

The PropertySourcesPlaceholderConfigurer not only looks for properties in the Properties file you specify. By default, if it cannot find a property in the specified properties files, it checks against Spring Environment properties and regular Java System properties.

PropertySourcesPlaceholderConfigurer不仅在您指定的properties文件中寻找属性。默认情况下,如果它在指定的属性文件中找不到属性,它就检查Spring Environment属性和常规Java System属性。

You can use the PropertySourcesPlaceholderConfigurer to substitute class names, which is sometimes useful when you have to pick a particular implementation class at runtime. The following example shows how to do so:

<bean class="org.springframework.beans.factory.config.PropertySourcesPlaceholderConfigurer">
    <property name="locations">
        <value>classpath:com/something/strategy.properties</value>
    </property>
    <property name="properties">
        <value>custom.strategy.class=com.something.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 an ApplicationContext for a non-lazy-init bean.

您可以使用PropertySourcesPlaceholderConfigurer来替代类名,当您必须在运行时选择一个特定的实现类时,这有时很有用。下面的例子展示了如何这样做:

如果类不能在运行时解析为有效的类,则在即将创建bean时解析失败,这是在非惰性初始化bean的ApplicationContext的preInstantiateSingletons()阶段。

Example: The PropertyOverrideConfigurer

The PropertyOverrideConfigurer, another bean factory post-processor, resembles the PropertySourcesPlaceholderConfigurer, 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.

另一个bean工厂后处理器PropertyOverrideConfigurer类似于PropertySourcesPlaceholderConfigurer,但与后者不同的是,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定义文件中并不能立即看出正在使用重写配置程序。对于为同一个bean属性定义不同值的多个PropertyOverrideConfigurer实例,由于覆盖机制,最后一个实例胜出。

Properties file configuration lines take the following format:

Properties文件配置行采用以下格式:
beanName.property=value

The following listing shows an example of the format:

下面的清单显示了该格式的一个示例:
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 that has driver and url properties.

这个示例文件可以与容器定义一起使用,该容器定义包含一个名为dataSource的bean,该bean具有驱动程序和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 the following example, the sammy property of the bob property of the fred property of the tom bean is set to the scalar value 123:

也支持复合属性名,只要路径的每个组件(除了被重写的最终属性)都是非空的(假定由构造函数初始化)。在下面的例子中,tom bean的fred属性的bob属性的sammy属性被设置为标量值123:
tom.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, as the following example shows:

使用Spring 2.5中引入的上下文命名空间,可以使用专用的配置元素来配置属性覆盖,如下所示:
<context:property-override location="classpath:override.properties"/>

1.8.3. Customizing Instantiation Logic with a `FactoryBean`

You can 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容器实例化逻辑的点。如果您有复杂的初始化代码,并且可以用Java更好地表达,而不是(可能)冗长的XML,那么您可以创建自己的FactoryBean,在类中编写复杂的初始化,然后将定制的FactoryBean插入到容器中。

The FactoryBean<T> interface provides three methods:

  • T 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 or false otherwise. The default implementation of this method returns true.
  • Class<?> getObjectType(): Returns the object type returned by the getObject() method or null if the type is not known in advance.
FactoryBean接口提供了三种方法:
  • T getObject():返回该工厂创建的对象的实例。这个实例可能是共享的,这取决于这个工厂返回的是单例还是原型。
  • boolean isSingleton():如果该FactoryBean返回单例,则返回true,否则返回false。这个方法的默认实现返回true。
  • Class getObjectType():返回getObject()方法返回的对象类型,如果事先不知道类型,则返回null。

The FactoryBean concept and interface are 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自带的FactoryBean接口的实现超过50个。

When you need to ask a container for an actual FactoryBean instance itself instead of the bean it produces, prefix 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前加上&符号(&)。因此,对于一个给定的带有myBean id的FactoryBean,在容器上调用getBean("&myBean")将返回FactoryBean的产品,而调用getBean("&myBean")将返回FactoryBean实例本身。
posted @ 2022-09-13 10:03  丶Jan  阅读(34)  评论(0)    收藏  举报