spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

其他教程   发布日期:2023年08月04日   浏览次数:574

本篇内容介绍了“spring自动注入AutowiredAnnotationBeanPostProcessor源码分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    一、MergedBeanDefinitionPostProcessor

    1.1、postProcessMergedBeanDefinition

    在Bean属性赋值前,缓存属性字段上的@Autowired和@Value注解信息。

    1. public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    2. //1.1.1 查询属性或方法上有@Value和@Autowired注解的元素
    3. InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    4. //1.1.2 检查元数据信息
    5. metadata.checkConfigMembers(beanDefinition);
    6. }

    1.1.1 findAutowiringMetadata 查询属性或方法上有@Value和@Autowired注解的元素

    1. private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    2. // Fall back to class name as cache key, for backwards compatibility with custom callers.
    3. //获取Bean名称作为缓存key
    4. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    5. // Quick check on the concurrent map first, with minimal locking.
    6. //使用双重检查机制获取缓存
    7. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    8. //判断是否有元数据
    9. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    10. synchronized (this.injectionMetadataCache) {
    11. metadata = this.injectionMetadataCache.get(cacheKey);
    12. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    13. if (metadata != null) {
    14. metadata.clear(pvs);
    15. }
    16. //构建元数据
    17. metadata = buildAutowiringMetadata(clazz);
    18. this.injectionMetadataCache.put(cacheKey, metadata);
    19. }
    20. }
    21. }
    22. return metadata;
    23. }

    这个 do-while 循环是用来一步一步往父类上爬的(可以看到这个循环体的最后一行是获取父类,判断条件是判断是否爬到了

    1. Object
    1. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    2. // 判断是不是候选者类,比如说类名是以 java.开头的则不是候选者类 Order的实现类也不是候选者类
    3. // 但是如果this.autowiredAnnotationTypes 中有以java.开头的注解就返回true了
    4. if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    5. return InjectionMetadata.EMPTY;
    6. }
    7. List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    8. Class<?> targetClass = clazz;
    9. do {
    10. final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    11. // 循环获取类上的属性,如果类属性上有@Value和@Autowired包装成AutowiredFieldElement放入结果集
    12. ReflectionUtils.doWithLocalFields(targetClass, field -> {
    13. MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    14. if (ann != null) {
    15. if (Modifier.isStatic(field.getModifiers())) {
    16. if (logger.isInfoEnabled()) {
    17. logger.info("Autowired annotation is not supported on static fields: " + field);
    18. }
    19. return;
    20. }
    21. boolean required = determineRequiredStatus(ann);
    22. currElements.add(new AutowiredFieldElement(field, required));
    23. }
    24. });
    25. // 循环获取类上的方法,如果类方法上有@Value和@Autowired包装成AutowiredMethodElement放入结果集
    26. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    27. Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    28. if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    29. return;
    30. }
    31. MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
    32. if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    33. if (Modifier.isStatic(method.getModifiers())) {
    34. if (logger.isInfoEnabled()) {
    35. logger.info("Autowired annotation is not supported on static methods: " + method);
    36. }
    37. return;
    38. }
    39. if (method.getParameterCount() == 0) {
    40. if (logger.isInfoEnabled()) {
    41. logger.info("Autowired annotation should only be used on methods with parameters: " +
    42. method);
    43. }
    44. }
    45. boolean required = determineRequiredStatus(ann);
    46. PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    47. currElements.add(new AutowiredMethodElement(method, required, pd));
    48. }
    49. });
    50. elements.addAll(0, currElements);
    51. targetClass = targetClass.getSuperclass();
    52. }
    53. while (targetClass != null && targetClass != Object.class);
    54. return InjectionMetadata.forElements(elements, clazz);
    55. }

    1.1.2 检查元数据信息

    检查是否有重复的元数据,去重处理,如一个属性上既有@Autowired注解,又有@Resource注解 。只使用一种方式进行注入,由于@Resource先进行解析,所以会选择@Resource的方式

    1. public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    2. Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
    3. for (InjectedElement element : this.injectedElements) {
    4. Member member = element.getMember();
    5. if (!beanDefinition.isExternallyManagedConfigMember(member)) {
    6. beanDefinition.registerExternallyManagedConfigMember(member);
    7. checkedElements.add(element);
    8. if (logger.isTraceEnabled()) {
    9. logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
    10. }
    11. }
    12. }
    13. this.checkedElements = checkedElements;
    14. }

    二、SmartInstantiationAwareBeanPostProcessor

    2.1、determineCandidateConstructors

    在bean实例化前选择@Autowired注解的构造函数,同时注入属性,从而完成自定义构造函数的选择。

    1. public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
    2. throws BeanCreationException {
    3. // Let's check for lookup methods here...
    4. if (!this.lookupMethodsChecked.contains(beanName)) {
    5. try {
    6. ReflectionUtils.doWithMethods(beanClass, method -> {
    7. Lookup lookup = method.getAnnotation(Lookup.class);
    8. if (lookup != null) {
    9. Assert.state(this.beanFactory != null, "No BeanFactory available");
    10. LookupOverride override = new LookupOverride(method, lookup.value());
    11. try {
    12. RootBeanDefinition mbd = (RootBeanDefinition)
    13. this.beanFactory.getMergedBeanDefinition(beanName);
    14. mbd.getMethodOverrides().addOverride(override);
    15. }
    16. catch (NoSuchBeanDefinitionException ex) {
    17. throw new BeanCreationException(beanName,
    18. "Cannot apply @Lookup to beans without corresponding bean definition");
    19. }
    20. }
    21. });
    22. }
    23. catch (IllegalStateException ex) {
    24. throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
    25. }
    26. this.lookupMethodsChecked.add(beanName);
    27. }
    28. // Quick check on the concurrent map first, with minimal locking.
    29. Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    30. if (candidateConstructors == null) {
    31. // Fully synchronized resolution now...
    32. synchronized (this.candidateConstructorsCache) {
    33. candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    34. if (candidateConstructors == null) {
    35. Constructor<?>[] rawCandidates;
    36. try {
    37. //反射获取所有构造函数
    38. rawCandidates = beanClass.getDeclaredConstructors();
    39. }
    40. catch (Throwable ex) {
    41. throw new BeanCreationException(beanName,
    42. "Resolution of declared constructors on bean Class [" + beanClass.getName() +
    43. "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
    44. }
    45. //候选构造方法
    46. List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
    47. Constructor<?> requiredConstructor = null;
    48. Constructor<?> defaultConstructor = null;
    49. //这个貌似是 Kotlin 上用的, 不用管它
    50. Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
    51. int nonSyntheticConstructors = 0;
    52. //遍历这些构造函数
    53. for (Constructor<?> candidate : rawCandidates) {
    54. //判断构造方法是否是合成的
    55. if (!candidate.isSynthetic()) {
    56. nonSyntheticConstructors++;
    57. }
    58. else if (primaryConstructor != null) {
    59. continue;
    60. }
    61. //查看是否有 @Autowired 注解
    62. //如果有多个构造方法, 可以通过标注 @Autowired 的方式来指定使用哪个构造方法
    63. AnnotationAttributes ann = findAutowiredAnnotation(candidate);
    64. if (ann == null) {
    65. Class<?> userClass = ClassUtils.getUserClass(beanClass);
    66. if (userClass != beanClass) {
    67. try {
    68. Constructor<?> superCtor =
    69. userClass.getDeclaredConstructor(candidate.getParameterTypes());
    70. ann = findAutowiredAnnotation(superCtor);
    71. }
    72. catch (NoSuchMethodException ex) {
    73. // Simply proceed, no equivalent superclass constructor found...
    74. }
    75. }
    76. }
    77. //有 @Autowired 的情况
    78. if (ann != null) {
    79. if (requiredConstructor != null) {
    80. throw new BeanCreationException(beanName,
    81. "Invalid autowire-marked constructor: " + candidate +
    82. ". Found constructor with 'required' Autowired annotation already: " +
    83. requiredConstructor);
    84. }
    85. boolean required = determineRequiredStatus(ann);
    86. if (required) {
    87. if (!candidates.isEmpty()) {
    88. throw new BeanCreationException(beanName,
    89. "Invalid autowire-marked constructors: " + candidates +
    90. ". Found constructor with 'required' Autowired annotation: " +
    91. candidate);
    92. }
    93. requiredConstructor = candidate;
    94. }
    95. candidates.add(candidate);
    96. }
    97. //无参构造函数的情况
    98. else if (candidate.getParameterCount() == 0) {
    99. //构造函数没有参数, 则设置为默认的构造函数
    100. defaultConstructor = candidate;
    101. }
    102. }
    103. //到这里, 已经循环完了所有的构造方法
    104. //候选者不为空时
    105. if (!candidates.isEmpty()) {
    106. // Add default constructor to list of optional constructors, as fallback.
    107. if (requiredConstructor == null) {
    108. if (defaultConstructor != null) {
    109. candidates.add(defaultConstructor);
    110. }
    111. else if (candidates.size() == 1 && logger.isInfoEnabled()) {
    112. logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
    113. "': single autowire-marked constructor flagged as optional - " +
    114. "this constructor is effectively required since there is no " +
    115. "default constructor to fall back to: " + candidates.get(0));
    116. }
    117. }
    118. candidateConstructors = candidates.toArray(new Constructor<?>[0]);
    119. }
    120. //类的构造方法只有1个, 且该构造方法有多个参数
    121. else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
    122. candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
    123. }
    124. //这里不会进, 因为 primaryConstructor = null
    125. else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
    126. defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
    127. candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
    128. }
    129. //这里也不会进, 因为 primaryConstructor = null
    130. else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
    131. candidateConstructors = new Constructor<?>[] {primaryConstructor};
    132. }
    133. else {
    134. //如果方法进了这里, 就是没找到合适的构造方法
    135. //1. 类定义了多个构造方法, 且没有 @Autowired , 则有可能会进这里
    136. candidateConstructors = new Constructor<?>[0];
    137. }
    138. this.candidateConstructorsCache.put(beanClass, candidateConstructors);
    139. }
    140. }
    141. }
    142.    //这里如果没找到, 则会返回 null, 而不会返回空数组
    143. return (candidateConstructors.length > 0 ? candidateConstructors : null);
    144. }

    遍历构造方法:

    • 只有一个无参构造方法, 则返回null

    • 只有一个有参构造方法, 则返回这个构造方法

    • 有多个构造方法且没有@Autowired, 此时spring则会蒙圈了, 不知道使用哪一个了。这里的后置处理器智能选择构造方法后置处理器。当选择不了的时候, 干脆返回 null

    • 有多个构造方法, 且在其中一个方法上标注了 @Autowired , 则会返回这个标注的构造方法

    • 有多个构造方法, 且在多个方法上标注了@Autowired, 则spring会抛出异常, Spring会认为, 你指定了几个给我, 是不是你弄错了

    注意:

    这地方有个问题需要注意一下, 如果你写了多个构造方法, 且没有写 无参构造方法, 那么此处返回null,

    在回到 createBeanInstance 方法中, 如果不能走 autowireConstructor(), 而走到 instantiateBean() 中去的话, 会报错的,因为类已经没有无参构造函数了。

    以上就是spring自动注入AutowiredAnnotationBeanPostProcessor源码分析的详细内容,更多关于spring自动注入AutowiredAnnotationBeanPostProcessor源码分析的资料请关注九品源码其它相关文章!