spring @Value 只看这篇是不够的

spring @Value 只看这篇是不够的

spring 的 @Value 的使用频率是比较高的,一般我们是用来注入外部化配置,特别是 property 文件配置。
本文介绍 @Value 的常用方式。

基本使用

// 应用到普通属性
// 如果匹配到了,则用配置属性设置属性
// 如果没有匹配到,则使用 ${..}设置属性
// 如果配置文件中没有配置属性,会报错,可以通过设置默认值避免错误。
@Value("${no:not defined}")
private String noDefine;

// 在构造方法使用
@Component
public class MyBean {

    private final String catalog;

    public MovieRecommender(@Value("${name}") String catalog) {
        this.catalog = catalog;
    }
}

//systemProperties 是预定义的内部变量,可以通过它获取系统属性。
// 注入操作系统属性
@Value("#{systemProperties['os.name']}")
private String osName;
// 如果@Value包含 SpEL,会动态生成值,当然 SpEL 要合法,否则会抛异常
// 结果:系统用户名+.why
@Value("#{systemProperties['user.name'] + '.why' }") 
private String catalog;

// 有了 Spel 的加成,可以支持复杂数据结构的注入,如
// map
@Value("#{{'Thriller': 100, 'Comedy': 300}}") 
Map countOfMoviesPerCatalog
// list
@Value("#{'${demo.list}'.split(',')}")
private List list;

// 可以通过 @Value 注入 Resource 类型
@Value("http://www.baidu.com")
private Resource baidu; // 注入URL资源
resource 数组
@Value("classpath*:/META-INF/*.properties")
private Resource[] resources;

原理剖析

@Value 有这多的使用方式,他是怎么实现的呢,我想到的第一步是看下 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 注解的。
这里我就不不详细分析源码了,有几点注意的地方我标记一下。

  • AutowiredAnnotationBeanPostProcessor 实现了 Ordered 接口所以有多个 BeanPostProcessor 时,他们的执行顺序对结果的影响需要注意,特别是自定义 BeanPostProcessor 时,一定要了解容器中现有生效的 bean 和 顺序,才能让自定义 BeanPostProcessor 在合适的位置执行。
  • postProcessProperties 方法实现了具体的注入逻辑。

    • AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
      • AutowireCapableBeanFactory#resolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter) 涉及到类型转换

参考

  • 1.9.8. Using @Value
  • Spring Expression Language (SpEL)

你可能感兴趣的:(spring @Value 只看这篇是不够的)