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

    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"/>

  • 相关阅读:
    SimpleDateFormat解析的时区问题
    linux之cp/scp命令+scp命令详解
    java.net.SocketException: java.security.NoSuchAlgorithmException
    Gradle使用手册(一):为什么要用Gradle?
    js_实用
    exp.validate.js
    MySQL实用技巧
    MongoDB 用户配置
    js 图片处理 Jcrop.js API
    MySQL连接池
  • 原文地址:https://www.cnblogs.com/springmorning/p/10364659.html
Copyright © 2011-2022 走看看