我的编程空间,编程开发者的网络收藏夹
学习永远不晚

spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

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

    一、MergedBeanDefinitionPostProcessor

    1.1、postProcessMergedBeanDefinition

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

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {   //1.1.1 查询属性或方法上有@Value和@Autowired注解的元素   InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);   //1.1.2 检查元数据信息   metadata.checkConfigMembers(beanDefinition);}
    1.1.1 findAutowiringMetadata 查询属性或方法上有@Value和@Autowired注解的元素
    private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {   // Fall back to class name as cache key, for backwards compatibility with custom callers.   //获取Bean名称作为缓存key   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;}

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

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {    // 判断是不是候选者类,比如说类名是以 java.开头的则不是候选者类 Order的实现类也不是候选者类    // 但是如果this.autowiredAnnotationTypes 中有以java.开头的注解就返回true了   if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {      return InjectionMetadata.EMPTY;   }   List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();   Class<?> targetClass = clazz;   do {      final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();      // 循环获取类上的属性,如果类属性上有@Value和@Autowired包装成AutowiredFieldElement放入结果集        ReflectionUtils.doWithLocalFields(targetClass, field -> {         MergedAnnotation<?> 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));         }      });      // 循环获取类上的方法,如果类方法上有@Value和@Autowired包装成AutowiredMethodElement放入结果集      ReflectionUtils.doWithLocalMethods(targetClass, method -> {         Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);         if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {            return;         }         MergedAnnotation<?> 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 InjectionMetadata.forElements(elements, clazz);}
    1.1.2 检查元数据信息

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

    public void checkConfigMembers(RootBeanDefinition beanDefinition) {   Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());   for (InjectedElement element : this.injectedElements) {      Member member = element.getMember();      if (!beanDefinition.isExternallyManagedConfigMember(member)) {         beanDefinition.registerExternallyManagedConfigMember(member);         checkedElements.add(element);         if (logger.isTraceEnabled()) {            logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);         }      }   }   this.checkedElements = checkedElements;}

    二、SmartInstantiationAwareBeanPostProcessor

    2.1、determineCandidateConstructors

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

    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)            throws BeanCreationException {        // Let's check for lookup methods here...        if (!this.lookupMethodsChecked.contains(beanName)) {            try {                ReflectionUtils.doWithMethods(beanClass, method -> {                    Lookup lookup = method.getAnnotation(Lookup.class);                    if (lookup != null) {                        Assert.state(this.beanFactory != null, "No BeanFactory available");                        LookupOverride override = new LookupOverride(method, lookup.value());                        try {                            RootBeanDefinition mbd = (RootBeanDefinition)                                    this.beanFactory.getMergedBeanDefinition(beanName);                            mbd.getMethodOverrides().addOverride(override);                        }                        catch (NoSuchBeanDefinitionException ex) {                            throw new BeanCreationException(beanName,                                    "Cannot apply @Lookup to beans without corresponding bean definition");                        }                    }                });            }            catch (IllegalStateException ex) {                throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);            }            this.lookupMethodsChecked.add(beanName);        }        // Quick check on the concurrent map first, with minimal locking.        Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);        if (candidateConstructors == null) {            // Fully synchronized resolution now...            synchronized (this.candidateConstructorsCache) {                candidateConstructors = this.candidateConstructorsCache.get(beanClass);                if (candidateConstructors == null) {                    Constructor<?>[] rawCandidates;                    try {                        //反射获取所有构造函数                        rawCandidates = beanClass.getDeclaredConstructors();                    }                    catch (Throwable ex) {                        throw new BeanCreationException(beanName,                                "Resolution of declared constructors on bean Class [" + beanClass.getName() +                                        "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);                    }                    //候选构造方法                    List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);                    Constructor<?> requiredConstructor = null;                    Constructor<?> defaultConstructor = null;                    //这个貌似是 Kotlin 上用的, 不用管它                    Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);                    int nonSyntheticConstructors = 0;                    //遍历这些构造函数                    for (Constructor<?> candidate : rawCandidates) {                        //判断构造方法是否是合成的                        if (!candidate.isSynthetic()) {                            nonSyntheticConstructors++;                        }                        else if (primaryConstructor != null) {                            continue;                        }                        //查看是否有 @Autowired 注解                        //如果有多个构造方法, 可以通过标注 @Autowired 的方式来指定使用哪个构造方法                        AnnotationAttributes ann = findAutowiredAnnotation(candidate);                        if (ann == null) {                            Class<?> userClass = ClassUtils.getUserClass(beanClass);                            if (userClass != beanClass) {                                try {                                    Constructor<?> superCtor =                                            userClass.getDeclaredConstructor(candidate.getParameterTypes());                                    ann = findAutowiredAnnotation(superCtor);                                }                                catch (NoSuchMethodException ex) {                                    // Simply proceed, no equivalent superclass constructor found...                                }                            }                        }                        //有 @Autowired 的情况                        if (ann != null) {                            if (requiredConstructor != null) {                                throw new BeanCreationException(beanName,                                        "Invalid autowire-marked constructor: " + candidate +                                                ". Found constructor with 'required' Autowired annotation already: " +                                                requiredConstructor);                            }                            boolean required = determineRequiredStatus(ann);                            if (required) {                                if (!candidates.isEmpty()) {                                    throw new BeanCreationException(beanName,                                            "Invalid autowire-marked constructors: " + candidates +                                                    ". Found constructor with 'required' Autowired annotation: " +                                                    candidate);                                }                                requiredConstructor = candidate;                            }                            candidates.add(candidate);                        }                        //无参构造函数的情况                        else if (candidate.getParameterCount() == 0) {                            //构造函数没有参数, 则设置为默认的构造函数                            defaultConstructor = candidate;                        }                    }                    //到这里, 已经循环完了所有的构造方法                    //候选者不为空时                    if (!candidates.isEmpty()) {                        // Add default constructor to list of optional constructors, as fallback.                        if (requiredConstructor == null) {                            if (defaultConstructor != null) {                                candidates.add(defaultConstructor);                            }                            else if (candidates.size() == 1 && logger.isInfoEnabled()) {                                logger.info("Inconsistent constructor declaration on bean with name '" + beanName +                                        "': single autowire-marked constructor flagged as optional - " +                                        "this constructor is effectively required since there is no " +                                        "default constructor to fall back to: " + candidates.get(0));                            }                        }                        candidateConstructors = candidates.toArray(new Constructor<?>[0]);                    }                    //类的构造方法只有1个, 且该构造方法有多个参数                    else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {                        candidateConstructors = new Constructor<?>[] {rawCandidates[0]};                    }                    //这里不会进, 因为 primaryConstructor = null                    else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&                            defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {                        candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};                    }                    //这里也不会进, 因为 primaryConstructor = null                    else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {                        candidateConstructors = new Constructor<?>[] {primaryConstructor};                    }                    else {                        //如果方法进了这里, 就是没找到合适的构造方法                        //1. 类定义了多个构造方法, 且没有 @Autowired , 则有可能会进这里                        candidateConstructors = new Constructor<?>[0];                    }                    this.candidateConstructorsCache.put(beanClass, candidateConstructors);                }            }        }   //这里如果没找到, 则会返回 null, 而不会返回空数组        return (candidateConstructors.length > 0 ? candidateConstructors : null);    }

    遍历构造方法:

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

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

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

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

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

    注意:

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

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

    “spring自动注入AutowiredAnnotationBeanPostProcessor源码分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

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

    spring自动注入AutowiredAnnotationBeanPostProcessor源码解析

    这篇文章主要介绍了spring自动注入AutowiredAnnotationBeanPostProcessor源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-07

    Spring@Bean注解深入分析源码执行过程

    随着SpringBoot的流行,我们现在更多采用基于注解式的配置从而替换掉了基于XML的配置,所以本篇文章我们主要探讨基于注解的@Bean以及和其他注解的使用
    2023-01-10

    Spring中Bean注入源码示例解析

    这篇文章主要为大家介绍了Spring中Bean注入源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-15

    SpringBoot2入门自动配置原理源码分析

    这篇文章主要介绍“SpringBoot2入门自动配置原理源码分析”,在日常操作中,相信很多人在SpringBoot2入门自动配置原理源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot2
    2023-06-30

    Spring注解之@Import注解的使用和源码分析

    今天主要介绍Spring@Import注解,在Spring中@Import使用得比较频繁,它得作用是导入bean,具体的导入方式有多种,特别在SpringBoot项目中,很多地方都使用到了@Import注解,感兴趣的小伙伴可以参考阅读
    2023-05-16

    Spring声明式事务注解的源码分析

    本文小编为大家详细介绍“Spring声明式事务注解的源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring声明式事务注解的源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、@EnableTr
    2023-07-02

    SpringCloud@RefreshScope注解源码层面深入分析

    @RefreshScope注解能帮助我们做局部的参数刷新,但侵入性较强,需要开发阶段提前预知可能的刷新点,并且该注解底层是依赖于cglib进行代理的,所以不要掉入cglib的坑,出现刷了也不更新情况
    2023-05-15

    Spring@Autowired注解与自动装配的示例分析

    这篇文章主要介绍了Spring@Autowired注解与自动装配的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1 配置文件的方法我们编写spring 框架的代码时候
    2023-05-31

    深入探索Spring AI:源码分析流式回答

    在当今的数字时代,流式响应机制不仅提升了系统的性能,还在用户体验上扮演了关键角色。通过引入 Flux 类型,Spring WebFlux 的设计理念使得应用能够以非阻塞的方式处理并发请求,从而有效利用资源并减少响应延迟。

    springBoot自动注入原理的示例分析

    这篇文章给大家分享的是有关springBoot自动注入原理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。@SpringBootApplication注解解读为什么我们的启动类上标注一个@SpringBo
    2023-06-29

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录