spring中可以通过@Autowired
注解注入依赖到bean的属性中,简单好用,但是出现多个类型相同的依赖,spring如何处理呢,现在开始了解下@Autowired
注解处理依赖注入的原理。首先实例化之后,AutowiredAnnotationBeanPostProcessor
处理器会找出存在@Autowired或@Value注解的字段,static不会处理,然后根据属性required判断是否需要注入。
// AutowiredAnnotationBeanPostProcessor
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//找出使用了@Autowired或@Value注解的属性字段
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//static不处理,
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//根据属性required判断是否需要注入
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
之后在postProcessProperties()
方法中完成Bean的属性注入。逻辑到容器中根据类型找到要注入的bean,然后缓存下来,最后将找到的bean以反射写到属性。
// AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
//优先从缓存中获取,可以根据beanName从Map<String, InjectionMetadata> injectionMetadataCache获取
//再从AutowiredFieldElement中获取,这样可以防止重复创建相同的AutowiredFieldElement
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
......
//到容器中找到要注入的bean
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
//缓存下来
......
registerDependentBeans(beanName, autowiredBeanNames);
......
}
}
//反射注入
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
如果注入的类型是Optional
,spring找到bean后会用Optional
进行封装;如果注入的是ObjectFactory
和ObjectProvider
则生成DependencyObjectProvider注入,之后再通过getObject
获取实例;这些都不常见,用的最多的应该是正常的bean注入,先判断是否为存在@Lazy
注解的懒加载模式,是的话就生成代理对象注入,之后getTarget
获取真实的bean;都不是就进入正常的bean注入逻辑doResolveDependency
。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
根据类型找到依赖的Bean是在doResolveDependency()
方法中实现的,分两类考虑,如果是把bean注入到一个集合中就使用resolveMultipleBeans(),如果是单个bean的话就findAutowireCandidates(),当发现多个时需要在determineAutowireCandidate()进行处理,接下来就以注入单个bean为例看,因为开发中大部分都是注入单个bean的实例对象。
// DefaultListableBeanFactory
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
......//处理@Value注解
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
......
//要注入多个bean到一个集合
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 注入单个bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
......
String autowiredBeanName;
Object instanceCandidate;
//从多个bean中找到合适的bean
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
......
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();
}
}
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//到容器中找到所需类型的bean的name集合
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
//优先从缓存中根据依赖类型获取依赖的bean实例对象
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//获取除自身外的其他bean
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
......
if (result.isEmpty() && !multiple) {
// 没有获取到其他bean的话看看是不是注入自身
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
找到候选依赖后,需要决定注入的依赖。优先选择使用@Primary注解的bean,找不到的话根据@Priority注解选择,值越小优先级越高,否则根据name匹配,即根据字段名选择名字相同的依赖bean。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//优先使用@Primary注解的bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//@Priority注解的值越小优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
//根据bean的name进行匹配
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}