Импортировать файл конфигурации Spring на основе свойства в файле .properties.
В моей конфигурации Spring xml я пытаюсь заставить что-то вроде этого работать:
<beans>
<import resource="${file.to.import}" />
<!-- Other bean definitions -->
</beans>
Я хочу решить, какой файл импортировать на основе свойства в файле свойств.
Я знаю, что могу использовать свойство System, но я не могу добавить свойство JVM при запуске.
Примечание. Свойство PropertyPlaceHolderConfigurer не будет работать. Импорт разрешается до запуска любых BeanFactoryPostProcessors. Элемент import может разрешать только System.properties.
У кого-нибудь есть простое решение? Я не хочу запускать классы классов подкласса и т.д....
Спасибо
Ответы
Ответ 1
Это, к сожалению, намного сложнее, чем должно быть. В моем приложении я выполнил это, выполнив следующие действия:
-
Небольшой контекст "bootstrap", который отвечает за загрузку PropertyPlaceholderConfigurer bean и еще один bean, который отвечает за загрузку контекста приложения.
-
Второй bean, упомянутый выше, принимает в качестве входных данных "реальные" spring файлы контекста для загрузки. У меня есть файлы контекста spring, организованные так, что конфигурируемая часть хорошо известна и находится там же. Например, у меня может быть 3 файла конфигурации: one.onpremise.xml, one.hosted.xml, one.multitenant.xml. bean программно загружает эти файлы контекста в текущий контекст приложения.
Это работает, потому что файлы контекста указаны в качестве входных данных bean, ответственных за их загрузку. Это не сработает, если вы просто попытаетесь сделать импорт, как вы упомянули, но это имеет тот же эффект, что и немного больше. Класс bootstrap выглядит примерно так:
public class Bootstrapper implements ApplicationContextAware, InitializingBean {
private WebApplicationContext context;
private String[] configLocations;
private String[] testConfigLocations;
private boolean loadTestConfigurations;
public void setConfigLocations(final String[] configLocations) {
this.configLocations = configLocations;
}
public void setTestConfigLocations(final String[] testConfigLocations) {
this.testConfigLocations = testConfigLocations;
}
public void setLoadTestConfigurations(final boolean loadTestConfigurations) {
this.loadTestConfigurations = loadTestConfigurations;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
context = (WebApplicationContext) applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
String[] configsToLoad = configLocations;
if (loadTestConfigurations) {
configsToLoad = new String[configLocations.length + testConfigLocations.length];
arraycopy(configLocations, 0, configsToLoad, 0, configLocations.length);
arraycopy(testConfigLocations, 0, configsToLoad, configLocations.length, testConfigLocations.length);
}
context.setConfigLocations(configsToLoad);
context.refresh();
}
}
В принципе, получите контекст приложения, задайте его местоположения конфигурации и скажите ему, чтобы он обновился. Это отлично работает в моем приложении.
Надеюсь, что это поможет.
Ответ 2
Для Spring 2.5 и 3.0 У меня есть аналогичное решение для louis, однако я только что прочитал о 3.1 предстоящей функции: управление свойствами, который тоже звучит отлично.
Ответ 3
В Spring JIRA есть старая проблема для добавления свойств поддержки заполнитель для импорта (SPR-1358), которая была разрешена как "Не будет исправлять", но с тех пор было предложено решение с использованием EagerPropertyPlaceholderConfigurer.
Я лоббировал возобновление SPR-1358, но ответа пока нет. Возможно, если другие добавят свои варианты использования в комментарии к комментариям, которые помогут повысить осведомленность.
Ответ 4
Почему бы и нет:
- прочитайте свой файл свойств при запуске
- который определит, какую конфигурацию Spring загрузить
- в зависимости от того, что загружается config Spring, устанавливает определенные вещи, затем загружает общий Spring config
чтобы вы эффективно инвертировали свое предлагаемое решение.
Ответ 5
Добавьте что-то похожее на следующее:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound"><value>true</value></property>
<property name="locations">
<list>
<value>classpath:propertyfile.properties</value>
</list>
</property>
</bean>
Ответ 6
Если вы хотите указать импортированное имя XML файла вне applicationContext.xml, чтобы вы могли заменить applicationContext.xml, не теряя конфигурацию импортированного пути к файлу XML, вы можете просто добавить промежуточный Spring beans XML файл, скажем, confSelector.xml, так что importContext.xml импортирует confSelector.xml и confSelector.xml только содержит элемент <import> , который ссылается на соответствующий пользовательский XML файл beans.
Другим средством, которое может быть полезно, являются XML-сущности (определенные путем добавления элементов <! ENTITY... > в объявление DTD в начале XML). Они позволяют импортировать XML-фрагменты из других файлов и предоставлять функциональность "заполнитель-заполнитель" для любого XML файла.
Ни одно из этих решений не позволяет вам иметь файл конфигурации в формате Java.properties.
Ответ 7
Ответ Андре Шустера, который я натолкнулся, помог мне решить очень похожую проблему, которую я испытывал, желая найти другое выражение свойств в зависимости от того, работал ли я на своем собственном хосте, Дженкинсом на нашем сборке или в "реального" развертывания. Я сделал это:
<context:property-placeholder location="file:///etc/myplace/database.properties" />
а затем
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF/classes/resources/database.properties</value>
...
</list>
</property>
</bean>
который решил мою проблему, потому что на моем хосте разработки я поместил ссылку на свою собственную базу данных database.properties в /etc/myplace/database.properties и немного другую на сервере Jenkins. В реальном развертывании такой файл не найден, поэтому Spring возвращается в "реальный" в ресурсах в подкаталоге файлов классов. Если указанные свойства уже указаны в файле /etc/myplace/database.properties, то (к счастью) они не переопределяются локальным файлом.
Ответ 8
Другим обходным решением, которое не зависит от свойств системы, является загрузка свойств всех файлов с использованием другого PropertyPlaceholderConfigurer для каждого файла и определение другого placeholderPrefix для каждого из них.
Этот placeholderprefix настраивается исходным файлом свойств.
Определите первый файл свойства: (содержащий первый или второй)
global.properties
fileToUse=first
Определите файлы, содержащие свойство, которое может быть переключено в зависимости от свойства, указанного выше:
first.properties
aProperty=propertyContentOfFirst
second.properties
aProperty=propertyContentOfSecond
Затем определите держатели мест для всех файлов:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:global.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="first{" />
<property name="locations">
<list>
<value>classpath:first.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="second{" />
<property name="locations">
<list>
<value>classpath:second.properties</value>
</list>
</property>
</bean>
Используйте свойство, определенное в глобальном, для определения ресурса для использования из другого файла:
${fileToUse}{aProperty}
Ответ 9
Если я добавлю аргумент JVM ниже и файл myApplicationContext.dev.xml, spring загрузит
-DmyEnvironment = DEV
<context:property-placeholder />
<import resource="classpath:/resources/spring/myApplicationContext.${myEnvironment}.xml"/>
Ответ 10
Я использую Spring 3 и загружаю такие свойства:
<context:property-placeholder location="/WEB-INF/my.properties" />