はじめに
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の型にマッピングできる。