二、设置Bean属性

收信完注入元数据后,Bean的属性还是没有注入的,还需要将执行属性注入。还是在doCreateBean方法中,收集完注入元数据后,紧接着会调用populateBean:

  1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  2. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  3. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
  4. PropertyDescriptor[] filteredPds = null;
  5. if (hasInstAwareBpps) {
  6. if (pvs == null) {
  7. pvs = mbd.getPropertyValues();
  8. }
  9. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  10. // 调用BeanPostProcessor
  11. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  12. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  13. // 调用 postProcessProperties
  14. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
  15. if (pvsToUse == null) {
  16. if (filteredPds == null) {
  17. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
  18. }
  19. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  20. if (pvsToUse == null) {
  21. return;
  22. }
  23. }
  24. pvs = pvsToUse;
  25. }
  26. }
  27. }
  28. }

可以看到在populateBean中会调用InstantiationAwareBeanPostProcessor.postProcessProperties方法,由于已经知道 AutowiredAnnotationBeanPostProcessor 是实现InstantiationAwareBeanPostProcessor 的,所以可以直接查看实现方法:

  1. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  2. // 获取缓存中的 InjectionMetadata
  3. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  4. try {
  5. // 进行属性的注入
  6. metadata.inject(bean, beanName, pvs);
  7. }
  8. // 返回注入的属性
  9. return pvs;
  10. }
  11. // InjectMetadata.java
  12. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  13. // 获取检查后的元素
  14. Collection<InjectedElement> checkedElements = this.checkedElements;
  15. // 如果checkedElements不为空就使用checkedElements,否则使用injectedElements
  16. Collection<InjectedElement> elementsToIterate =
  17. (checkedElements != null ? checkedElements : this.injectedElements);
  18. if (!elementsToIterate.isEmpty()) {
  19. // 遍历elementsToIterate
  20. for (InjectedElement element : elementsToIterate) {
  21. // AutowiredFieldElement、AutowiredMethodElement这两个类继InjectionMetadata.InjectedElement
  22. // 各自重写了inject方法
  23. element.inject(target, beanName, pvs);
  24. }
  25. }
  26. }

AutowiredFieldElement#inject

  1. protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  2. // 强转成Field类型
  3. Field field = (Field) this.member;
  4. Object value;
  5. if (this.cached) {
  6. // 如果缓存过,直接使用缓存的值,一般第一次注入都是false
  7. value = resolvedCachedArgument(beanName, this.cachedFieldValue);
  8. }
  9. else {
  10. // 构建依赖描述符
  11. DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
  12. desc.setContainingClass(bean.getClass());
  13. Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
  14. Assert.state(beanFactory != null, "No BeanFactory available");
  15. // 获取类型转换器
  16. TypeConverter typeConverter = beanFactory.getTypeConverter();
  17. try {
  18. // 进行依赖解决,**********关键代码****见代码片段5
  19. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  20. }
  21. catch (BeansException ex) {
  22. throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
  23. }
  24. // 加锁
  25. synchronized (this) {
  26. //....
  27. }
  28. }
  29. // 如果找到了符合的bean,设置字段可访问,利用反射设置值
  30. if (value != null) {
  31. ReflectionUtils.makeAccessible(field);
  32. field.set(bean, value);
  33. }
  34. }

代码片段5、解决依赖注入resolveDependency

  1. @Override
  2. @Nullable
  3. public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
  4. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  5. descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
  6. // 判断依赖的数据的类似是否为Optional类型
  7. if (Optional.class == descriptor.getDependencyType()) {
  8. return createOptionalDependency(descriptor, requestingBeanName);
  9. }
  10. // 判断依赖的类型是否为ObjectFactory类型
  11. else if (ObjectFactory.class == descriptor.getDependencyType() ||
  12. ObjectProvider.class == descriptor.getDependencyType()) {
  13. return new DependencyObjectProvider(descriptor, requestingBeanName);
  14. }
  15. // 判断依赖的类型是否为JSR330类型
  16. else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
  17. return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
  18. }
  19. else {
  20. // 判断依赖属性的是否加入了@Lazy注解
  21. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
  22. descriptor, requestingBeanName);
  23. if (result == null) {
  24. // 解决依赖注入的核心方法,见代码片段6
  25. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  26. }
  27. return result;
  28. }
  29. }

代码片段6,doResolveDependency

  1. /**
  2. * descriptor:依赖描述器,大概描述了 XXX 里的 field 需要自动装配 xxx 类型的 bean
  3. * beanName:
  4. */
  5. @Nullable
  6. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
  7. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  8. // InjectionPoint
  9. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  10. try {
  11. // 1. 快速查找,根据名称查找。AutowiredAnnotationBeanPostProcessor用到
  12. Object shortcut = descriptor.resolveShortcut(this);
  13. if (shortcut != null) {
  14. return shortcut;
  15. }
  16. // 2. 注入指定值,QualifierAnnotationAutowireCandidateResolver解析@Value会用到
  17. Class<?> type = descriptor.getDependencyType();
  18. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  19. if (value != null) {
  20. if (value instanceof String) {
  21. // 2.1 占位符解析
  22. String strVal = resolveEmbeddedValue((String) value);
  23. BeanDefinition bd = (beanName != null && containsBean(beanName) ?
  24. getMergedBeanDefinition(beanName) : null);
  25. // 2.2 Spring EL 表达式
  26. value = evaluateBeanDefinitionString(strVal, bd);
  27. }
  28. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  29. return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
  30. }
  31. // 3. 集合依赖,如 Array、List、Set、Map。内部查找依赖也是使用findAutowireCandidates
  32. Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
  33. if (multipleBeans != null) {
  34. return multipleBeans;
  35. }
  36. // 4. 单个依赖查询*****见代码片段7的解析
  37. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  38. // 4.1 没有查找到依赖,判断descriptor.require
  39. if (matchingBeans.isEmpty()) {
  40. if (isRequired(descriptor)) {
  41. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  42. }
  43. return null;
  44. }
  45. String autowiredBeanName;
  46. Object instanceCandidate;
  47. // 4.2 有多个,如何过滤
  48. if (matchingBeans.size() > 1) {
  49. // 4.2.1 @Primary -> @Priority -> 方法名称或字段名称匹配
  50. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  51. if (autowiredBeanName == null) {
  52. // 4.2.2 根据是否必须,抛出异常。注意这里如果是集合处理,则返回null
  53. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  54. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  55. }
  56. else {
  57. return null;
  58. }
  59. }
  60. instanceCandidate = matchingBeans.get(autowiredBeanName);
  61. }
  62. else {
  63. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  64. autowiredBeanName = entry.getKey();
  65. instanceCandidate = entry.getValue();
  66. }
  67. // 4.3 到了这,说明有且仅有命中一个
  68. if (autowiredBeanNames != null) {
  69. autowiredBeanNames.add(autowiredBeanName);
  70. }
  71. // 4.4 实际上调用 getBean(autowiredBeanName, type)。但什么情况下会出现这种场景?
  72. if (instanceCandidate instanceof Class) {
  73. // 使用的BeanFactory的getBean的方法。doGetBean()的流程代码
  74. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  75. }
  76. Object result = instanceCandidate;
  77. if (result instanceof NullBean) {
  78. if (isRequired(descriptor)) {
  79. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  80. }
  81. result = null;
  82. }
  83. return result;
  84. }
  85. finally {
  86. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  87. }
  88. }

说明: doResolveDependency方法的四个功能,快速查找和集合处理都委托给了其它方法,注入指定值虽然看起来复杂,但占位符处理、EL 表达式解析、类型转换这三个功能点都有具体的类处理,也不是本文的重点。
我们重点看一下单个依赖的查询,弄明白了单个依赖的查询,其它集合依赖也差不多。

  1. 查找容器中所有可用依赖:findAutowireCandidates 方法根据类型查找依赖。
  2. 如何有多个依赖怎么处理?其实 Spring 有一套通用的流程,先按 @Primary 查找,再按 @Priority,最后按方法名称或字段名称查找,直到只有一个 bean 为止。相关的匹配规则见 determineAutowireCandidate 方法。
  3. 此时只有一个依赖,从容器获取真实的 bean。descriptor.resolveCandidate方法根据名称autowiredBeanName 实例化对象。

思考:findAutowireCandidates 返回的为什么是对象类型,而不是实例对象?

  1. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

matchingBeans中的 Object 对象可能是对象类型,而不全部是实例对象。因为findAutowireCandidates方法是根据类型 type 查找名称 beanNames,如果容器中该 beanName 还没有实例化,findAutowireCandidates 不会画蛇添足直接实例化该 bean,当然如果已经实例化了会直接返回这个 bean。

代码片段7、findAutowireCandidates

根据上面的分析,resolveDependency方法对Optional、延迟注入、懒加载注入等分别进行了处理。之后 doResolveDependency 在正式查找之前看能不能快速查找,如缓存 beanName@Value 等快速指定需要注入的值,避免通过类型查找,最后才对集合依赖和单一依赖分别进行了处理。实际上,无论是集合依赖还是单一依赖查找,本质上都是调用 findAutowireCandidates进行类型依赖查找。
findAutowireCandidates方法,我们可以看到Spring IoC依赖注入的来源:

  1. 先查找 Spring IoC 内部依赖 resolvableDependencies。在 AbstractApplicationContext#prepareBeanFactory 方法中默认设置了如下内部依赖:BeanFactoryResourceLoaderApplicationEventPublisherApplicationContext
  2. 在父子容器进行类型查找:查找类型匹配的beanNamesbeanFactory#beanNamesForType 方法根据类型查找是,先匹配单例实例类型(包括 Spring 托管 Bean),再匹配 BeanDefinition 的类型。从这一步,我们可以看到 Spring 依赖注入的另外两个来源:一是 Spring 托管的外部 Bean,二是 Spring BeanDefinition。
  1. protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
  2. Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
  3. // 1. Spring IoC 内部依赖 resolvableDependencies
  4. for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
  5. Class<?> autowiringType = classObjectEntry.getKey();
  6. if (autowiringType.isAssignableFrom(requiredType)) {
  7. Object autowiringValue = classObjectEntry.getValue();
  8. autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
  9. if (requiredType.isInstance(autowiringValue)) {
  10. result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
  11. break;
  12. }
  13. }
  14. }
  15. // 2. 类型查找:本质上递归调用beanFactory#beanNamesForType。先匹配实例类型,再匹配bd。
  16. String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  17. this, requiredType, true, descriptor.isEager());
  18. for (String candidate : candidateNames) {
  19. // 2.1 如果不是自己依赖自己 , 并且符合装配候选,就塞入result。
  20. if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
  21. // 2.2 添加到候选对象中
  22. addCandidateEntry(result, candidate, descriptor, requiredType);
  23. }
  24. }
  25. // 3. 补偿机制:如果依赖查找无法匹配,怎么办?包含泛型补偿和自身引用补偿两种。
  26. if (result.isEmpty()) {
  27. boolean multiple = indicatesMultipleBeans(requiredType);
  28. // 3.1 fallbackDescriptor: 泛型补偿,实际上是允许注入对象类型的泛型存在无法解析的情况
  29. DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
  30. // 3.2 补偿1:不允许自称依赖,但如果是集合依赖,需要过滤非@Qualifier对象。什么场景?
  31. for (String candidate : candidateNames) {
  32. if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
  33. (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
  34. addCandidateEntry(result, candidate, descriptor, requiredType);
  35. }
  36. }
  37. // 3.3 补偿2:允许自称依赖,但如果是集合依赖,注入的集合依赖中需要过滤自己
  38. if (result.isEmpty() && !multiple) {
  39. for (String candidate : candidateNames) {
  40. if (isSelfReference(beanName, candidate) &&
  41. (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
  42. isAutowireCandidate(candidate, fallbackDescriptor)) {
  43. addCandidateEntry(result, candidate, descriptor, requiredType);
  44. }
  45. }
  46. }
  47. }
  48. return result;
  49. }