spring @Value 只看這篇是不夠的
spring 的 @Value 的使用頻率是比較高的爪膊,一般我們是用來注入外部化配置赏僧,特別是 property 文件配置种柑。
本文介紹 @Value 的常用方式务蝠。
基本使用
// 應(yīng)用到普通屬性
// 如果匹配到了击奶,則用配置屬性設(shè)置屬性
// 如果沒有匹配到辈双,則使用 ${..}設(shè)置屬性
// 如果配置文件中沒有配置屬性,會(huì)報(bào)錯(cuò)柜砾,可以通過設(shè)置默認(rèn)值避免錯(cuò)誤湃望。
@Value("${no:not defined}")
private String noDefine;
// 在構(gòu)造方法使用
@Component
public class MyBean {
private final String catalog;
public MovieRecommender(@Value("${name}") String catalog) {
this.catalog = catalog;
}
}
//systemProperties 是預(yù)定義的內(nèi)部變量,可以通過它獲取系統(tǒng)屬性。
// 注入操作系統(tǒng)屬性
@Value("#{systemProperties['os.name']}")
private String osName;
// 如果@Value包含 SpEL证芭,會(huì)動(dòng)態(tài)生成值瞳浦,當(dāng)然 SpEL 要合法,否則會(huì)拋異常
// 結(jié)果:系統(tǒng)用戶名+.why
@Value("#{systemProperties['user.name'] + '.why' }")
private String catalog;
// 有了 Spel 的加成废士,可以支持復(fù)雜數(shù)據(jù)結(jié)構(gòu)的注入叫潦,如
// map
@Value("#{{'Thriller': 100, 'Comedy': 300}}")
Map<String, Integer> countOfMoviesPerCatalog
// list
@Value("#{'${demo.list}'.split(',')}")
private List<String> list;
// 可以通過 @Value 注入 Resource 類型
@Value("http://www.baidu.com")
private Resource baidu; // 注入U(xiǎn)RL資源
resource 數(shù)組
@Value("classpath*:/META-INF/*.properties")
private Resource[] resources;
原理剖析
@Value 有這多的使用方式,他是怎么實(shí)現(xiàn)的呢官硝,我想到的第一步是看下 doc 上有沒有蛛絲馬跡矗蕊。
Note that actual processing of the @Value annotation is performed by a BeanPostProcessor which in turn means that you cannot use @Value within BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).
線索指向了 AutowiredAnnotationBeanPostProcessor 的 doc。
BeanPostProcessor implementation that autowires annotated fields, setter methods, and arbitrary config methods. Such members to be injected are detected through annotations: by default, Spring's @Autowired and @Value annotations.
Also supports JSR-330's @Inject annotation, if available, as a direct alternative to Spring's own @Autowired.
找對地方了氢架,而且知道了傻咖,AutowiredAnnotationBeanPostProcessor 是處理 Autowired,Value达箍,Inject 注解的没龙。
這里我就不不詳細(xì)分析源碼了,有幾點(diǎn)注意的地方我標(biāo)記一下缎玫。
- AutowiredAnnotationBeanPostProcessor 實(shí)現(xiàn)了 Ordered 接口所以有多個(gè) BeanPostProcessor 時(shí)硬纤,他們的執(zhí)行順序?qū)Y(jié)果的影響需要注意,特別是自定義 BeanPostProcessor 時(shí)赃磨,一定要了解容器中現(xiàn)有生效的 bean 和 順序筝家,才能讓自定義 BeanPostProcessor 在合適的位置執(zhí)行。
-
postProcessProperties 方法實(shí)現(xiàn)了具體的注入邏輯邻辉。
- AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
- AutowireCapableBeanFactory#resolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set<java.lang.String>, org.springframework.beans.TypeConverter) 涉及到類型轉(zhuǎn)換
- AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject