前言

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

正文

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



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

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

  1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  2. ......
  3. // Candidate constructors for autowiring?
  4. //寻找当前正在实例化的bean中有@Autowired注解的构造函数
  5. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  6. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
  7. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  8. //如果ctors不为空,就说明构造函数上有@Autowired注解
  9. return autowireConstructor(beanName, mbd, ctors, args);
  10. }
  11. ......
  12. // No special handling: simply use no-arg constructor.
  13. return instantiateBean(beanName, mbd);
  14. }
  15. protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
  16. throws BeansException {
  17. if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
  18. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  19. if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
  20. SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
  21. Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
  22. if (ctors != null) {
  23. return ctors;
  24. }
  25. }
  26. }
  27. }
  28. return null;
  29. }

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

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

  1. protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
  2. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  3. if (bp instanceof MergedBeanDefinitionPostProcessor) {
  4. /**
  5. * CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
  6. * AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
  7. */
  8. MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
  9. bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
  10. }
  11. }
  12. }

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

  1. public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  2. InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
  3. metadata.checkConfigMembers(beanDefinition);
  4. }
  5. private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
  6. // Fall back to class name as cache key, for backwards compatibility with custom callers.
  7. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  8. // Quick check on the concurrent map first, with minimal locking.
  9. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  10. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
  11. synchronized (this.injectionMetadataCache) {
  12. metadata = this.injectionMetadataCache.get(cacheKey);
  13. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
  14. if (metadata != null) {
  15. metadata.clear(pvs);
  16. }
  17. //主要看这个方法
  18. metadata = buildAutowiringMetadata(clazz);
  19. this.injectionMetadataCache.put(cacheKey, metadata);
  20. }
  21. }
  22. }
  23. return metadata;
  24. }
  25. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
  26. List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
  27. Class<?> targetClass = clazz;
  28. do {
  29. final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
  30. // 找到带有@Autowired注解的属性并封装为AnnotationAttributes
  31. ReflectionUtils.doWithLocalFields(targetClass, field -> {
  32. AnnotationAttributes ann = findAutowiredAnnotation(field);
  33. if (ann != null) {
  34. if (Modifier.isStatic(field.getModifiers())) {
  35. if (logger.isInfoEnabled()) {
  36. logger.info("Autowired annotation is not supported on static fields: " + field);
  37. }
  38. return;
  39. }
  40. boolean required = determineRequiredStatus(ann);
  41. currElements.add(new AutowiredFieldElement(field, required));
  42. }
  43. });
  44. // 找到带有@Autowired注解的方法并封装为AnnotationAttributes
  45. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
  46. Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
  47. if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
  48. return;
  49. }
  50. AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
  51. if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
  52. if (Modifier.isStatic(method.getModifiers())) {
  53. if (logger.isInfoEnabled()) {
  54. logger.info("Autowired annotation is not supported on static methods: " + method);
  55. }
  56. return;
  57. }
  58. if (method.getParameterCount() == 0) {
  59. if (logger.isInfoEnabled()) {
  60. logger.info("Autowired annotation should only be used on methods with parameters: " +
  61. method);
  62. }
  63. }
  64. boolean required = determineRequiredStatus(ann);
  65. PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
  66. currElements.add(new AutowiredMethodElement(method, required, pd));
  67. }
  68. });
  69. elements.addAll(0, currElements);
  70. targetClass = targetClass.getSuperclass();
  71. }
  72. while (targetClass != null && targetClass != Object.class);
  73. return new InjectionMetadata(clazz, elements);
  74. }

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

  1. private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
  2. public AutowiredAnnotationBeanPostProcessor() {
  3. this.autowiredAnnotationTypes.add(Autowired.class);
  4. this.autowiredAnnotationTypes.add(Value.class);
  5. try {
  6. this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
  7. ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
  8. logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
  9. }
  10. catch (ClassNotFoundException ex) {
  11. // JSR-330 API not available - simply skip.
  12. }
  13. }
  14. private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
  15. if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
  16. for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
  17. AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
  18. if (attributes != null) {
  19. return attributes;
  20. }
  21. }
  22. }
  23. return null;
  24. }

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

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

  1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  2. ......
  3. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
  4. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
  5. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  6. // Add property values based on autowire by name if applicable.
  7. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
  8. autowireByName(beanName, mbd, bw, newPvs);
  9. }
  10. // Add property values based on autowire by type if applicable.
  11. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
  12. autowireByType(beanName, mbd, bw, newPvs);
  13. }
  14. pvs = newPvs;
  15. }
  16. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  17. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
  18. PropertyDescriptor[] filteredPds = null;
  19. //重点看这个if代码块,重要程度 5
  20. if (hasInstAwareBpps) {
  21. if (pvs == null) {
  22. pvs = mbd.getPropertyValues();
  23. }
  24. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  25. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  26. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  27. // 依赖注入过程,@Autowired的支持
  28. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  29. if (pvsToUse == null) {
  30. if (filteredPds == null) {
  31. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  32. }
  33. // 老版本用这个完成依赖注入过程,@Autowired的支持
  34. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  35. if (pvsToUse == null) {
  36. return;
  37. }
  38. }
  39. pvs = pvsToUse;
  40. }
  41. }
  42. }
  43. if (needsDepCheck) {
  44. if (filteredPds == null) {
  45. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  46. }
  47. checkDependencies(beanName, mbd, filteredPds, pvs);
  48. }
  49. // xml中<property>标签的依赖注入
  50. if (pvs != null) {
  51. applyPropertyValues(beanName, mbd, bw, pvs);
  52. }
  53. }
  1. mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="
  5. http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
  7. default-autowire="byName">
  8. <bean id="a" class="com.A" autowire="byName"/>
  9. <bean id="b" class="com.B" autowire="byType"/>
  10. </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并设置属性。

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

  1. if (hasInstAwareBpps) {
  2. if (pvs == null) {
  3. pvs = mbd.getPropertyValues();
  4. }
  5. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  6. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  7. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  8. // 依赖注入过程,@Autowired的支持
  9. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  10. if (pvsToUse == null) {
  11. if (filteredPds == null) {
  12. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  13. }
  14. // 老版本用这个完成依赖注入过程,@Autowired的支持
  15. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  16. if (pvsToUse == null) {
  17. return;
  18. }
  19. }
  20. pvs = pvsToUse;
  21. }
  22. }
  23. }

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

  1. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  2. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  3. try {
  4. metadata.inject(bean, beanName, pvs);
  5. }
  6. catch (BeanCreationException ex) {
  7. throw ex;
  8. }
  9. catch (Throwable ex) {
  10. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
  11. }
  12. return pvs;
  13. }

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

  1. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  2. Collection<InjectedElement> checkedElements = this.checkedElements;
  3. Collection<InjectedElement> elementsToIterate =
  4. (checkedElements != null ? checkedElements : this.injectedElements);
  5. if (!elementsToIterate.isEmpty()) {
  6. for (InjectedElement element : elementsToIterate) {
  7. if (logger.isTraceEnabled()) {
  8. logger.trace("Processing injected element of bean '" + beanName + "': " + element);
  9. }
  10. if(element.isField) {
  11. Field field = (Field)element.member;
  12. System.out.println("==IOC/DI===beanName==" + beanName + "==field[" + field.getName() +"]-> getBean(" + field.getName() + ")");
  13. }
  14. element.inject(target, beanName, pvs);
  15. }
  16. }
  17. }

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

  1. protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  2. Field field = (Field) this.member;
  3. Object value;
  4. if (this.cached) {
  5. value = resolvedCachedArgument(beanName, this.cachedFieldValue);
  6. }
  7. else {
  8. DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
  9. desc.setContainingClass(bean.getClass());
  10. Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
  11. Assert.state(beanFactory != null, "No BeanFactory available");
  12. TypeConverter typeConverter = beanFactory.getTypeConverter();
  13. try {
  14. // 找到依赖对象
  15. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  16. }
  17. catch (BeansException ex) {
  18. throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
  19. }
  20. synchronized (this) {
  21. if (!this.cached) {
  22. if (value != null || this.required) {
  23. this.cachedFieldValue = desc;
  24. registerDependentBeans(beanName, autowiredBeanNames);
  25. if (autowiredBeanNames.size() == 1) {
  26. String autowiredBeanName = autowiredBeanNames.iterator().next();
  27. if (beanFactory.containsBean(autowiredBeanName) &&
  28. beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
  29. this.cachedFieldValue = new ShortcutDependencyDescriptor(
  30. desc, autowiredBeanName, field.getType());
  31. }
  32. }
  33. }
  34. else {
  35. this.cachedFieldValue = null;
  36. }
  37. this.cached = true;
  38. }
  39. }
  40. }
  41. if (value != null) {
  42. ReflectionUtils.makeAccessible(field);
  43. field.set(bean, value);
  44. }
  45. }

这段代码整体逻辑比较清晰,首先根据field创建一个依赖对象的抽象DependencyDescriptor对象,然后通过beanFactory.resolveDependency解析拿到对应的实例,最后通过反射注入即可。因此我们主要看resolveDependency方法中做了什么:

  1. public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
  2. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  3. descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
  4. if (Optional.class == descriptor.getDependencyType()) {
  5. return createOptionalDependency(descriptor, requestingBeanName);
  6. }
  7. else if (ObjectFactory.class == descriptor.getDependencyType() ||
  8. ObjectProvider.class == descriptor.getDependencyType()) {
  9. return new DependencyObjectProvider(descriptor, requestingBeanName);
  10. }
  11. else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
  12. return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
  13. }
  14. else {
  15. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
  16. descriptor, requestingBeanName);
  17. if (result == null) {
  18. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  19. }
  20. return result;
  21. }
  22. }

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

  1. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
  2. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  3. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  4. try {
  5. Object shortcut = descriptor.resolveShortcut(this);
  6. if (shortcut != null) {
  7. return shortcut;
  8. }
  9. Class<?> type = descriptor.getDependencyType();
  10. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  11. if (value != null) {
  12. if (value instanceof String) {
  13. String strVal = resolveEmbeddedValue((String) value);
  14. BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
  15. value = evaluateBeanDefinitionString(strVal, bd);
  16. }
  17. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  18. return (descriptor.getField() != null ?
  19. converter.convertIfNecessary(value, type, descriptor.getField()) :
  20. converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
  21. }
  22. // 有多个实现类需要注入,特指注入的是数组、集合或者Map
  23. Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
  24. if (multipleBeans != null) {
  25. return multipleBeans;
  26. }
  27. // 找到依赖对象的所有实现类
  28. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  29. if (matchingBeans.isEmpty()) {
  30. if (isRequired(descriptor)) {
  31. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  32. }
  33. return null;
  34. }
  35. String autowiredBeanName;
  36. Object instanceCandidate;
  37. // 依赖的对象有多个实例
  38. if (matchingBeans.size() > 1) {
  39. // 根据@Primary、@Priority和名称依次进行匹配注入
  40. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  41. if (autowiredBeanName == null) {
  42. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  43. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  44. }
  45. else {
  46. // In case of an optional Collection/Map, silently ignore a non-unique case:
  47. // possibly it was meant to be an empty collection of multiple regular beans
  48. // (before 4.3 in particular when we didn't even look for collection beans).
  49. return null;
  50. }
  51. }
  52. instanceCandidate = matchingBeans.get(autowiredBeanName);
  53. }
  54. else {
  55. // We have exactly one match.
  56. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  57. autowiredBeanName = entry.getKey();
  58. instanceCandidate = entry.getValue();
  59. }
  60. if (autowiredBeanNames != null) {
  61. autowiredBeanNames.add(autowiredBeanName);
  62. }
  63. // 如果拿到的是class对象,通过getBean实例化返回
  64. if (instanceCandidate instanceof Class) {
  65. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  66. }
  67. Object result = instanceCandidate;
  68. if (result instanceof NullBean) {
  69. if (isRequired(descriptor)) {
  70. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  71. }
  72. result = null;
  73. }
  74. if (!ClassUtils.isAssignableValue(type, result)) {
  75. throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
  76. }
  77. return result;
  78. }
  79. finally {
  80. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  81. }
  82. }

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

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

  1. protected Map<String, Object> findAutowireCandidates(
  2. @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
  3. String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  4. this, requiredType, true, descriptor.isEager());
  5. Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
  6. ......
  7. for (String candidate : candidateNames) {
  8. if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
  9. addCandidateEntry(result, candidate, descriptor, requiredType);
  10. }
  11. }
  12. ......
  13. return result;
  14. }
  15. private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
  16. DependencyDescriptor descriptor, Class<?> requiredType) {
  17. if (descriptor instanceof MultiElementDescriptor) {
  18. Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
  19. if (!(beanInstance instanceof NullBean)) {
  20. candidates.put(candidateName, beanInstance);
  21. }
  22. }
  23. else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
  24. ((StreamDependencyDescriptor) descriptor).isOrdered())) {
  25. Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
  26. candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
  27. }
  28. else {
  29. candidates.put(candidateName, getType(candidateName));
  30. }
  31. }

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

接着回到doResolveDependency方法中:

  1. if (matchingBeans.size() > 1) {
  2. // 根据@Primary、@Priority和名称依次进行匹配注入
  3. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  4. if (autowiredBeanName == null) {
  5. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  6. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  7. }
  8. else {
  9. // In case of an optional Collection/Map, silently ignore a non-unique case:
  10. // possibly it was meant to be an empty collection of multiple regular beans
  11. // (before 4.3 in particular when we didn't even look for collection beans).
  12. return null;
  13. }
  14. }
  15. instanceCandidate = matchingBeans.get(autowiredBeanName);
  16. }
  17. else {
  18. // We have exactly one match.
  19. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  20. autowiredBeanName = entry.getKey();
  21. instanceCandidate = entry.getValue();
  22. }
  23. if (autowiredBeanNames != null) {
  24. autowiredBeanNames.add(autowiredBeanName);
  25. }
  26. // 如果拿到的是class对象,通过getBean实例化返回
  27. if (instanceCandidate instanceof Class) {
  28. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  29. }
  30. Object result = instanceCandidate;

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

  • 首先判断实现类上是否有@Primary注解,找到一个则返回当前实例,找到多个则报错。
  • 若没有标注@Primary注解,则判断是否指定了优先级,且只能是通过@Priority注解指定的,@Order不支持。
  • 上述都没有拿到合适的Bean则通过属性名称获取Bean。

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

总结

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

你所不知道的Spring的@Autowired实现细节的更多相关文章

  1. 你所不知道的 CSS 滤镜技巧与细节

    承接上一篇你所不知道的 CSS 动画技巧与细节,本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! OK,下面直接进入正文.本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE ...

  2. 你所不知道的 CSS 阴影技巧与细节

    关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow 的用法. 最近一个新的项目,CSS-Ins ...

  3. 你所不知道的 CSS 阴影技巧与细节 滚动视差?CSS 不在话下 神奇的选择器 :focus-within 当角色转换为面试官之后 NPOI 教程 - 3.2 打印相关设置 前端XSS相关整理 委托入门案例

    你所不知道的 CSS 阴影技巧与细节   关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow  ...

  4. 你所不知道的 CSS 动画技巧与细节

    怕标题起的有点大,下述技巧如果你已经掌握了看看就好,欢迎斧正,本文希望通过介绍一些 CSS 不太常用的技巧,辅以一些实践,让读者可以更加深入的理解掌握 CSS 动画. 废话少说,直接进入正题,本文提到 ...

  5. 你所不知道的 CSS 负值技巧与细节

    写本文的起因是,一天在群里有同学说误打误撞下,使用负的 outline-offset 实现了加号.嗯?好奇的我马上也动手尝试了下,到底是如何使用负的 outline-offset 实现加号呢? 使用负 ...

  6. 【CSS】346- 你所不知道的 CSS 阴影技巧与细节

    偷懒了1个多礼拜,在工作饱和的情况下,怎么坚持学习?今天的分享来自@Coco国服第一切图仔,我们聊聊CSS属性box-shadow- 关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 ...

  7. Android Context完全解析,你所不知道的Context的各种细节

    Context相信所有的Android开发人员基本上每天都在接触,因为它太常见了.但是这并不代表Context没有什么东西好讲的,实际上Context有太多小的细节并不被大家所关注,那么今天我们就来学 ...

  8. 你所不知道的五件事情--java.util.concurrent(第二部分)

    这是Ted Neward在IBM developerWorks中5 things系列文章中的一篇,仍然讲述了关于Java并发集合API的一些应用窍门,值得大家学习.(2010.06.17最后更新) 摘 ...

  9. 你所不知道的Html5那些事(一)

    文章简介:       关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后 ...

随机推荐

  1. SYN 攻击原理及解决方法

    原理SYN foold攻击主要针对tcp通信三次握手期间做的手脚,所以要弄懂这个攻击的原理我们首先必须知道tcp三次握手的详细过程 由上图可知tcp三次握手顾名思义要经过三个步骤,这三个步骤分别是 客 ...

  2. JVM详解之:汇编角度理解本地变量的生命周期

    目录 简介 本地变量的生命周期 举例说明 优化的原因 总结 简介 java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢? 带着这个问题我们来看一下今 ...

  3. 两数相加(B站看视频总结)

    ''' 两数相加: 给出两个 非空 的链表用来表示两个非负的整数 各自的位数是按照逆序的方式存储的 每一个节点只能保存 一位数 示例: 输入:(2->4->3) + (5->6-&g ...

  4. Seaborn实现回归分析

    import numpy as np import pandas as pd from scipy import stats,integrate import matplotlib.pyplot as ...

  5. Python unichr() 函数

    描述 unichr() 函数 和 chr() 函数功能基本一样, 只不过是返回 unicode 的字符.高佣联盟 www.cgewang.com 注意: Python3 不支持 unichr(),改用 ...

  6. PHP ucwords() 函数

    实例 把每个单词的首字符转换为大写: <?php高佣联盟 www.cgewang.comecho ucwords("hello world");?> 定义和用法 ucw ...

  7. Echarts饼图绘制

    实现效果: html代码: <div id="chartBody1" style="width:120%;height:28vh;"> <di ...

  8. 不要再问我MVC、MVP、MVVM了

    网络上有很多类似的讨论.包括一些大v,比如 阮一峰:MVC,MVP 和 MVVM 的图示 廖雪峰:MVVM 司徒正美: 各自用一句话来概括MVC.MVP.MVVM的差异特点 ... 但是说的往往比较概 ...

  9. day10.函数基础及函数参数

    一.函数 功能:包裹一部分代码 实现某一个功能 达成某一个目的 特点: """ 特点:可以反复调用,提高代码的复用性,提高开发效率,便于维护管理 函数基本格式 函数的定义 ...

  10. 033_go语言中的打点器

    代码演示 package main import "fmt" import "time" func main() { ticker := time.NewTic ...