前回の記事では[PropertiesFactoryBean]を使ったプロパティの取得方法を紹介した。今回は、もうひとつのやり方である[property-placeholder]を使用したプロパティの使用方法を紹介する。
SpringMVCでこれを使用する際の注意点として、[property-placeholder]はapplicationContext.xml と spring-mvc.xml の両方に定義が必要である。
ソース
フォルダ構成。
applicationContext.xml。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.yyama.hoge" /> <context:property-placeholder location="classpath*:myProp.properties" /> </beans>
[context:property-placeholder]を使用している。要素[location]にはプロパティファイルの位置を指定する。サンプルではClassPath直下の"myProp.properties"を指定している。
プロパティファイル"myProp.properties"は前回と一緒。
key=value
次にFugaクラス。
package org.yyama.hoge; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class Fuga { @Value("${key}") String value; public void proc() throws Exception { System.out.println("key:" + value); } }
[@Value("${key}")]でプロパティファイルを読み込み、keyに紐づく値を変数"value"に設定してくれる。このように${キーの値}という書き方でvalueを取得できると覚えておく。
キーが見つからない場合、次のような例外が発生する。
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fuga': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}" at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:355) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) at org.yyama.Main.main(Main.java:8) Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}" at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174) at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:219) at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:193) at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172) at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:813) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1039) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349) ... 13 more
続いてMainクラス。前回のサンプルと同じ。
package org.yyama; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.yyama.hoge.Fuga; public class Main { public static void main(String... args) throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); ctx.getBean(Fuga.class).proc(); ctx.close(); } }
一応pom.xml。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework.samples</groupId> <artifactId>Sample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <!-- Generic properties --> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring --> <spring-framework.version>4.3.2.RELEASE</spring-framework.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> </dependencies> </project>
実行すると以下の出力が得られ、プロパティファイルが正しく読み込まれていることが確認できる。
key:value
設定ファイル内でも使えるよ
[property-placeholder]で取得したプロパティの値はSpringの設定ファイル内でも使用できる。このサンプルでいう[applicationContext.xml]ファイル内で使用できる。
たとえば次のような感じ。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.yyama.hoge" /> <context:property-placeholder location="classpath*:myProp.properties" /> <bean class="org.yyama.hoge.Piyo"> <property name="val" value="${key}" /> </bean> </beans>
propertyタグのvalue要素に"${key}"と記載されている。これでPiyoクラスの変数valにプロパティファイルで定義されているkeyに紐づく値が自動でセットされる。
Piyoクラス。
package org.yyama.hoge; public class Piyo { String val; public void setVal(String val) { this.val = val; } public void proc() throws Exception { System.out.println("key:" + val); } }
本題とは関係ないが、変数に値を自動セットしたい場合はsetterは必要になる。
まとめ
2回にわたり[PropertiesFactoryBean]と[context:property-placeholde]でプロパティファイルを読み込むサンプルを示した。どちらを使ってもいいと思うが、設定ファイル内でプロパティファイルの内容を利用できる点で[context:property-placeholde]に軍配が上がるのではないだろうか。
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発
- 作者:株式会社NTTデータ
- 出版社/メーカー: 翔泳社
- 発売日: 2016/07/21
- メディア: 大型本