Bean的属性赋值和自动注入
一、Bean的属性赋值
Bean的属性赋值可以使用**@Value**,其支持多种方式如下:
1)基本数值
2)可以写SpEL表达式,#{}
3)可以写${},取出配置文件中的值
@Data
public class Property01_Value {
/**
* @author luomengwei
* 1)基本数值
* 2)可以写SpEL表达式,#{}
* 3)可以写${},取出配置文件中的值
**/
@Value("wei")
String name;
@Value("#{20-2}")
Integer age;
@Value("${english.name}")
String englishName;
}
@PropertySource注解,可以用来读取外部配置文件中的k/v保存到环境变量中。
@PropertySource(value = {"classpath:/propertyvalue.properties"})
//@PropertySources() 多个配置文件
@Configuration
public class Property02_PropertySource {
@Bean("Property01")
Property01_Value property01_value() {
return new Property01_Value();
}
}
二、Bean的自动注入
2.1 注解自动注入
**@Autowired:**自动注入
1)默认按照类型去容器寻找对应组件:XXXX.class
2)如果找到多个相同类型组件,在按照 属性名 称作为ID去查找
3)@Qualifier(“xxxService2”),使用@Qualifier指定需要装配的组件ID,而不是使用属性名
4)自动装配默认一定需要将属性赋值好,没有就会报错
可以使用 @Autowired(required = false)
5)@Primary标注首选bean 在多个类型组件是,未明确指定组件装配ID时,默认使用首选的bean
Spring还支持 @Resource(JSR250) 和 @Inject(JSR330) JSR:Java规范
**@Resource:**可以和 @Autowired 一样支持自动装配功能,默认按照属性名称进行装配
不支持 Spring的注解指定(@Qualifier),可以使用 @Resource(name = “xxxService2”) 指定组件ID
@Inject:需要导入 javax.inject 的依赖,和 @Autowired 功能一样,但其没有属性,不支持更多的功能如:required = false
那关于 @AutoWire 和 @Resource 的区别是什么呢?
1、@Autowired 是 Spring定义的;@Resource 和 @Inject 是Java规范。
2、依赖查找的顺序是不一样的
依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。查找有分为两种实现:按名称(byName)查找或按类型(byType)查找,其中 @Autowired 和 @Resource 都是既使用了名称查找又使用了类型查找,但二者进行查找的顺序却截然相反。
- @Autowired 先根据类型(byType)查找,如果存在多个(Bean)再根据名称(byName)进行查找
- @Resource 先根据名称(byName)查找,如果(根据名称)查找不到,再根据类型(byType)进行查找
3、两者所支持的参数不一样
@Autowired只包含一个参数:required,表示是否开启自动注入,默认是true,要求依赖对象必须存在,如果要允许null值,可以设置为false。
@Resource包含七个参数,其中最重要的两个参数是:name 和 type
4、作用域不同
@Autowired 可以用在方法、构造器、参数、属性;都是从容器中获取参数值
@Resource 只可以使用在field,setter方法上(只能是单个单数的setter方法)
2.2 xxxAware注入Spring容器底层组件
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext、BeanFactory、XXX)
自定义组件可实现 xxxAware,在创建对象的时候,调用接口规定的方法注入相关组件: Aware,把Spring底层的组件注入到自定义的bean中
xxxAware,如:ApplicationContextAware、EmbeddedValueResolverAware
@Component
public class AutoWire01_Aware implements ApplicationContextAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String value = resolver.resolveStringValue("你好${os.name},我是EmbeddedValueResolverAware,我的年龄为: #{20-2}");
System.out.println(value);
}
}
在【Bean的生命周期及扩展】篇章中有讲解过,@AutoWire和ApplicationContextAware均是依赖于后置处理器 BeanPostProcessor实现的,实现原理可详见该文章。
2.3 @Profile环境切换
@Profile环境切换:指定组件在哪个环境下能被注册到容器中,不指定,任何环境不能注册
1)加了环境标识的bean,只有这个环境被激活时才注册到容器中。默认是:default。
2)注解加在类上,只有是指定环境时,整个配置类里面的配置才生效。
@Configuration
public class AutoWire02_Profile {
@Profile("default")
@Bean("defaultSpringPeople")
SpringPeople defaultSpringPeople() {
return new SpringPeople("default", 16);
}
@Profile("dev")
@Bean("devSpringPeople")
SpringPeople devSpringPeople() {
return new SpringPeople("dev", 18);
}
@Profile("test")
@Bean("testSpringPeople")
SpringPeople testSpringPeople() {
return new SpringPeople("test", 20);
}
}
测试方法:
1、使用命令行参数:在虚拟机参数位置加载 -Dspring.profiles.active=test
2、代码的方式激活某环境
@Test
public void propertyTest() {
// 默认有参构造器,不能设置参数信息,直接创建了容器
//AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutoWire02_Profile.class);
// 1、创建 applicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test");
// 3、配置启动类
applicationContext.register(AutoWire02_Profile.class);
// 4、启动容器刷新
applicationContext.refresh();
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}