@Value注解可以标注在字段、方法、参数以及注解上,而且在程序运行期间生效。
通过@Value注解将外部的值动态注入到bean的属性中,一般有如下这几种情况:
注入普通字符串
@Value("NNN") private String name; // 注入普通字符串
注入操作系统属性
@Value("#{systemProperties[‘os.name‘]}") private String systemPropertiesName; // 注入操作系统属性
注入SpEL表达式结果
@Value("#{ T(java.lang.Math).random() * 100.0 }") private double randomNumber; //注入SpEL表达式结果
注入其他bean中属性的值
@Value("#{person.name}") private String username; // 注入其他bean中属性的值,即注入person对象的name属性中的值
注入文件资源
@Value("classpath:/config.properties") private Resource resourceFile; // 注入文件资源
注入URL资源
@Value("http://www.baidu.com") private Resource url; // 注入URL资源
#{}
在外面,${}
在里面说明 | 举例 | |
${···}的用法 | {}里面的内容必须符合SpEL表达式,通过@Value("${spelDefault.value}")我们可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,那么就会报错。不过,我们可以通过赋予默认值来解决这个问题。 |
@Value("${author.name:meimeixia}") private String name; |
#{···}的用法 | {}里面的内容同样也是必须符合SpEL表达式。例如, |
// SpEL:调用字符串Hello World的concat方法 @Value("#{‘Hello World‘.concat(‘!‘)}") private String helloWorld; // SpEL:调用字符串的getBytes方法,然后再调用其length属性 @Value("#{‘Hello World‘.bytes.length}") private String helloWorldBytes; |
混合使用 |
// SpEL:传入一个字符串,根据","切分后插入列表中, #{}和${}配合使用时,注意不能反过来${}在外面,而#{}在里面 @Value("#{‘${server.name}‘.split(‘,‘)}") private List<String> severs; 上面片段的代码的执行顺序:通过 在上文中 // SpEL:注意不能反过来,${}在外面,而#{}在里面,因为这样会执行失败 @Value("${#{‘HelloWorld‘.concat(‘_‘)}}") private List<String> severs2; 答案是不能。因为Spring执行 |
从@PropertySource的源码中可以看出,我们可以通过@PropertySource注解指定多个properties文件,使用的形式如下所示。
@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的属性注入值。
这里使用的@PropertySource(value={"classpath:/person.properties"})注解就相当于XML配置文件中使用的<context:property-placeholder location="classpath:person.properties" />。
MainConfigOfPropertyValues | Person |
package com.meimeixia.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import com.meimeixia.bean.Person; // 使用@PropertySource读取外部配置文件中的key/value保存到运行的环境变量中,加载完外部的配置文件以后,使用${}取出配置文件中的值 @PropertySource(value={"classpath:/person.properties"}) @Configuration public class MainConfigOfPropertyValues { @Bean public Person person() { return new Person(); } } |
@Value("${person.nickName}") private String nickName; // 昵称 |
使用@PropertySource注解读取外部配置文件中的key/value之后,是将其保存到运行的环境变量中了,所以我们也可以通过运行环境来获取外部配置文件中的值。
IOCTest_PropertyValue | 结果 |
@Test public void test01() { printBeans(applicationContext); System.out.println("==================="); Person person = (Person) applicationContext.getBean("person"); System.out.println(person); ConfigurableEnvironment environment = applicationContext.getEnvironment(); String property = environment.getProperty("person.nickName"); System.out.println(property); // 关闭容器 applicationContext.close(); } |
![]() |
Spring组件的自动装配就是Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。
默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);
如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao");
@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
自动装配默认一定要将属性赋值好,没有就会报错,可以使用@Autowired(required=false);
@Primary:让spring进行自动装配的时候,默认使用首选的bean,也可以继续使用@Qualifier指定需要装配的bean的名字
@Autowired是根据类型进行自动装配的,如果需要按名称进行装配,那么就需要配合@Qualifier注解来使用了。
在Spring中使用注解时,常常会使用到@Autowired这个注解,它默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口而言,可能会有几种不同的实现类,而在默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。
@Resource注解是Java规范里面的,也可以说它是JSR250规范里面定义的一个注解。该注解默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,那么默认取字段名将其作为组件的名称在IOC容器中进行查找,如果注解写在setter方法上,那么默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的一点是,如果name属性一旦指定,那么就只会按照名称进行装配。
@Resource注解和@Autowired注解的功能是一样的,都能实现自动装配,只不过@Resource注解默认是按照组件名称(即属性的名称)进行装配的。虽然@Resource注解具备自动装配这一功能,但是它是不支持@Primary注解优先注入的功能的,而且也不能像@Autowired注解一样能添加required=false属性。
@Inject注解也是Java规范里面的,也可以说它是JSR330规范里面定义的一个注解。该注解默认是根据参数名去寻找bean注入,支持Spring的@Primary注解优先注入,@Inject注解还可以增加@Named注解指定要注入的bean。
@Inject注解和@Autowired注解的功能是一样的,都能实现自动装配,而且它俩都支持@Primary注解优先注入的功能。只不过,@Inject注解不能像@Autowired注解一样能添加required=false
属性,因为它里面没啥属性。
不同点
相同点
在容器中如果存在同一类型的多个组件,那么可以使用@Profile注解标识要获取的是哪一个bean。也可以说@Profile注解是Spring为我们提供的可以根据当前环境,动态地激活和切换一系列组件的功能。这个功能在不同的环境使用不同的变量的情景下特别有用,例如,开发环境、测试环境、生产环境使用不同的数据源,在不改变代码的情况下,可以使用这个注解来动态地切换要连接的数据库。
原文:https://www.cnblogs.com/nxf-rabbit75/p/14619864.html