を使用してプロパティファイルを読み取っていますcontext:property-placeholder
。プログラムでそれらにアクセスするにはどうすればよいですか(@Value
機能しません-開発の時点でプロパティのタイトルがわかりません)?
主な問題はapplicationContext.xml
、「親」フレームワークによって設定されているため、ファイルを変更できないことです。
ps。奇妙ですがEnvironment.getProperty
戻ってきますnull
を使用してプロパティファイルを読み取っていますcontext:property-placeholder
。プログラムでそれらにアクセスするにはどうすればよいですか(@Value
機能しません-開発の時点でプロパティのタイトルがわかりません)?
主な問題はapplicationContext.xml
、「親」フレームワークによって設定されているため、ファイルを変更できないことです。
ps。奇妙ですがEnvironment.getProperty
戻ってきますnull
いいえ、できません。PropertyPlaceholderConfigurer
は、BeanFactoryPostProcessor
Beanの作成中にのみ「生きている」です。表記に遭遇する${property}
と、内部プロパティに対してそれを解決しようとしますが、これらのプロパティをコンテナで使用できるようにしません。
とはいえ、同様の質問が何度も出てきましたが、提案された解決策は通常、プロパティをサブクラスPropertyPlaceHolderConfigurer
化し、コンテキストで手動で使用できるようにすることです。または、PropertiesFactoryBean
アプリケーションのプロパティにアクセスするには、次のアプローチを使用します
<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"/>
@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;
Springは制御の反転アプローチに従います。これは、特定のプロパティを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>
<util:properties id="prop" location="location of prop file" />
これはjava.util.Propertiesオブジェクトを返します
JAVAコードで
Properties prop = (Properties) context.getBean("prop");
今、あなたはアクセスすることができます、
prop.getProperty("key");
プロパティをコード内で簡単にアクセスできるように、プロパティプレースホルダーに配置する前にプロパティの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")を使用することもできます
これは、プロパティの複数の場所をスキャンする必要がある場合に機能します...
<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;
Spring5.1.4を使用してテスト済み
その「親」フレームワークで定義されたプロパティファイルを想定しましょう
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:main.properties" />
</bean>
@Valueアノテーションは次のように使用できます。
@Value( value = "#{applicationProperties['my.app.property']}" )
private String myProperty;