Spring Framework学习之路(20)--- 容器扩展点

1.8. Container Extension Points

1.8. 容器扩展点

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 using a BeanPostProcessor

1.8.1. 使用BeanPostProcessor定制bean

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 Orderedinterface; 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 instances.
您可以配置多个BeanPostProcessor实例,并且可以通过设置订单属性来控制这些BeanPostProcessors执行的顺序。只有BeanPostProcessor实现Ordered接口时,才可以设置此属性;如果你编写自己的BeanPostProcessor,你应该考虑实现Ordered接口。有关更多详细信息,请参阅BeanPostProcessor和Ordered接口的javadocs。另请参阅以下有关BeanPostProcessor的程序实例注册的注释。

BeanPostProcessors operate on bean (or object) instances; that is to say, the Spring IoC container instantiates a bean instance and then BeanPostProcessors do their work.
BeanPostProcessors对bean(或对象)实例进行操作; 也就是说,Spring IoC容器实例化一个bean实例,然后BeanPostProcessors完成它们的工作。

BeanPostProcessors are scoped per-container. This is only relevant if you are using container hierarchies. If you define a BeanPostProcessor 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 a BeanPostProcessor defined in another container, even if both containers are part of the same hierarchy.
BeanPostProcessors是每个容器的作用域。 这只有在使用容器层次结构时才有意义。 如果你在一个容器中定义了一个BeanPostProcessor,它将只处理该容器中的bean。 换句话说,在一个容器中定义的bean不会被另一个容器中定义的BeanPostProcessor进行后处理,即使两个容器都是同一层次结构的一部分。

To change the actual bean definition (i.e., the blueprint that defines the bean), you instead need to use a BeanFactoryPostProcessor as described in Customizing configuration metadata with a BeanFactoryPostProcessor.
要更改实际的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’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()之前)和容器声明的init方法)以及任何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。 ApplicationContext将这些bean注册为后处理器,以便稍后在创建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需要尽早实例化以适用于上下文中其他bean的初始化,因此这种早期类型检测非常重要。

Programmatically registering BeanPostProcessors
以编程方式注册BeanPostProcessors

While the recommended approach for BeanPostProcessor registration is through ApplicationContext auto-detection (as described above), it is also possible to register them programmatically against a ConfigurableBeanFactory using the addBeanPostProcessor 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 that BeanPostProcessors added programmatically do not respect the Ordered interface. Here it is the order of registration that dictates the order of execution. Note also that BeanPostProcessors registered programmatically are always processed before those registered through auto-detection, regardless of any explicit ordering.
虽然BeanPostProcessor注册的推荐方法是通过ApplicationContext自动检测(如上所述),但也可以使用addBeanPostProcessor方法以编程方式将其注册到ConfigurableBeanFactory。 当需要在注册之前评估条件逻辑,或者甚至跨层次结构中的上下文复制Bean后处理器时,这会非常有用。 但请注意,以编程方式添加的BeanPostProcessors不尊重Ordered界面。 这是注册顺序决定执行顺序。 还要注意,以编程方式注册的BeanPostProcessors总是在通过自动检测注册的BeanPostProcessors之前进行处理,而不管任何明确的排序。

BeanPostProcessors and AOP auto-proxying
BeanPostProcessors和AOP自动代理


Classes that implement the BeanPostProcessor interface are special and are treated differently by the container. All BeanPostProcessors and beans that they reference directly are instantiated on startup, as part of the special startup phase of the ApplicationContext. Next, all BeanPostProcessors 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 BeanPostProcessors nor the beans they reference directly are eligible for auto-proxying, and thus do not have aspects woven into them.
实现BeanPostProcessor接口的类是特殊的,并且容器对其进行不同的处理。作为ApplicationContext特殊启动阶段的一部分,它们直接引用的所有BeanPostProcessors和Bean都将在启动时实例化。接下来,所有BeanPostProcessors都以已排序的方式注册并应用于容器中的所有其他bean。因为AOP自动代理被实现为BeanPostProcessor本身,所以BeanPostProcessors和它们直接引用的bean都不适用于自动代理,因此不具有编入它们的方面。

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)”.
对于任何这样的bean,您应该看到一条信息性日志消息:“Bean foo不适合通过所有BeanPostProcessor接口进行处理(例如:不适合自动代理)”。

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 the field/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.
请注意,如果使用自动装配或@Resource(可能会回退到自动装配)将Bean连接到BeanPostProcessor中,Spring可能会在搜索类型匹配的依赖关系候选时访问意外的Bean,因此使它们不适用于自动代理或其他类型豆后期处理。例如,如果你有@Resource注释的依赖项,其中的字段/设置者名称并不直接对应于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
例如:Hello World,BeanPostProcessor风格

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;

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;
    }
}
<?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 Dynamic language support.)
注意InstantiationTracingBeanPostProcessor是如何定义的。 它甚至没有名称,因为它是一个bean,它可以像其他任何bean一样依赖注入。 (前面的配置也定义了一个由Groovy脚本支持的bean。Spring动态语言支持在标题为动态语言支持的章节中有详细介绍。)

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
示例: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 BeanPostProcessorimplementation 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就是一个例子,它是Spring发行版中的一个BeanPostProcessor实现,它确保标记有(任意)注释的bean的JavaBean属性实际(配置为)依赖注入一个值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工地码哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值