iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >spring自动注入AutowiredAnnotationBeanPostProcessor源码分析
  • 106
分享到

spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

2023-07-05 10:07:22 106人浏览 泡泡鱼
摘要

本篇内容介绍了“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源码分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: spring自动注入AutowiredAnnotationBeanPostProcessor源码分析

    本文链接: https://www.lsjlt.com/news/350994.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

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

    下载Word文档
    猜你喜欢
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作