你所不知道的Spring的@Autowired实现细节分析

前言

相信很多Java开发都遇到过一个面试题:Resource和Autowired的区别是什么?这个问题的答案相信基本都清楚,但是这两者在Spring中是如何实现的呢?这就要分析Spring源码才能知道了。友情提示:本篇主要是讲解Autowired的实现原理,不会分析Spring初始化的过程,不熟悉的读者可以先阅读笔者之前的一篇文章《这一次搞懂Spring的Bean实例化原理》。

正文

在Spring Bean的整个创建过程中会调用很多BeanPostProcessor接口的的实现类:

上图是我整理的Spring Bean的创建过程及整个过程中各个BeanPostProcessor和回调的调用,右边相同颜色的连线代表是同一组调用,主要看到AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,前者就是支持 @Autowired和@Value注解,后者则是支持@PostConstruct、@PreDestroy、@Resource注解。先了解这两个Processor的作用,下面从头分析。

从图中可以看到,在createBeanInstance方法中会调用SmartInstantiationAwareBeanPostProcessor类型的determineCandidateConstructors,这个方法是做什么的呢?看代码:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
 ......
 // Candidate constructors for autowiring?
 //寻找当前正在实例化的bean中有@Autowired注解的构造函数
 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  //如果ctors不为空,就说明构造函数上有@Autowired注解
  return autowireConstructor(beanName, mbd, ctors, args);
 }
 ......

 // No special handling: simply use no-arg constructor.
 return instantiateBean(beanName, mbd);
 }

 protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
  throws BeansException {

 if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
   SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
   Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
   if (ctors != null) {
   return ctors;
   }
  }
  }
 }
 return null;
 }

createBeanInstance方法是去实例化Bean,而调用AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors的目的就是先去找到带有@Autowired注解的构造方法(自动注入有三种模式:属性、构造方法、普通方法),也就是通过构造方法注入,如果没有找到则通过反射调用无参构造实例化。平时我们基本上都是使用的属性注入,所以一般都不会进入determineCandidateConstructors方法,所以这里也不详细阐述,感兴趣的读者可自行看看。

接着回到doCreateBean方法中,就可以看到调用了applyMergedBeanDefinitionPostProcessors方法:

 protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof MergedBeanDefinitionPostProcessor) {
  /**
   * CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
   * AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
   */
  MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
  bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
  }
 }
 }

这个方法本质上就是调用MergedBeanDefinitionPostProcessor类型的postProcessMergedBeanDefinition方法,通过这个方法去收集@Autowired、@Resource等注解,这里主要分析AutowiredAnnotationBeanPostProcessor的实现:

 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
 InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
 metadata.checkConfigMembers(beanDefinition);
 }

 private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable 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.
 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) {
   metadata.clear(pvs);
   }
   //主要看这个方法
   metadata = buildAutowiringMetadata(clazz);
   this.injectionMetadataCache.put(cacheKey, metadata);
  }
  }
 }
 return metadata;
 }

 private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
 List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
 Class<?> targetClass = clazz;

 do {
  final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

  // 找到带有@Autowired注解的属性并封装为AnnotationAttributes
  ReflectionUtils.doWithLocalFields(targetClass, field -> {
  AnnotationAttributes ann = findAutowiredAnnotation(field);
  if (ann != null) {
   if (Modifier.isStatic(field.getModifiers())) {
   if (logger.isInfoEnabled()) {
    logger.info("Autowired annotation is not supported on static fields: " + field);
   }
   return;
   }
   boolean required = determineRequiredStatus(ann);
   currElements.add(new AutowiredFieldElement(field, required));
  }
  });

  // 找到带有@Autowired注解的方法并封装为AnnotationAttributes
  ReflectionUtils.doWithLocalMethods(targetClass, method -> {
  Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
  if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
   return;
  }
  AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
  if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
   if (Modifier.isStatic(method.getModifiers())) {
   if (logger.isInfoEnabled()) {
    logger.info("Autowired annotation is not supported on static methods: " + method);
   }
   return;
   }
   if (method.getParameterCount() == 0) {
   if (logger.isInfoEnabled()) {
    logger.info("Autowired annotation should only be used on methods with parameters: " +
     method);
   }
   }
   boolean required = determineRequiredStatus(ann);
   PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
   currElements.add(new AutowiredMethodElement(method, required, pd));
  }
  });

  elements.addAll(0, currElements);
  targetClass = targetClass.getSuperclass();
 }
 while (targetClass != null && targetClass != Object.class);

 return new InjectionMetadata(clazz, elements);
 }

收集的逻辑主要在findAutowiringMetadata方法中,层层调用后可以看到是通过findAutowiredAnnotation这个方法去找到带有@Autowired和@Value注解的属性和方法:

 private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

 public AutowiredAnnotationBeanPostProcessor() {
 this.autowiredAnnotationTypes.add(Autowired.class);
 this.autowiredAnnotationTypes.add(Value.class);
 try {
  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.
 }
 }

 private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
 if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
  for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
  AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
  if (attributes != null) {
   return attributes;
  }
  }
 }
 return null;
 }

最后将其封装为AutowiredFieldElement和AutowiredMethodElement对象的list并连同Class一起封装成InjectionMetadata返回,这就完成了相关注解的收集。

收集完成后在哪里使用呢?对Bean生命周期熟悉的读者都知道,之后就会进行依赖注入,自然相关的调用就在populateBean这个方法里:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

 ......

 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
  MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  // Add property values based on autowire by name if applicable.
  if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
  autowireByName(beanName, mbd, bw, newPvs);
  }
  // Add property values based on autowire by type if applicable.
  if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
  autowireByType(beanName, mbd, bw, newPvs);
  }
  pvs = newPvs;
 }

 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

 PropertyDescriptor[] filteredPds = null;

 //重点看这个if代码块,重要程度 5
 if (hasInstAwareBpps) {
  if (pvs == null) {
  pvs = mbd.getPropertyValues();
  }
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
   // 依赖注入过程,@Autowired的支持
   PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
   if (pvsToUse == null) {
   if (filteredPds == null) {
    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
   }

   // 老版本用这个完成依赖注入过程,@Autowired的支持
   pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
   if (pvsToUse == null) {
    return;
   }
   }
   pvs = pvsToUse;
  }
  }
 }
 if (needsDepCheck) {
  if (filteredPds == null) {
  filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  }
  checkDependencies(beanName, mbd, filteredPds, pvs);
 }

 // xml中<property>标签的依赖注入
 if (pvs != null) {
  applyPropertyValues(beanName, mbd, bw, pvs);
 }
 }

mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE

很多读者包括网上很多文章在看到这个判断时,都认为自动注入的逻辑就是这里,但实际上并不是,这里是自动注入没错,但却是针对以前xml配置,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
    default-autowire="byName">
 <bean id="a" class="com.A" autowire="byName"/>
 <bean id="b" class="com.B" autowire="byType"/>
</beans> 

头文件中的default-autowire属性就是开启全局自动注入,而bean标签上的autowire则是特定针对当前bean的,会覆盖全局配置。这样我们配置后,bean标签就无需配置prototype子标签,也能自动注入对应的对象。这些属性包含了以下几个值:

no:默认值。表示不进行自动注入。对应BeanDefinition中autowireMode的值为 0。

byName:根据名称进行自动注入。对应BeanDefinition中autowireMode的值为1。

byType:根据类型进行自动注入,如果容器中找到两个及以上符合该类型的Bean就将抛出异常。对应BeanDefinition中autowireMode的值为2。

constructor:等同于byType,只是当指定autowire=”constructor”时表示将通过构造方法根据类型进行自动注入。对应BeanDefinition中autowireMode的值为3。

这就是xml配置中的自动注入,而我们使用@Autowired注解时,BeanDefinition中autowireMode的值为 0,即表示不进行自动注入。插一句题外话,网上很多人在争论@Autowired是自动注入还是手动注入,我个人认为都算自动注入,不能说它没有进入这段逻辑就不能叫自动注入,只是它以另外一种方式实现了,至少也没有让我们自己手动new并设置属性。

那这另外一种方式是什么呢?就是下面这个代码干的事:

if (hasInstAwareBpps) {
 if (pvs == null) {
 pvs = mbd.getPropertyValues();
 }
 for (BeanPostProcessor bp : getBeanPostProcessors()) {
 if (bp instanceof InstantiationAwareBeanPostProcessor) {
  InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  // 依赖注入过程,@Autowired的支持
  PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  if (pvsToUse == null) {
  if (filteredPds == null) {
   filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  }

  // 老版本用这个完成依赖注入过程,@Autowired的支持
  pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  if (pvsToUse == null) {
   return;
  }
  }
  pvs = pvsToUse;
 }
 }
}

可以看到这里又是调用了InstantiationAwareBeanPostProcessor类型的postProcessProperties和postProcessPropertyValues方法,后者是老版本中的实现,已经废弃,所以直接看postProcessProperties,还是进入到AutowiredAnnotationBeanPostProcessor类中:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
 try {
  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;
 }

findAutowiringMetadata这个方法不陌生的,刚刚已经分析了,是去收集对应注解并封装为InjectionMetadata对象放入到缓存,这里就是从缓存中拿到值,注入则是通过inject实现的:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
 Collection<InjectedElement> checkedElements = this.checkedElements;
 Collection<InjectedElement> elementsToIterate =
  (checkedElements != null ? checkedElements : this.injectedElements);
 if (!elementsToIterate.isEmpty()) {
 for (InjectedElement element : elementsToIterate) {
  if (logger.isTraceEnabled()) {
  logger.trace("Processing injected element of bean '" + beanName + "': " + element);
  }
  if(element.isField) {
  Field field = (Field)element.member;
  System.out.println("==IOC/DI===beanName==" + beanName + "==field[" + field.getName() +"]-> getBean(" + field.getName() + ")");
  }
  element.inject(target, beanName, pvs);
 }
 }
}

最后就是调用element.inject实现注入,element我们刚刚也看到了,就是AutowiredFieldElement和AutowiredMethodElement,分别实现属性注入和方法注入,这里我们看最常用的属性注入就行了:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
 Field field = (Field) this.member;
 Object value;
 if (this.cached) {
 value = resolvedCachedArgument(beanName, this.cachedFieldValue);
 }
 else {
 DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
 desc.setContainingClass(bean.getClass());
 Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
 Assert.state(beanFactory != null, "No BeanFactory available");
 TypeConverter typeConverter = beanFactory.getTypeConverter();
 try {
  // 找到依赖对象
  value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
 }
 catch (BeansException ex) {
  throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
 }
 synchronized (this) {
  if (!this.cached) {
  if (value != null || this.required) {
   this.cachedFieldValue = desc;
   registerDependentBeans(beanName, autowiredBeanNames);
   if (autowiredBeanNames.size() == 1) {
   String autowiredBeanName = autowiredBeanNames.iterator().next();
   if (beanFactory.containsBean(autowiredBeanName) &&
    beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    this.cachedFieldValue = new ShortcutDependencyDescriptor(
     desc, autowiredBeanName, field.getType());
   }
   }
  }
  else {
   this.cachedFieldValue = null;
  }
  this.cached = true;
  }
 }
 }

 if (value != null) {
 ReflectionUtils.makeAccessible(field);
 field.set(bean, value);
 }
}

这段代码整体逻辑比较清晰,首先根据field创建一个依赖对象的抽象DependencyDescriptor对象,然后通过beanFactory.resolveDependency解析拿到对应的实例,最后通过反射注入即可。

因此我们主要看resolveDependency方法中做了什么:

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;
 }
}

一般情况下,都是走的else分支并调用doResolveDependency方法:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
 @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
 try {
 Object shortcut = descriptor.resolveShortcut(this);
 if (shortcut != null) {
  return shortcut;
 }

 Class<?> type = descriptor.getDependencyType();
 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
 if (value != null) {
  if (value instanceof String) {
  String strVal = resolveEmbeddedValue((String) value);
  BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
  value = evaluateBeanDefinitionString(strVal, bd);
  }
  TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  return (descriptor.getField() != null ?
   converter.convertIfNecessary(value, type, descriptor.getField()) :
   converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
 }

 // 有多个实现类需要注入,特指注入的是数组、集合或者Map
 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
 if (multipleBeans != null) {
  return multipleBeans;
 }

 // 找到依赖对象的所有实现类
 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
 if (matchingBeans.isEmpty()) {
  if (isRequired(descriptor)) {
  raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  }
  return null;
 }

 String autowiredBeanName;
 Object instanceCandidate;

 // 依赖的对象有多个实例
 if (matchingBeans.size() > 1) {
  // 根据@Primary、@Priority和名称依次进行匹配注入
  autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  if (autowiredBeanName == null) {
  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);
 }
 // 如果拿到的是class对象,通过getBean实例化返回
 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);
 }
}

这里面首先是通过 getAutowireCandidateResolver().getSuggestedValue(descriptor)拿到@Value注解的值,然后通过TypeConverter进行转换,默认可转换的类型是JDK和Spring内置的一些类型,自然不包含我们自定义的类,所以如果不进行扩展在@Autowired注入我们自定义类对象时同时使用@Value注解是会报错的。

接着是调用resolveMultipleBeans方法实现对Map、List、数组等属性的注入,本质上还是调用findAutowireCandidates方法找到所有的实现类的对象装入对应的集合数组中,所以直接看findAutowireCandidates:

protected Map<String, Object> findAutowireCandidates(
 @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  this, requiredType, true, descriptor.isEager());
 Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);

 ......

 for (String candidate : candidateNames) {
 if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
  addCandidateEntry(result, candidate, descriptor, requiredType);
 }
 }

 ......
 return result;
}

private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
 DependencyDescriptor descriptor, Class<?> requiredType) {

 if (descriptor instanceof MultiElementDescriptor) {
 Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
 if (!(beanInstance instanceof NullBean)) {
  candidates.put(candidateName, beanInstance);
 }
 }
 else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
  ((StreamDependencyDescriptor) descriptor).isOrdered())) {
 Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
 candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
 }
 else {
 candidates.put(candidateName, getType(candidateName));
 }
}

首先通过beanNamesForTypeIncludingAncestors方法拿到依赖类所有的实现类的beanName,然后调用addCandidateEntry将beanName及对应的实例或者Class对象放入到Map中。

接着回到doResolveDependency方法中:

if (matchingBeans.size() > 1) {
 // 根据@Primary、@Priority和名称依次进行匹配注入
 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
 if (autowiredBeanName == null) {
 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);
}
// 如果拿到的是class对象,通过getBean实例化返回
if (instanceCandidate instanceof Class) {
 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;

如果只有一个实例则直接返回该实例,如果实现类有多个则调用determineAutowireCandidate进行判断该使用哪一个实例对象,判断规则如下:

首先判断实现类上是否有@Primary注解,找到一个则返回当前实例,找到多个则报错。

若没有标注@Primary注解,则判断是否指定了优先级,且只能是通过@Priority注解指定的,@Order不支持。

上述都没有拿到合适的Bean则通过属性名称获取Bean。

拿到对应的实例后,最后进行反射注入即可。以上就是@Autowired的实现细节。

总结

本篇从源码角度详细分析了@Autowired的实现细节,只有真正阅读了源码才能了解更多的细节,在开发中更加清楚如何注入多个实例以及如何指定注入的优先级,同时在面试中也能更有理有据,而不是统一的大众回答,先根据byType,再根据byName。另外对于方法注入和@Resource注解的处理本篇没有涉及,但是相信看完本文读者自己也能轻松分析这部分源码。

(0)

相关推荐

  • java中构造方法和普通方法的区别说明

    1.普通方法: 定义:简单的说方法就是完成特定功能的代码块. 普通方法定义格式: 修饰符 返回值类型 方法名 (参数类型 参数名1,参数类型 参数名2,.........) { 函数体: return 返回值: } 返回值类型用于限定返回值的数据类型. 普通方法分为:有明确返回值的方法和没有明确返回值的方法. A.有明确返回值的方法的调用 可以单独调用(无意义).输出调用.赋值调用(推荐). public static int sum (int a , int b) { int c =a+b;

  • java中concat()方法的使用说明

    concat()方法介绍: 将几个字符串连接到一起. 例如: s = s.concat(str1);//将字符串str1接到字符串s后面 s = s.concat(str2);//将字符串str1接到字符串s后面 代码: public class Test { public static void main(String[] args){ String s = "厉害了,"; String str1 = "我的"; String str2 = "国!&qu

  • 这一次搞懂Spring的Bean实例化原理操作

    前言 前两篇文章分析了Spring XML和注解的解析原理,并将其封装为BeanDefinition对象存放到IOC容器中,而这些只是refresh方法中的其中一个步骤--obtainFreshBeanFactory,接下来就将围绕着这些BeanDefinition对象进行一系列的处理,如BeanDefinitionRegistryPostProcessor对象方法的调用.BeanFactoryPostProcessor对象方法的调用以及Bean实例的创建都离不开这些BeanDefinition

  • 在idea中将java项目中的单个类打包成jar包操作

    JAR文件的全称是Java Archive File,即Java档案文件.JAR文件是一种压缩文件,与常见的ZIP压缩文件兼容,被称为JAR包. JAR文件与zip文件的主要区别是在JAR文件中默认包含了一个名为META-INF/MANIFEST.MF的清单文件,这个清单文件是在生成JAR文件时系统自动创建的. 打包jar包 1.先创建一个要打包成jar包的类 2.File -> Project Structrue -> Artifacts -> + -> JAR -> fr

  • 你所不知道的Spring的@Autowired实现细节分析

    前言 相信很多Java开发都遇到过一个面试题:Resource和Autowired的区别是什么?这个问题的答案相信基本都清楚,但是这两者在Spring中是如何实现的呢?这就要分析Spring源码才能知道了.友情提示:本篇主要是讲解Autowired的实现原理,不会分析Spring初始化的过程,不熟悉的读者可以先阅读笔者之前的一篇文章<这一次搞懂Spring的Bean实例化原理>. 正文 在Spring Bean的整个创建过程中会调用很多BeanPostProcessor接口的的实现类: 上图是

  • 你所不知道的Spring自动注入详解

    自动注入和@Autowire @Autowire不属于自动注入! 注入方式(重要) 在Spring官网上(文档),定义了在Spring中的注入方式一共有两种:set方法和构造函数. 也就是说,你想在A类里面注入另外一个B类,无论你是通过写 XML文件,或者通过 @Autowried,他们最终都是通过这个A类的set方法或者构造函数,将B类注入到A类中! 换句话说,你如果A类里面没有setB(B b){-},那你就别想通过set方法把B类注入到A类中 自动注入 首先摆出一个比较颠覆的观点:@Aut

  • 你所不知道的Python奇技淫巧13招【实用】

    有时候你会看到很Cool的Python代码,你惊讶于它的简洁,它的优雅,你不由自主地赞叹:竟然还能这样写.其实,这些优雅的代码都要归功于Python的特性,只要你能掌握这些Pythonic的技巧,你一样可以写出像诗一样的Python代码. 1.导入模块 你是不是经常对调用模块时输入一长串模块索引感到头疼?说实在的,数量少的时候或许还可以勉强忍受,一旦程序规模上去了,这也是一项不容小觑的工程. #Bad import urllib.request url = r'http://www.landsb

  • 关于JavaScript数组你所不知道的3件事

    在编程语言当中,数组(Array)是一个非常常用的功能:它是一种特殊的变量,可以用来同时储存多个数值.然而,在JavaScript方面,数组的功能还有很多其他值得探索的地方. 在这篇文章中,我们将会讨论JavaScript数组的三个并不那么常见的功能. 1. 给数组添加自定义属性 在网上搜寻有关JavaScript数组的定义时,你会发现几乎所有人对于数组的定义都一样:一种对象. 事实上,我们用JavaScript处理的所有东西,都可以视为是一种对象.JavaScript中有两种数据类型,基本类型

  • Go语言中你所不知道的位操作用法

    前言 因为之前一直忽略的就是所有语言中关于位操作,觉得用处并不多,可能用到也非常简单的用法,但是其实一直忽略的是它们的用处还是非常大的,下面先回顾一下位操作符的基础 位操作符 与操作:& 1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0 或操作:! 1 | 1 = 1 1 | 0 = 1 0 | 1 = 1 0 & 0 = 0 异或:^ 1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0 左移:<

  • 关于Java中你所不知道的Integer详解

    前言 本文主要给大家介绍了关于Java中Integer的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实参形参 前些天看到朋友圈分享了一片文章<Java函数的传参机制--你真的了解吗?> 有些触发,之前也研究过Java的Integer,所以写下本文,希望对你有所帮助. 交换 首先来看一个示例. 请用Java完成swap函数,交换两个整数类型的值. public static void test() throws Exception { Integer a = 1,

  • 详解Linux下你所不知道的7个SSH命令用法

    一个系统管理员可能会同时管理着多台服务器,这些服务器也许会放在不同的地方.要亲自一台一台的去访问来管理它们显然不是最好的方法,通过远程控制的方法应该是最有效的. Linux系统的远程管理工具大概有几种:telnet,ssh,vnc等,其中ssh是最常用的管理方法,采用密文的传输方式,简单安全. Secure Shell缩写是SSH, 由IETF的网络工作小组(Network Working Group)所制定,SSH是一项创建在应用层和传输层基础上的安全协议,为计算机的shell提供安全的传输和

  • 浅谈Postgresql默认端口5432你所不知道的一点

    关于Postgresql端口5432的定义: 5432端口,已经在IANA(The Internet Assigned Numbers Authority,互联网数字分配机构)注册, 并把该端口唯一分配给Postgres. 这意味着,一台安装了linux OS的服务器,哪怕没有安装过postgresql数据库,也会有这个预留端口. 查看这个预留端口的方法如下: new@newdb-> cat /etc/services |grep 5432 postgres 5432/tcp postgresq

  • Spring使用@Autowired注解实现自动装配方式

    目录 Spring支持注解配置 引入注解依赖 启用注解 使用@Autowired注解实现自动装配 1.IOC容器配置 2.实体类使用@Autowired注解注入属性 3.测试结果 @Autowired注解的使用和注入规则 1.使用在变量域上面 2.@Autowired注解使用在构造器上面 Spring支持注解配置 引入注解依赖 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="ht

  • 关于Go你不得不知道的一些实用小技巧

    目录 Go 箴言 Go 之禅 代码 使用 go fmt 格式化 多个 if 语句可以折叠成 switch 用 chan struct{} 来传递信号, chan bool 表达的不够清楚 30 * time.Second 比 time.Duration(30) * time.Second 更好 用 time.Duration 代替 int64 + 变量名 按类型分组 const 声明,按逻辑和/或类型分组 var 不要在你不拥有的结构上使用 encoding/gob 不要依赖于计算顺序,特别是在

随机推荐