【问题标题】:How to add Properties to an Application Context如何将属性添加到应用程序上下文
【发布时间】:2012-02-15 13:20:24
【问题描述】:

我有一个独立应用程序,该应用程序计算一个值(属性),然后启动一个 Spring 上下文。 我的问题是如何将该计算的属性添加到 spring 上下文中,以便我可以像从属性文件 (@Value("${myCalculatedProperty}")) 加载的属性一样使用它?

稍微说明一下

public static void main(final String[] args) {
    String myCalculatedProperty = magicFunction();         
    AbstractApplicationContext appContext =
          new ClassPathXmlApplicationContext("applicationContext.xml");
    //How to add myCalculatedProperty to appContext (before starting the context)

    appContext.getBean(Process.class).start();
}

ApplicationContext.xml:

<bean id="propertyPlaceholderConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:*.properties" />
</bean>

<context:component-scan base-package="com.example.app"/>

这是一个 Spring 3.0 应用程序。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    在 Spring 3.1 中,您可以实现自己的 PropertySource,请参阅:Spring 3.1 M1: Unified Property Management

    首先,创建您自己的PropertySource 实现:

    private static class CustomPropertySource extends PropertySource<String> {
    
        public CustomPropertySource() {super("custom");}
    
        @Override
        public String getProperty(String name) {
            if (name.equals("myCalculatedProperty")) {
                return magicFunction();  //you might cache it at will
            }
            return null;
        }
    }
    

    现在在刷新应用上下文之前添加这个PropertySource

    AbstractApplicationContext appContext =
        new ClassPathXmlApplicationContext(
            new String[] {"applicationContext.xml"}, false
        );
    appContext.getEnvironment().getPropertySources().addLast(
       new CustomPropertySource()
    );
    appContext.refresh();
    

    从现在开始,您可以在 Spring 中引用您的新属性:

    <context:property-placeholder/>
    
    <bean class="com.example.Process">
        <constructor-arg value="${myCalculatedProperty}"/>
    </bean>
    

    也适用于注解(记得添加&lt;context:annotation-config/&gt;):

    @Value("${myCalculatedProperty}")
    private String magic;
    
    @PostConstruct
    public void init() {
        System.out.println("Magic: " + magic);
    }
    

    【讨论】:

    • @Ralph:不,很遗憾。只是为了记录,我添加了完整的 PropertySource 示例实现。
    • 这确实有效,但您必须确保您使用的 Spring 版本(包括所有依赖项)晚于 3.0,否则您不会走得太远。尤其要检查 context.xml 文件顶部的包含内容。
    • 谁能给我推荐一下spring-boot的解决方案。
    • @PratikShah 从 spring 3.1 开始,您可以将@PropertySource("classpath:path/to/classpath/application.properties") 添加到具有@Configuration 的类中。复数 @PropertiySources 如果您使用的是 Java
    【解决方案2】:

    您可以将计算的值添加到系统属性中:

    System.setProperty("placeHolderName", myCalculatedProperty);
    

    【讨论】:

    • 但请注意,这种方式您禁用了使用启动参数(即 -DplaceHolderName=someEnvSpecificValue)从应用程序外部轻松覆盖此属性的可能性。我认为添加了使用系统属性的可能性来处理特定于环境的值,并且还有其他可能性可以将您的自定义属性添加到上下文中,即注册多个PropertyPlaceholderConfigurer
    【解决方案3】:

    如果您控制ApplicationContext 的创建,如您的示例中那样,则您始终可以添加BeanRegistryPostProcessor 以将第二个PropertyPlaceholderConfigurer 添加到上下文中。它应该有ignoreUnresolvablePlaceholders="true"order="1",并且只解析使用Properties 对象的自定义计算属性。所有其他属性都应由应具有 order="2" 的 XML 中的 PropertyPlaceholderConfigurer 解析。

    【讨论】:

      【解决方案4】:

      您的myCalculatedProperty 必须包含在您的一个属性文件中(由Spring propertyPlaceholderConfigurer 注入)。

      编辑:只需使用设置器,就像这样

      public static void main(final String[] args) {
          String myCalculatedProperty = magicFunction();         
          AbstractApplicationContext appContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
      
          Process p = appContext.getBean(Process.class);
          p.setMyCalculatedProperty(myCalculatedProperty);
          p.start();
      }
      

      【讨论】:

      • 这行得通,但我不想创建属性文件(应用程序每次运行的值都不一样),我想直接“注入”它们。
      • 只使用你的属性的setter,不是吗?
      • 我不明白最后的评论。 spring 上下文中的属性像普通属性一样使用(使用@Value)。我需要在 spring 上下文中以某种方式声明它,以便 spring (PropertyPlaceholder) 可以像从属性文件加载的属性一样使用它。
      • 我明白了,但这并不能解决问题。当我这样做时,我需要搜索所有用@Value 注释的字段(其中一些是构造函数参数)。所以最终这会使弹簧过时。
      猜你喜欢
      • 2020-12-03
      • 2017-12-09
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2010-12-02
      相关资源
      最近更新 更多