はじめに
Springには外部定義から値を読み込んで、Javaのフィールドにセットする機能がある。
application.propertiesにメッセージを記述し、
message=hello
Javaクラスで利用すると、
@Service public MessageServiceImpl implements MessageService { @Value("${message}") String message; public void say() { //helloが出力される System.out.println(message); } }
詳細はTERASOLUNAガイドラインがわかりやすい。
5.10. プロパティ管理 — TERASOLUNA Server Framework for Java (5.x) Development Guideline 5.1.0.RELEASE documentation
またSpringBootでは、外部ファイルのほかにも環境変数やJNDIなど、様々なところから値をとってこれる。Spring Boot Features
@Valueの詳細
外部定義の値(String)からJavaの型へのマッピングはPropertyEditorで行われる。
デフォルトで定義されているPropertyEditorは以下の通り。
詳細はリファレンスを参照。http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-beans-conversion
- ByteArrayPropertyEditor
- ClassEditor
- CustomBooleanEditor
- CustomCollectionEditor
- CustomDateEditor
- CustomNumberEditor
- FileEditor
- InputStreamEditor
- LocaleEditor
- PatternEditor
- PropertiesEditor
- StringTrimmerEditor
- URLEditor
上記で処理できない型にマッピングしようとすると、ConversionNotSupportedExceptionがスローされる。
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed toconvert value of type [java.lang.String] to required type [java.nio.file.Path]; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.nio.file.Path]: no matching editorsor conversion strategy found at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:74) at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:54) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1033) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ... 24 more Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.nio.file.Path]: no matching editors or conversion strategy found at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:302) at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:125) at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverte rSupport.java:61) ... 28 more
マッピングする型を増やす方法
JavaのPathを例に説明する。
1. マッピングさせたい型のPropertyEditor を作る。
package com.example.path; import java.beans.PropertyEditorSupport; import java.nio.file.Paths; public class PathPropertyEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { this.setValue(text == null?null: Paths.get(text)); } }
2. PropertyEditorを登録する。
@SpringBootApplication public class PathPropertyEditorApplication { public static void main(String[] args) { SpringApplication.run(PathPropertyEditorApplication.class, args); } @Bean public CustomEditorConfigurer getCustomEditorConfigurer(){ CustomEditorConfigurer configurer = new CustomEditorConfigurer(); Map<Class<?>, Class<? extends PropertyEditor>> map = new HashMap<>(); map.put(Path.class, PathPropertyEditor.class); configurer.setCustomEditors(map); return configurer; } }
実行してみる。
@Component public class Application implements CommandLineRunner { @Value(("${home.dir}")) Path path; @Override public void run(String... strings) throws Exception { System.out.println("----------------"); System.out.println(path); System.out.println("----------------"); } }
実行結果
---------------- \tmp ----------------
これで外部定義した文字列を任意のJavaの型にマッピングできる。