【Java】Spring Bootで Java Config を使用し、Propertiesファイルを読み込む
SpringBootを使って、Propertiesファイルを読みたかったから、やってみた
以下の2つのJavaクラスを作った
sample/config/Config.java
package sample.config; import java.io.IOException; import java.util.Properties; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @Configuration @EnableAutoConfiguration public class Config { @Bean public Properties sqlProperties() throws IOException { PropertiesFactoryBean propFactoryBean = new PropertiesFactoryBean(); propFactoryBean.setLocation(new ClassPathResource("sample.properties")); // これ大事! propFactoryBean.afterPropertiesSet(); return propFactoryBean.getObject(); } }
Properties
を返すBeanを定義Properties
を生成するためのPropertiesFactoryBean
を用意location
にClassPathResource
のインスタンスをセットsrc/main/resources/sample.properties
だとしたら、new ClassPathResource('sample.properties')
とする- SpringBootで
src/main/resources
はクラスパス内のため
PropertiesFactoryBean.afterPropertiesSet()
がないとうまく値を取れなかったため、必ず実行すること- 何をしているのかはよくわからない
PropertiesFactoryBean.getObject()
でPropertiesのインスタンスを返す
sample/App.java
package sample; import java.util.Properties; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { private static final Logger log = LoggerFactory.getLogger(App.class); @Resource private Properties sqlProperties; public static void main(String[] args) { log.info("Hello World!"); try(ConfigurableApplicationContext ctx = SpringApplication.run(App.class, args)) { App app = ctx.getBean(App.class); app.run(args); } catch (Exception e) { e.printStackTrace(); } } public void run(String... args) throws Exception { log.info(sqlProperties.getProperty("samplevalue")); } }
- DIしたい
Properties
型の変数に@Resource
をつける@Resource
はBean名でDIされるらしい- 今回の場合、
sqlProperties
- 今回の場合、
getProperty()
で取得
src/main/resources/sample.properties
samplevalue=hello world
実行
20:30:49.252 [main] INFO sample.App - Hello World! . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.6.RELEASE) 2019-07-22 20:30:49.827 INFO 42668 --- [ main] sample.App : Starting App on Plus-OP021 with PID 42668 (C:\pleiades\workspace\spring-boot-properties-load\target\classes started by t-ohsaka in C:\pleiades\workspace\spring-boot-properties-load) 2019-07-22 20:30:49.828 INFO 42668 --- [ main] sample.App : No active profile set, falling back to default profiles: default 2019-07-22 20:30:50.507 INFO 42668 --- [ main] sample.App : Started App in 1.052 seconds (JVM running for 1.604) 2019-07-22 20:30:50.510 INFO 42668 --- [ main] sample.App : hello world!
わーできた!!簡単!!
今回のプロジェクトはここ に置いた
エラーが出たときのメモ
- Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.util.Properties' available: expected single matching bean but found 2: sqlProperties,systemProperties
- SpringのDIは型で一致したものをDIするため、同じ型のものがあると、どっちかわからない
@Resource
で変数名を@Bean
をつけたメソッド名と同じにする
- Bean named 'sqlProperties' is expected to be of type 'java.util.Properties' but was actually of type 'org.springframework.beans.factory.support.NullBean'
- 正しく
@Bean
で返せていなかった PropertiesFactoryBean.afterPropertiesSet()
を実行する- SpringのDIコンテナはbeanを生成しプロパティがセットされた後にafterPropertiesSet()メソッドを呼び出します
- 5.DIされたときの動作の制御(カスタマイズ)について - soracane
- JavaDocの和訳
すべてのBeanプロパティを設定し、BeanFactoryAware、ApplicationContextAwareなどを満たした後で、格納されているBeanFactoryによって呼び出されます。
このメソッドを使用すると、Beanインスタンスは、すべてのBeanプロパティが設定されたときに、全体の構成の検証と最終的な初期化を実行できます。
- んーわからん
- 正しく