在使用Java config配置Bean以前,即xml配置时代,bean的属性值可以通过 <property name=“xxx” value=""/>的形式。 value既可以使用固定值,也可以使用占位符的形式${xxx}。 占位符中的配置的值由一个特殊的bean的解析(PropertyPlaceholderConfigurer)。

而到了java config时代,给bean属性配置值,可以使用的方式是@Value,本章就来重点讲下@Value如何使用。

@Value定义

先看源码:

package org.springframework.beans.factory.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Annotation at the field or method/constructor parameter level* that indicates a default value expression for the affected argument.** <p>Typically used for expression-driven dependency injection. Also supported* for dynamic resolution of handler method parameters, e.g. in Spring MVC.** <p>A common use case is to assign default field values using* <code>#{systemProperties.myProp}</code> style expressions.** <p>Note that actual processing of the {@code @Value} annotation is performed* by a {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} which in turn means that you <em>cannot</em> use* {@code @Value} within* {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} or* {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}* types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}* class (which, by default, checks for the presence of this annotation).** @author Juergen Hoeller* @since 3.0* @see AutowiredAnnotationBeanPostProcessor* @see Autowired* @see org.springframework.beans.factory.config.BeanExpressionResolver* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {/*** The actual value expression &mdash; for example, <code>#{systemProperties.myProp}</code>.*/String value();}

从源码注释提取一下关键信息:

  • @Value可注解在Field, 方法,方法参数,或注解。通常用于表达式驱动的依赖注入,也支持动态方法参数的解析。
  • 一个通常的用法是SpEL, 如:#{systemProperties.myProp}。 (SpEL下一章单独讲解)。
  • 注意:事实上@Value注解是通过BeanPostProcessor实现的,所以BeanPostProcessor本身不能注入@Value的Field。
  • 确切的说@Value是通过AutowiredAnnotationBeanPostProcessor实现,即它既处理@Autowired注解,也处理@Value。

@Value注解的用法

  1. 不通过配置文件将外部的值动态注入到Bean中
  • 注入普通字符串
@Value("panda")
private String name;
  • 注入操作系统属性
@Value("#{systemProperties['os.name']}")
private String os;
  • 注入表达式结果
@Value("#{T(java.lang.Math).random() * 100.0}")
private double randomNumber;
  • 注入其他Bean的属性
@Value("#{animal.name}")
private String animalName;
  • 注入文件资源
@Value("classpath:application.properties")
private Resource classpathResource;
  • 注入URL资源
@Value("https://baidu.com")
private Resource urlResource;

示例:

  • 自定义Bean class, 演示了各种通过@Value的注入场景
package win.elegentjs.spring.ioc.value;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;/*** 自定义Bean class, 演示了各种通过@Value的注入场景* 注:不使用外部配置属性*/
@Data
public class CustomerValue {@Value("panda")private String name;@Value("#{systemProperties['os.name']}")private String os;@Value("#{T(java.lang.Math).random() * 100.0}")private double randomNumber;@Value("#{animal.name}")private String animalName;@Value("classpath:application.properties")private Resource classpathResource;@Value("https://baidu.com")private Resource urlResource;
}
  • java config 配置类,定义了两个bean,animal会被customerValue依赖
package win.elegentjs.spring.ioc.value;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** java config 配置类,定义了两个bean,animal会被customerValue依赖*/
@Configuration
public class CustomerValueConfig {@Beanpublic CustomerValue customerValue() {return new CustomerValue();}@Beanpublic Animal animal() {Animal animal = new Animal();animal.setName("dog");return animal;}
}
  • 测试类,演示测试结果
package win.elegentjs.spring.ioc.value;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Slf4j
public class CustomerValueSample {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CustomerValueConfig.class);CustomerValue customerValue = context.getBean(CustomerValue.class);log.info("==> customerValue: {}", customerValue);}
}// result:
2021-05-31 19:36:06.919 [main] INFO  win.elegentjs.spring.ioc.value.CustomerValueSample-==> customerValue: CustomerValue(name=panda, os=Mac OS X, randomNumber=54.4727006010814, animalName=dog, classpathResource=class path resource [application.properties], urlResource=URL [https://baidu.com])
  1. 通过配置文件注入属性

先通过@PropertySource指定属性配置文件源,@PropertySource源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {/*** Indicate the name of this property source. If omitted, a name will* be generated based on the description of the underlying resource.* @see org.springframework.core.env.PropertySource#getName()* @see org.springframework.core.io.Resource#getDescription()*/String name() default "";/*** Indicate the resource location(s) of the properties file to be loaded.* <p>Both traditional and XML-based properties file formats are supported* &mdash; for example, {@code "classpath:/com/myco/app.properties"}* or {@code "file:/path/to/file.xml"}.* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;* each location must evaluate to exactly one {@code .properties} resource.* <p>${...} placeholders will be resolved against any/all property sources already* registered with the {@code Environment}. See {@linkplain PropertySource above}* for examples.* <p>Each location will be added to the enclosing {@code Environment} as its own* property source, and in the order declared.*/String[] value();/*** Indicate if failure to find the a {@link #value() property resource} should be* ignored.* <p>{@code true} is appropriate if the properties file is completely optional.* Default is {@code false}.* @since 4.0*/boolean ignoreResourceNotFound() default false;/*** A specific character encoding for the given resources, e.g. "UTF-8".* @since 4.3*/String encoding() default "";/*** Specify a custom {@link PropertySourceFactory}, if any.* <p>By default, a default factory for standard resource files will be used.* @since 4.3* @see org.springframework.core.io.support.DefaultPropertySourceFactory* @see org.springframework.core.io.support.ResourcePropertySource*/Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;}

原始的源码注释很长,这里没有贴出来,感兴趣的自己去看一下,总结一下有用信息如下:

  • @PropertySource是一个实用注解用于添加一个PropertySource至Spring的Environment对象:即通过@PropertySource将properties配置文件中的值存储到spring的Environment对象中。
  • 典型用法1:使用Environment对象取属性值
 @Configuration@PropertySource("classpath:/com/myco/app.properties")public class AppConfig {@Autowiredprivate Environment env;@Beanpublic TestBean testBean() {TestBean testBean = new TestBean();testBean.setName(env.getProperty("testbean.name"));return testBean;}}
  • 典型用法2:使用@Value("${…}")解析
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {@Value("${testbean.name}")private String beanName;}
  • 在xml中能解析${…}占位符是因为配置了<context:property-placeholder>, 而@Configuration是因为配置了PropertySourcesPlaceholderConfigurer,一般情况下不需要自己配置,除非默认的规则不满足,需要自己定制。

  • 可配置缺省值。 如 “${testbean.name:zhangsan}”。 如果未设置缺省值,取不到的情况下会抛出IllegalArgumentException异常。

  • 同一个属性项,后注册的会覆盖前面的,优先级更高。

以下是一个简单示例:

  • 在classpath下新增一个配置文件:application.properties
weather=sunning
wind=5
  • propertySource java config配置示例
package win.elegentjs.spring.ioc.propertysource;import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration
@PropertySource({"classpath:application.properties"})
@ToString
public class MyPropertySourceConfig {@Value("${weather}")private String weather;@Value("${wind}")private Integer wind;
}
  • 测试,查看结果
package win.elegentjs.spring.ioc.propertysource;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Slf4j
public class MyPropertySourceSample {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(MyPropertySourceConfig.class);MyPropertySourceConfig config = context.getBean(MyPropertySourceConfig.class);log.info("==> config: {}", config);}
}// result:
2021-05-31 19:38:35.508 [main] INFO  w.e.s.ioc.propertysource.MyPropertySourceSample-==> config: MyPropertySourceConfig(weather=sunning, wind=5)

#{…} vs ${…}

${}用于从属性配置文件中获取属性值。
#{}里面可以写SpEL表达式, 如#{T(java.lang.Math.random}, #{‘Hello world’.bytes.length}。 类似于OGNL。

两者可以混用,如:#{${…}.split(’,’)}
但需要注意:必须#{}在外面,${}在里面, 因为${}会优先解析

小结

本节学习了如何使用@Value加载属性值,属性值可以来源于外部资源文件,也可以来自内部的属性,spEL。
学习了如何使用@PropertySource加载外部配置文件。至于背后的原理部分如Environment, PropertySourcesPlaceholderConfigurer等后面会开专门的章节分析。

11. spring-容器: @Value, @PropertySource详解相关推荐

  1. java图片填充父容器_java相关:spring的父子容器及配置详解

    java相关:spring的父子容器及配置详解 发布于 2020-5-26| 复制链接 本篇文章主要介绍了spring的父子容器及配置详解,详细的介绍了spring父子容器的概念.使用场景和用法,有兴 ...

  2. Spring EL表达式使用详解

    Spring EL表达式使用详解 什么是Spring EL表达式 注入字面值 注入操作系统(OS)的属性 注入properties配置文件中数据 Bean属性调用 Bean方法调用 T运算符 构造器 ...

  3. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  4. SpringBoot2.1.5(16)--- Spring Boot的日志详解

    SpringBoot2.1.5(16)--- Spring Boot的日志详解 市面上有许多的日志框架,比如 JUL( java.util.logging), JCL( Apache Commons ...

  5. Spring定时器corn表达式详解

    1.结构 Spring定时器corn表达式详解 2.各字段的含义 字段 允许值 允许的特殊字符 秒 0~59 - * / 分 0~59 - * / 小时 0~23 - * / 日期 1~31 - * ...

  6. Spring包含JAR的详解

    一.Spring 常用包的说明 spring.jar :  包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and ...

  7. Spring 集成与分片详解

    1.Spring集成与分片详解 1.1pom依赖 1.2application.properties 定义配置类和任务类中要用到的参数 1.3创建任务 创建任务类,加上@Component注解 1.4 ...

  8. spring依赖注入原理详解(转载)

    spring依赖注入原理详解----转载 所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它.所 ...

  9. Spring之Joinpoint类详解

    说明 Joinpoint是AOP的连接点.一个连接点代表一个被代理的方法.我们从源码角度看连接点有哪些属性和功能. 源码 /** Copyright 2002-2016 the original au ...

最新文章

  1. react native windows 搭建(完整版)
  2. 【网络安全】一次应急实战经验思路分享
  3. mysql的内连接查询
  4. 一张大图总结数据结构与算法
  5. C#多线程编程系列(二)- 线程基础
  6. Power BI 数据可视化软件实现共享报表
  7. LeetCode——1710. 卡车上的最大单元数
  8. 怎样为企业挑选正确的EDR解决方案
  9. java 蓝桥杯 求先序排列
  10. 罗永浩确认12月初开发布会 不是手机也不是电子烟
  11. MyCat分布式数据库集群架构工作笔记0008---Mycat主--从复制原理
  12. 标准IO库fgets和fputs对一个文本文件的读写操作
  13. 【sping揭秘】18、使用spring访问数据
  14. 地图编辑器怎样炼成的
  15. mount挂载不上,不提示任何信息
  16. 回顾2017展望2018
  17. iOS15.4 Beta4 新测试版推送,新增反跟踪功能
  18. 如何在 Windows 上安装 ONLYOFFICE 文档 v7.2
  19. mysql 中添加和删除字段
  20. 正则表达式学习的一天

热门文章

  1. Linux下安装intel数学库Math Kernel Library(MKL)
  2. php实现图形计算器
  3. AT24C02的IIC通信
  4. Android实现高德地图定位详细流程
  5. Ubuntu、Win10双系统安装(GPT磁盘格式)
  6. 5.65寸7色墨水屏NFC方案 NFC彩色墨水屏方案 5.65寸7色桌牌方案 彩色墨水屏NFC无源方案 5.65寸七色无源NFC相框 5.65寸7色相框
  7. Learn Git Branching 学习笔记(高级话题篇)
  8. 想玩玩ometv了,挑战挑战自己(连不上去的解决方法---苹果和安卓)
  9. 基于J2EE的房屋租赁系统的设计与实现.rar(论文+项目源码+数据库文件)
  10. 实现商城的列表页与详情页