SpringBoot-注解@Autowired,@Resource,@Qualifier,@Primary
参考文献
@Autowired
1 | // org.springframework.beans.factory.annotation.Autowired |
使用场景
@Autowired
标注在构造器上,通过构造器注入依赖对象
@Autowired
标注在方法上,通过方法注入依赖的对象
@Autowired
标注在setter方法上,通过setter方法注入
@Autowired
标注在方法参数上
@Autowired
用在字段上
@Autowired
标注字段,多个候选者的时候,按字段名称注入
将指定类型的所有bean,注入到Collection、Map中
@Autowire
源码分析
-
@Autowired
注解的原理用一句话讲明:就是先从IoC容器中根据类型找到所有符合的Bean,然后再根据@Primary、@Order、@PriorityOrder
或Spring默认规则挑选出最符合的Bean,利用反射注入到字段中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
*/
public AutowiredAnnotationBeanPostProcessor() {
// 后置处理器将处理@Autowire注解
this.autowiredAnnotationTypes.add(Autowired.class);
// 后置处理器将处理@Value注解
this.autowiredAnnotationTypes.add(Value.class);
try {
// 后置处理器将处理javax.inject.Inject JSR-330注解
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}1
按类型找->通过限定符@Qualifier过滤->@Primary->@Priority->根据名称找(字段名称或者参数名称)
- 先按类型找,然后按名称找
触发方式
-
Spring容器在每个Bean实例化之后,调用
AutowiredAnnotationBeanPostProcessor
的postProcessMergedBeanDefinition
方法,查找该Bean是否有@Autowired
注解。1
2
3
4
5
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
} -
Spring在每个Bean实例化的时候,调用
populateBean
进行属性注入的时候,即调用postProcessProperties
方法,查找该Bean是否有@Autowired
注解。1
2
3
4
5org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
--> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
--> org.springframework.beans.factory.annotation.InjectionMetadata#inject
--> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
--> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
/**
* 该方法就是在属性注入populateBean中调用的pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 的具体实现之一。
* @param pvs the property values that the factory is about to apply (never {@code null})
* @param bean the bean instance created, but whose properties have not yet been set
* @param beanName the name of the bean
* @return
*/
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 获取指定类中autowire相关注解的元信息
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 对Bean的属性进行自动注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, { PropertyValues pvs)
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
// 首先从容器中查找是否有给定类的autowire相关注解元信息
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
// 解析给定类autowire相关注解元信息
metadata.clear(pvs);
}
// 解析给定类autowire相关注解元信息
metadata = buildAutowiringMetadata(clazz);
// 将得到的给定类autowire相关注解元信息存储在容器缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}1
2
3
4
5
6
7
8
9
10
11
12
13// org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, String beanName, PropertyValues pvs)throws Throwable {
// 要注入的字段集合
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历每个字段 注入
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, String beanName, PropertyValues pvs)throws Throwable {
// 获取要注入的字段
Field field = (Field) this.member;
Object value;
// 如果字段的值有缓存
if (this.cached) {
try {
// 从缓存中获取字段值value
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
// 没有缓存
else {
value = resolveFieldValue(field, bean, beanName);
}
// 如果字段值不为null
if (value != null) {
// 显式使用JDK的反射机制,设置自动的访问控制权限为允许访问
ReflectionUtils.makeAccessible(field);
// 为字段赋值
field.set(bean, value);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38// org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject
protected void inject(Object bean, String beanName, PropertyValues pvs)throws Throwable {
// 如果属性被显式设置为skip,则不进行注入
if (checkPropertySkipping(pvs)) {
return;
}
// 获取注入元素对象
Method method = (Method) this.member;
Object[] arguments;
// 如果容器对当前方法缓存
if (this.cached) {
try {
// 获取缓存中指定Bean名称的方法参数
arguments = resolveCachedArguments(beanName);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
arguments = resolveMethodArguments(method, bean, beanName);
}
}
// 如果没有缓存
else {
arguments = resolveMethodArguments(method, bean, beanName);
}
// 如果方法参数依赖对象不为null
if (arguments != null) {
try {
// 使用JDK的反射机制,显式设置方法的访问控制权限为允许访问
ReflectionUtils.makeAccessible(method);
// 调用Bean的指定方法
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
} -
最核心的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter)throws BeansException {
// 注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 针对给定的工厂给定一个快捷实现的方式,例如考虑一些预先解析的信息
// 在进入所有bean的常规类型匹配算法之前,解析算法将首先尝试通过此方法解析快捷方式。
// 子类可以覆盖此方法
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 获取字段属性的类型
Class<?> type = descriptor.getDependencyType();
// 用于支持Spring的注解@Value
// org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.getSuggestedValue
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
// 解析Value值
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 通过转换器将bean的值转换为对应的type类型
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// 如果标识@Autowired注解的属性是复合类型,如Array,Collection,Map
// 从这个方法获取@Autowired里的
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根据属性类型找到BeanFactory中所有类型的匹配bean
// 返回值的构成: key=匹配的beanName,value=beanName对应的实例化后的bean(通过getBean(beanName)返回)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
// 如果没有符合该类型的Bean
if (matchingBeans.isEmpty()) {
// 没有找到,检验 @Autowired的require是否为true
if (isRequired(descriptor)) {
// 抛出异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 如果符合该类型的Bean有多个
if (matchingBeans.size() > 1) {
// 选出优先级最高的依赖
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// 判断是否必须注入 isRequired(descriptor)
// 或者注解的属性类型并不是可以接受多个Bean的类型,如数组,Map,集合 !indicatesMultipleBeans(type)
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
// 抛出异常
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
@Qualifier
- 可以在依赖注入查找候选者的过程中对候选者进行过滤
使用场景
用在类上
-
用在类上,可以理解为给通过
@Qulifier
给这个bean打了一个标签。1
2
3
4
5
6
7import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
public class TestClass {
}
@Autowired
结合@Qulifier
指定注入的bean
- 被注入的类型有多个的时候,可以使用
@Qulifier
来指定需要注入那个bean
,将@Qulifier
的value
设置为需要注入bean
的名称
源码分析
-
处理类
1
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver
-
入口方法
1
2
3
4
5
6org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
--> org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
--> org.springframework.beans.factory.support.DefaultListableBeanFactory#isAutowireCandidate(java.lang.String, org.springframework.beans.factory.config.DependencyDescriptor)
--> org.springframework.beans.factory.support.DefaultListableBeanFactory#isAutowireCandidate(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, org.springframework.beans.factory.config.DependencyDescriptor, org.springframework.beans.factory.support.AutowireCandidateResolver)
--> org.springframework.beans.factory.support.AutowireCandidateResolver#isAutowireCandidate
--> org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate
@Resource
源码分析
-
处理类
1
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
1
2
3
4
5
6
7
8
9
10
11
12
13
14static {
resourceAnnotationTypes.add(Resource.class);
webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
if (webServiceRefClass != null) {
resourceAnnotationTypes.add(webServiceRefClass);
}
ejbClass = loadAnnotationType("javax.ejb.EJB");
if (ejbClass != null) {
resourceAnnotationTypes.add(ejbClass);
}
}
@Autowired
和@Resource
的区别
@Autowired
和@Resource
都可以用来装配bean,都可以用于字段或setter方法。@Autowired
默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许 null 值,可以设置它的 required 属性为 false。@Resource
默认按名称装配,当找不到与名称匹配的bean时才按照类型进行装配。名称可以通过name属性指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,当注解写在 setter 方法上时,默认取属性名进行装配。- 注意:如果name属性一旦指定,就只会按照名称进行装配。
@Resource
装配顺序- 如果同时指定name和 type,则从容器中查找唯一匹配的bean装配,找不到则抛出异常;
- 如果指定name属性,则从容器中查找名称匹配的bean装配,找不到则抛出异常;
- 如果指定 type 属性,则从容器中查找类型唯一匹配的bean装配,找不到或者找到多个抛出异常;
- 如果不指定,则自动按照 byName 方式装配,如果没有匹配,则回退一个原始类型进行匹配,如果匹配则自动装配。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!