码迷,mamicode.com
首页 > 编程语言 > 详细

Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.8.2 使用BeanFactoryPostProcessor定制配置元数据

时间:2019-02-12 13:20:45      阅读:16      评论:0      收藏:0      [点我收藏+]

标签:log4   改变   编辑   roo   ext   创建   语义   source   执行顺序   

6.8.2 使用BeanFactoryPostProcessor定制配置元数据

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

您可以配置多个BeanFactoryPostProcessors,并且可以通过设置order属性来控制这些BeanFactoryPostProcessors的执行顺序。但是,如果BeanFactoryPostProcessor实现了Ordered接口,则只能设置此属性。如果编写自己的BeanFactoryPostProcessor,则应该考虑实现Ordered接口。有关更多详细信息,请参阅BeanFactoryPostProcessorOrdered接口的javadoc

如果要改变bean实例(例如来自配置元数据创建的对象),则需要使用BeanPostProcessor(如上面6.8.1使用BeanPostProcessor定制bean”中所述)。虽然技术上可以在BeanFactoryPostProcessor中使用bean实例(例如,使用BeanFactory.getBean()),但这样做会导致过早实例化bean,违背了标准的容器生命周期。这可能会造成负面影响,例如绕过bean处理。

外,BeanFactoryPostProcessors作用域是每个容器。这仅在您使用容器层级时才有意义。 如果在一个容器中定义了一个BeanFactoryPostProcessor,它将仅应用于该容器中的bean定义。 尽管两个容器都作为相同的一部分BeanFactoryPostProcessors不会在另一个容器中对一个容器中的Bean定义执行处理。

bean工厂后处理器在ApplicationContext中声明时自动执行,以便将变化应用于定义容器的配置元数据。Spring包含许多预定义的bean工厂后处理器,例如PropertyOverrideConfigurerPropertyPlaceholderConfigurer。例如,也可以使用自定义的BeanFactoryPostProcessor,用来注册自定义属性编辑器。

ApplicationContext自动检测部署在它里面的任何实现BeanFactoryPostProcessor接口的bean。 它在适当的时候使用这些bean作为bean工厂后处理器。您可以像部署任何其他bean一样部署这些后处理器bean

BeanPostProcessors一样,您通常不希望为延迟初始化配置BeanFactoryPostProcessors。如果没有其他bean引用Bean(Factory)PostProcessor,则该后处理器根本不会被实例化。因此,将其标记为延迟初始化会被容器忽视,即使<beans />元素的声明中将default-lazy-init属性设置为true容器也会尽快地实例化BeanFactoryPostProcessor

示例:类名替换PropertyPlaceholderConfigurer

您可以使用PropertyPlaceholderConfigurerbean定义的属性值外部化为单独的标准的Java属性文件。这样做使得部署应用程序的人员可以根据特定环境属性进行自定义(如数据库URL和密码),而没有修改主要的XML定义文件或容器文件的复杂性或风险。

思考以下基于XML的配置元数据片段,其中定义了具有占位符值的DataSource。该示例显示了通过外部属性文件配置属性。在运行时,使用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>

实际值来自标准Java属性文件格式的另一个文件:

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root

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

使用Spring 2.5中引入的上下文命名空间,可以使用专用配置元素配置属性占位符。在location属性中可以以逗号分隔列表提供一个或多个位置。

<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>

PropertyPlaceholderConfigurer不仅在您指定的属性文件中查找属性。默认情况下,如果在指定的属性文件中找不到属性,它还会在Java系统属性中检查。您可以通过使用以下三个受支持的整数值之一设置configurersystemPropertiesMode属性来自定义此行为:

  • never0):从不检查系统属性
  • fallback1):如果在指定的属性文件中无法解析,则检查系统属性。这是默认值。
  • override2):在尝试指定的属性文件之前,首先检查系统属性。这允许系统属性覆盖任何其他属性源。

有关更多信息,请参阅PropertyPlaceholderConfigurer javadocs

您可以使用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}"/>

如果在运行时无法将类解析为有效类,则在即将创建bean时,在对于延迟初始化的bean在ApplicationContextpreInstantiateSingletons()阶段期间,bean的解析将失败

示例:PropertyOverrideConfigurer

PropertyOverrideConfigurer是另一个bean工厂后处理器,类似于PropertyPlaceholderConfigurer,但与PropertyPlaceholderConfigurer不同的是,原始定义可以具有默认值,或者根本不具有bean属性的值。如果重写的Properties文件没有某个bean属性的条目,则使用默认的上下文定义。

请注意,由于bean定义不知道被覆盖因此,XML定义文件中不会很明显地看出正在使用覆盖配置器。如果多个PropertyOverrideConfigurer实例为同一个bean属性定义了不同的值,由于覆盖机制,最后一个实例将获胜。

属性文件配置行采用以下格式:

beanName.property=value

例如:

dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb

此示例文件可以与包含名为dataSourcebean的容器定义一起使用,该bean具有driverurl属性。

也支持复合属性名称,只要路径的每个元素(重写的最属性之外)都已经非空假设被构造函数初始化)。在这个例子中......

foo.fred.bob.sammy=123

foo beanfred属性的bob属性的sammy属性设置量值为123

指定的覆盖值始终是文字; 它们不会被翻译成bean引用。当XML bean定义中的原始值指定bean引用时,此约定也适用。

Spring 2.5中引入的上下文命名空间,让使用专用配置元素配置属性覆盖成为可能

<context:property-override location="classpath:override.properties"/>

 

 

Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.8.2 使用BeanFactoryPostProcessor定制配置元数据

标签:log4   改变   编辑   roo   ext   创建   语义   source   执行顺序   

原文地址:https://www.cnblogs.com/springmorning/p/10364659.html

(0)
(0)
   
举报
评论 一句话评论(0
0条  
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!