注解-属性赋值和自动装配
对于属性的赋值以及如何自动装配是我们在实际编程中经常要实现的功能,spring为我们提供了应有尽有的方式来实现,特别地方便,用好spring还是先用好spring给我们提供的注解开始。理解它们的不同之处也是面试中常问的点。
1. @Value赋值
给一个Person
:
1 |
|
注册到容器中:
1 |
|
启动查看一下:
1 |
|
那么在以前写配置文件的时候,我们可以在xml中给属性注入值。
1 | <bean id="person" class="com.swg.bean.Person"> |
那么现在的注解可以实现这样的功能吗?
- @Value
1 | "hello") ( |
- @SpEL表达式
1 | "#{20-6}") ( |
2. @PropertySource加载外部配置文件
${}注入属性文件的值
- 新建一个配置文件
db.properties
,在里面写:
person.nickname = hello
- 首先在配置类中声明要引入的配置文件:
@PropertySource(value = “classpath:/db.properties”)
- 然后再引入:
1 | "${person.nickname}") ( |
- 以前在用xml的时候,是这样引入这个值的:
1 | <context:property-placeholder location="db.properties"/> |
自动装配:spring利用依赖注入DI,完成对IOC容器中各个组件依赖关系赋值
3. @Autowired & @Qualifier & @Primary
@Autowired
:默认是按照类型去容器中找相应的组件。找到就赋值。
applicationContext.getBean(Person.class)
如果找到多个相同类型的组件,再将属性名(默认是小写字母开头的id或者用@Bean("xxx")
中的xxx为属性名)作为组件的id去容器中查找。
applicationContext.getBean(“person”)
所以,最好名字不一样。
如果有多个相同类型的组件,可以用@Qualifier("xxx")
可以指定装配的id,而不是属性名。
@Primary:让spring自动装配的时候,默认使用首选的bean;但是如果@Qualifier明确指定了要装配哪一个,还是以@Qualifier为准。
默认,如果容器中没有这个组件,那么@Autowired就会报错。那么可不可以有就装配,没有就算了呢?
@Autowired(required=false)
4. @Resource & @Inject
这两个都是java规范的注解。
- @Resource–JSR250
默认是按照组件名称进行装配的。没有能支持@Primary
和@Autowired(required=false)
这个功能。
- @Inject–JSR330
还需要一个依赖:javax.inject
和@Autowired
差不多,但是比@Autowired
稍弱,虽然支持@Primary
,但是没有required=false
@Autowired
是spring
定义的,后两者都是java的规范。
那么这些自动装配功能的注解是如何实现的呢?原来是AutowiredAnnotationBeanPostProcessor
来实现的。
5. 方法、构造器位置的自动装配
@Autowired
能标注的位置:构造器、参数、方法、属性
- 写在属性上面:
1 |
|
- 写在方法上:
1 | //spring容器创建当前对象,就会调用方法,完成赋值; |
- 写在构造器上:
因为注册到ioc容器的组件,容器启动的时候回调用无参构造器创建对象,然后在进行初始化赋值等操作。
1 | //放在有参构造器上面,这样容器启动的时候就会调用这个有参构造器 |
如果当前类只有一个有参构造器,@Autowired是可以省略的。
- 写在参数前面:
1 | //car都是从容器中获取的 |
6. Aware注入Spring底层组件及原理
自定义组件想使用spring容器底层的一些组件,比如applicationContext
或者beanFactory
等。只需要实现xxxAware
接口即可。在创建对象的时候,会调用接口规定的方法注入相关组件。
比如ApplicationContextAware
:
1 | public interface ApplicationContextAware extends Aware { |
那么我们可以将它传进来的ApplicationContext
保存一下:
1 | public class Snail implements ApplicationContextAware{ |
7. @Profile环境搭建和根据环境注册bean
spring为我们提供的可用根据当前环境,动态地激活和切换一系列组件的功能。
开发环境、测试环境、生产环境,可能用不同的数据源,那么不想改动很多代码的话,就可以用@Profile
切换。
@Profile
:指定组件在哪个环境的情况下才能被注册到容器中,不指定,在任何环境下都能注册这个组件。
加了@Profile的@Bean,只有这个环境被激活的时候才能注册到容器中,但是有一个默认注册的:@Profile(“default”)
那么如何指定某个环境注册到spring容器中呢?
- 第一种方式:使用命令行动态参数
VM arguments: -Dspring.profiles.active=test
- 第二种方式:代码
1 | //1,创建一个applicationContext |
8. 总结
@Value
赋值@PropertySource
加载外部配置文件@Autowired
&@Qualifier
&@Primary
&@Resource
&@Inject
以及@Autowired
在方法、构造器、参数位置的自动装配- 通过实现
Aware
接口可以注入Spring
底层的一些组件 @Profile
环境搭建和根据环境注册bean