SpringBoot注解---2.组件赋值
一、@Value
1.作用范围
@Value注解可以标注在字段、方法、参数以及注解上,而且在程序运行期间生效。
2.用法
通过@Value注解将外部的值动态注入到bean的属性中,一般有如下这几种情况:
注入普通字符串
1 2 | @Value ( "NNN" ) private String name; // 注入普通字符串 |
注入操作系统属性
1 2 | @Value ( "#{systemProperties['os.name']}" ) private String systemPropertiesName; // 注入操作系统属性 |
注入SpEL表达式结果
1 2 | @Value ( "#{ T(java.lang.Math).random() * 100.0 }" ) private double randomNumber; //注入SpEL表达式结果 |
注入其他bean中属性的值
1 2 | @Value ( "#{person.name}" ) private String username; // 注入其他bean中属性的值,即注入person对象的name属性中的值 |
注入文件资源
1 2 | @Value ( "classpath:/config.properties" ) private Resource resourceFile; // 注入文件资源 |
注入URL资源
1 2 | @Value ( "http://www.baidu.com" ) private Resource url; // 注入URL资源 |
3.@Value中#{···}和${···}的区别
- #{...}:用于执行SpEl表达式,并将内容赋值给属性
- ${...}:主要用于加载外部属性文件中的值
- ${...}和#{...}:可以混合使用,但是必须
#{}
在外面,${}
在里面
说明 | 举例 | |||||
${···}的用法 | {}里面的内容必须符合SpEL表达式,通过@Value("${spelDefault.value}")我们可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,那么就会报错。不过,我们可以通过赋予默认值来解决这个问题。 |
|
||||
#{···}的用法 | {}里面的内容同样也是必须符合SpEL表达式。例如, |
|
||||
混合使用 |
上面片段的代码的执行顺序:通过 在上文中
答案是不能。因为Spring执行 |
二、@PropertySource加载配置文件
1.作用
从@PropertySource的源码中可以看出,我们可以通过@PropertySource注解指定多个properties文件,使用的形式如下所示。
1 2 3 4 | @PropertySource (value={ "classpath:/person.properties" , "classpath:/car.properties" }) 在 @PropertySource 注解的上面标注了如下的注解信息。这表示我们也可以使用 @PropertySources 注解来指定properties配置文件。 @Repeatable (PropertySources. class ) |
通过@PropertySource注解可以将properties配置文件中的key/value存储到Spring的Environment中,Environment接口提供了方法去读取配置文件中的值,参数是properties配置文件中定义的key值。当然了,也可以使用@Value注解用${}占位符为bean的属性注入值。
2.使用注解方式获取值
这里使用的@PropertySource(value={"classpath:/person.properties"})注解就相当于XML配置文件中使用的<context:property-placeholder location="classpath:person.properties" />。
MainConfigOfPropertyValues | Person | ||||
|
|
3.使用Environment获取值
使用@PropertySource注解读取外部配置文件中的key/value之后,是将其保存到运行的环境变量中了,所以我们也可以通过运行环境来获取外部配置文件中的值。
IOCTest_PropertyValue | 结果 | ||
|
![]() |
三、自动装配组件
Spring组件的自动装配就是Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。
1.@Autowired
默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);
如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao");
@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
自动装配默认一定要将属性赋值好,没有就会报错,可以使用@Autowired(required=false);
@Primary:让spring进行自动装配的时候,默认使用首选的bean,也可以继续使用@Qualifier指定需要装配的bean的名字
2.@Qualifier
@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,那么就需要配合@Qualifier注解来使用了。
3.@Primary
在Spring中使用注解时,常常会使用到@Autowired这个注解,它默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口而言,可能会有几种不同的实现类,而在默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。
4.@Resource
@Resource注解是Java规范里面的,也可以说它是JSR250规范里面定义的一个注解。该注解默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,那么默认取字段名将其作为组件的名称在IOC容器中进行查找,如果注解写在setter方法上,那么默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的一点是,如果name属性一旦指定,那么就只会按照名称进行装配。
@Resource注解和@Autowired注解的功能是一样的,都能实现自动装配,只不过@Resource注解默认是按照组件名称(即属性的名称)进行装配的。虽然@Resource注解具备自动装配这一功能,但是它是不支持@Primary注解优先注入的功能的,而且也不能像@Autowired注解一样能添加required=false属性。
5.@Inject
@Inject注解也是Java规范里面的,也可以说它是JSR330规范里面定义的一个注解。该注解默认是根据参数名去寻找bean注入,支持Spring的@Primary注解优先注入,@Inject注解还可以增加@Named注解指定要注入的bean。
@Inject注解和@Autowired注解的功能是一样的,都能实现自动装配,而且它俩都支持@Primary注解优先注入的功能。只不过,@Inject注解不能像@Autowired注解一样能添加required=false
属性,因为它里面没啥属性。
6.@Resource和@Inject俩注解与@Autowired注解的区别
不同点
- @Autowired是Spring中的专有注解,而@Resource是Java中JSR250规范里面定义的一个注解,@Inject是Java中JSR330规范里面定义的一个注解
- @Autowired支持参数required=false,而@Resource和@Inject都不支持
- @Autowired和@Inject支持@Primary注解优先注入,而@Resource不支持
- @Autowired通过@Qualifier指定注入特定bean,@Resource可以通过参数name指定注入bean,而@Inject需要通过@Named注解指定注入bean
相同点
- 三种注解都可以实现bean的自动装配。
四、Profile
在容器中如果存在同一类型的多个组件,那么可以使用@Profile注解标识要获取的是哪一个bean。也可以说@Profile注解是Spring为我们提供的可以根据当前环境,动态地激活和切换一系列组件的功能。这个功能在不同的环境使用不同的变量的情景下特别有用,例如,开发环境、测试环境、生产环境使用不同的数据源,在不改变代码的情况下,可以使用这个注解来动态地切换要连接的数据库。
- @Profile注解不仅可以标注在方法上,也可以标注在配置类上。
- 如果@Profile注解标注在配置类上,那么只有是在指定的环境的时候,整个配置类里面的所有配置才会生效。
- 如果一个bean上没有使用@Profile注解进行标注,那么这个bean在任何环境下都会被注册到IOC容器中,当然了,前提是在整个配置类生效的情况下。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
2019-04-05 pandas处理时间序列(1):pd.Timestamp()、pd.Timedelta()、pd.datetime( )、 pd.Period()、pd.to_timestamp()、datetime.strftime()、pd.to_datetime( )、pd.to_period()
2019-04-05 修改jupyter notebook的默认打开地址