Подтвердить что ты не робот

Как добавить свойства в контекст приложения

У меня есть автономное приложение, это приложение вычисляет значение (Свойство), а затем запускает контекст 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.

4b9b3361

Ответ 1

В Spring 3.1 вы можете реализовать свой собственный PropertySource, см. Spring 3.1 M1: Унифицированное управление свойствами.

Сначала создайте собственную реализацию 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>

Также работает с аннотациями (не забудьте добавить <context:annotation-config/>):

@Value("${myCalculatedProperty}")
private String magic;

@PostConstruct
public void init() {
    System.out.println("Magic: " + magic);
}

Ответ 2

Вы можете добавить вычисленное значение к свойствам системы:

System.setProperty("placeHolderName", myCalculatedProperty);

Ответ 3

Если вы контролируете создание ApplicationContext, как в вашем примере, чем вы всегда можете добавить BeanRegistryPostProcessor, чтобы добавить второй PropertyPlaceholderConfigurer в контекст. Он должен иметь ignoreUnresolvablePlaceholders="true" и order="1" и разрешать только настраиваемые вычисленные свойства с помощью объекта Properties. Все остальные свойства должны быть разрешены PropertyPlaceholderConfigurer из XML, который должен иметь order="2".

Ответ 4

Ваш myCalculatedProperty должен содержаться в одном из ваших файлов свойств (которые вводятся с помощью Spring propertyPlaceholderConfigurer).

EDIT: просто используйте setter, что-то вроде этого

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();
}