context:property-placeholder
を使用してプロパティファイルを読み込んでいます。どうすればそれらにアクセスできますかプログラムで(@Value
は機能しません-開発の時点でプロパティのタイトルがわかりません)
主な問題は、「親」フレームワークによってセットアップされているため、applicationContext.xml
ファイルを変更できないことです。
追伸奇妙ですが、Environment.getProperty
はnull
を返します
いいえ、できません。 PropertyPlaceholderConfigurer
は BeanFactoryPostProcessor
であり、Beanの作成中にのみ「有効」です。 ${property}
表記を検出すると、内部プロパティに対してそれを解決しようとしますが、これらのプロパティをコンテナで使用できるようにしません。
つまり、同様の質問が何度も登場しているので、提案される解決策は通常 PropertyPlaceHolderConfigurer
をサブクラス化する であり、コンテキストでプロパティを手動で利用できるようにします。または PropertiesFactoryBean
を使用
@Value
注釈は、Springの新しいリリースで機能します(v3.2.2でテスト済み)。
Spring構成ファイルでプロパティファイルをマップします。
<!--Import Info:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd-->
<context:property-placeholder location="classpath:/app-config.properties" />
ソースフォルダー(ルート)内にapp-config.propertiesを作成します。
my.property=test
my.property2=test2
コントローラークラスを作成する
@Controller
public class XRDSBuilder
{
@Value("${my.property}")
private String myProperty;
public String getMyProperty() { return myProperty; }
}
Springはmy.propertyのコンテンツをコントローラー内の変数に自動的にマッピングします
プロパティ値:
my.list.property=test,test2,test3
コントローラークラスの構成:
@Value("#{'${my.list.property}'.split(',')}")
private List<String> myListProperty;
@Component("PropertySplitter")
public class PropertySplitter {
/**
* Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
*/
public Map<String, String> map(String property) {
return this.map(property, ",");
}
/**
* Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
*/
public Map<String, List<String>> mapOfList(String property) {
Map<String, String> map = this.map(property, ";");
Map<String, List<String>> mapOfList = new HashMap<>();
for (Entry<String, String> entry : map.entrySet()) {
mapOfList.put(entry.getKey(), this.list(entry.getValue()));
}
return mapOfList;
}
/**
* Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
*/
public List<String> list(String property) {
return this.list(property, ",");
}
/**
* Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
*/
public List<List<String>> groupedList(String property) {
List<String> unGroupedList = this.list(property, ";");
List<List<String>> groupedList = new ArrayList<>();
for (String group : unGroupedList) {
groupedList.add(this.list(group));
}
return groupedList;
}
private List<String> list(String property, String splitter) {
return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
}
private Map<String, String> map(String property, String splitter) {
return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
}
}
プロパティ値:
my.complex.property=test1:value1,test2:value2
コントローラークラス:
@Value("#{PropertySplitter.map('${my.complex.property}')}")
Map<String, String> myComplexProperty;
次のアプローチを使用して、アプリケーションのプロパティにアクセスします
<util:properties id="appProperties" location="classpath:app-config.properties" />
<context:property-placeholder properties-ref="appProperties"/>
次に、修飾子を使用してプロパティをBeanに自動配線するだけの贅沢があります。
@Component
public class PropertyAccessBean {
private Properties properties;
@Autowired
@Qualifier("appProperties")
public void setProperties(Properties properties) {
this.properties = properties;
}
public void doSomething() {
String property = properties.getProperty("code.version");
}
}
より複雑なプロパティがある場合でも、ignore-resource-not-foundおよびignore-unresolvableを使用できます。このアプローチを使用して、アプリケーション設定の一部を外部化します。
<util:properties id="appProperties" ignore-resource-not-found="true"
location="classpath:build.properties,classpath:application.properties,
file:/data/override.properties"/>
<context:property-placeholder ignore-unresolvable="true" properties-ref="appProperties"/>
SpringはInversion Of Controlアプローチに従います。これは、特定のプロパティをPOJOに単純に注入できることを意味します。しかし、コードから名前で指定されたプロパティに直接アクセスしたい場合があります-アンチパターンとしてそれを見るかもしれません-これは明白に真実ですが、それを行う方法に集中することができます。
以下のPropertiesAccessor
は、_Property Placeholder
_によってロードされたプロパティへのアクセスを提供し、コンテナ固有のものをカプセル化します。 AbstractBeanFactory#resolveEmbeddedValue(String)
の呼び出しは安くないため、見つかったプロパティもキャッシュします。
_@Named
public class PropertiesAccessor {
private final AbstractBeanFactory beanFactory;
private final Map<String,String> cache = new ConcurrentHashMap<>();
@Inject
protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public String getProperty(String key) {
if(cache.containsKey(key)){
return cache.get(key);
}
String foundProp = null;
try {
foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");
cache.put(key,foundProp);
} catch (IllegalArgumentException ex) {
// ok - property was not found
}
return foundProp;
}
}
_
以下のサイトで答えを見つけました:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer">
<property name="properties" ref="props" />
</bean>
<bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="file:C:/CONFIG/settings.properties"/>
</bean>
これは、プロパティの複数の場所をスキャンする必要がある場合に機能します...
<bean id="yourProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<array value-type="org.springframework.core.io.Resource">
<value>classpath:yourProperties.properties</value>
<value>file:../conf/yourProperties.properties</value>
<value>file:conf/yourProperties.properties</value>
<value>file:yourProperties.properties</value>
</array>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
<context:property-placeholder properties-ref="yourProperties" ignore-unresolvable="true"/>
そして、実際のクラスでは...
@Autowired
Properties yourProperties;
Spring 5.1.4を使用してテスト済み
プロパティをプロパティプレースホルダーに配置する前にプロパティのBeanを作成して、プロパティがコード内で簡単にアクセスできるようにします。
例:
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="resources" value="classpath:META-INF/spring/config.properties" />
</bean>
<context:property-placeholder properties-ref="configProperties" ignore-unresolvable="true"/>
コード:
@Autowired
private PropertiesFactoryBean configProperties;
@Resource(name = "configProperties")を使用することもできます
<util:properties id="prop" location="location of prop file" />
これはJava.util.Propertiesオブジェクトを返します
In Java Code
Properties prop = (Properties) context.getBean("prop");
これで、
prop.getProperty("key");