## spring-@Autowired实现

news2024/11/8 20:37:02

spring-@Autowired实现

我们知道 spring 中有很多的后置处理器 BeanPostProcessor, 而 @Autowired 就是通过 AutowiredAnnotationBeanPostProcessor 来实现的

与之相似的还有 CommonAnnotationBeanPostProcessor 处理 @Resource 注解

AutowiredAnnotationBeanPostProcessor

构造函数

public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                                          ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

可以看出 AutowiredAnnotationBeanPostProcessor 同时处理 @Autowird和@Value 的解析

主要看 AutowiredAnnotationBeanPostProcessor#postProcessProperties 方法, postProcessPropertyValues 这个方法被遗弃了

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //找到有autowired 和 value的属性或者方法
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}


private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    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;
}

//通过反射获取类字段和带有autowired的注解
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
        return InjectionMetadata.EMPTY;
    }

    final List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> fieldElements = new ArrayList<>();
        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);
                fieldElements.add(new AutowiredFieldElement(field, required));
            }
        });

        final List<InjectionMetadata.InjectedElement> methodElements = new ArrayList<>();
        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);
                methodElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, sortMethodElements(methodElements, targetClass));
        elements.addAll(0, fieldElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return InjectionMetadata.forElements(elements, clazz);
}

注意,这里加入的是 AutowiredFieldElementAutowiredMethodElement

通过InjectionMetadata#inject方法注入


public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
        (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        for (InjectedElement element : elementsToIterate) {
            element.inject(target, beanName, pvs);
        }
    }
}

这里就要看 InjectedElement 的实现类了,以刚才 AutowiredFieldElement 为例

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

    private final boolean required;

    private volatile boolean cached;

    @Nullable
    private volatile Object cachedFieldValue;

    public AutowiredFieldElement(Field field, boolean required) {
        super(field, null);
        this.required = required;
    }

    @Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Field field = (Field) this.member;
        Object value;
        if (this.cached) {
            try {
                value = resolveCachedArgument(beanName, this.cachedFieldValue);
            }
            catch (BeansException ex) {
                // Unexpected target bean mismatch for cached argument -> re-resolve
                this.cached = false;
                logger.debug("Failed to resolve cached argument", ex);
                value = resolveFieldValue(field, bean, beanName);
            }
        }
        else {
            value = resolveFieldValue(field, bean, beanName);
        }
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }

    @Nullable
    private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
        Assert.state(beanFactory != null, "No BeanFactory available");
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        Object value;
        try {
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            if (!this.cached) {
                if (value != null || this.required) {
                    Object cachedFieldValue = desc;
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (value != null && autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        if (beanFactory.containsBean(autowiredBeanName) &&
                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                            cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
                        }
                    }
                    this.cachedFieldValue = cachedFieldValue;
                    this.cached = true;
                }
                else {
                    this.cachedFieldValue = null;
                    // cached flag remains false
                }
            }
        }
        return value;
    }
}

继续跟进 beanFactory.resolveDependency 方法 ,DefaultListableBeanFactory#doResolveDependency:

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                                  @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }

        Class<?> type = descriptor.getDependencyType();
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                                     getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            try {
                return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
            }
            catch (UnsupportedOperationException ex) {
                // A custom TypeConverter which does not support TypeDescriptor resolution...
                return (descriptor.getField() != null ?
                        converter.convertIfNecessary(value, type, descriptor.getField()) :
                        converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
            }
        }

        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }

        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        if (instanceCandidate instanceof Class) {
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

再看 value instanceof String里面的 resolveEmbeddedValue 方法,这个就是处理 @Value处理的逻辑

public String resolveEmbeddedValue(@Nullable String value) {
    if (value == null) {
        return null;
    }
    String result = value;
    for (StringValueResolver resolver : this.embeddedValueResolvers) {
        result = resolver.resolveStringValue(result);
        if (result == null) {
            return null;
        }
    }
    return result;
}

最后交给了 StringValueResolver 去处理

  • PropertyPlaceholderConfigurerResolver: 处理占位符
  • StaticStringValueResolver: 处理静态变量
private class PlaceholderResolvingStringValueResolver implements StringValueResolver {

    private final PropertyPlaceholderHelper helper;

    private final PlaceholderResolver resolver;

    public PlaceholderResolvingStringValueResolver(Properties props) {
        this.helper = new PropertyPlaceholderHelper(
            placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
        this.resolver = new PropertyPlaceholderConfigurerResolver(props);
    }

    @Override
    @Nullable
    public String resolveStringValue(String strVal) throws BeansException {
        String resolved = this.helper.replacePlaceholders(strVal, this.resolver);
        if (trimValues) {
            resolved = resolved.trim();
        }
        return (resolved.equals(nullValue) ? null : resolved);
    }
}

最终都交给 PropertyPlaceholderHelper#replacePlaceholders方法处理

现在回过头看下是在哪里调用了AutowiredAnnotationBeanPostProcessor#ostProcessProperties,不难发现,是在我们对bean初始化的时候,具体是在AbstractAutowiredCapableBeanFactory#populateBean 方法上:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            return;
        }
    }

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            //这里就是AutowiredAnnotationBeanPostProcessor入口
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

因为 AutowiredAnnotationBeanPostProcessor 也是 InstantiationAwareBeanPostProcessor 子类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1261663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

入金牌投资平台,学先进炒股技术,掌未来宝贵财富

钱是个好东西&#xff0c;它能让人享受到世间的甜&#xff0c;它能让人感受到万众瞩目的荣耀&#xff0c;它能让人得到一切该有的尊敬。可以这么说&#xff0c;没有人不爱钱。可是&#xff0c;君子爱财取之有道。对于正常的人而言&#xff0c;都只希望通过正规的渠道赚到尽可能…

SSL证书是选免费的还是付费的好?

在当今的数字化时代&#xff0c;网络安全已经成为了每个网站和应用程序的重要组成部分。为了保护用户的数据安全&#xff0c;许多网站和应用程序都选择了使用SSL证书。然而&#xff0c;面对市场上的各种SSL证书&#xff0c;用户往往会面临一个问题&#xff1a;SSL证书是选免费的…

抽象类-Java

抽象类 一、父类方法的不确定性二、抽象类介绍三、抽象类细节四、练习题 一、父类方法的不确定性 引入&#xff1a;对于一个动物&#xff0c;不知道它吃什么&#xff0c;比如猫吃鱼&#xff0c;兔子吃萝卜。动物类中的 eat 方法往往由它的子类去具体实现。 class Animal {pub…

前端开发学习 (三) 列表功能

一、列表功能 1、列表功能 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compa…

Buzz库python代码示例

Buzz库来编写一个下载器程序。 php <?php require_once vendor/autoload.php; // 引入Buzz库 use Buzz\Browser; use Buzz\Message\Response; $browser new Browser(); // 设置 $browser->setHttpClient(new HttpClientProxy([ host > , port > , ])…

c++容器详解Vector、deque、list、set、multiset、map、multimap、queue、stcak、Array

容器 数据结构描述实现头文件向量(vector)连续存储的元素<vector>列表(list)由节点组成的双向链表,每个结点包含着一个元素<list>双向队列(deque)连续存储的指向不同元素的指针所组成的数组<deque>集合(set)由节点组成的红黑树,每个节点都包含着一个元素,…

chatglm3 vllm部署推理;api访问使用

用fastchat部署暂时有各种问题,参考:https://github.com/lm-sys/FastChat/pull/2622 本篇用vllm运行测试可以使用 1、vllm运行 python -m vllm.entrypoints.api_server --model /***/chatglm/chatglm3-6b/

景联文科技加入中国人工智能产业联盟(AIIA)数据委员会

近日&#xff0c;景联文科技加入中国人工智能产业联盟&#xff08;AIIA&#xff09;数据委员会&#xff0c;成为委员会成员单位。 中国人工智能产业发展联盟&#xff08;简称AIIA&#xff09;是在国家发改委、科技部、工信部、网信办指导下&#xff0c;由中国信息通信研究院等单…

colab notebook导出为PDF

目录 方法一&#xff1a;使用浏览器打印功能 方法二&#xff1a;使用nbconvert转换 方法三&#xff1a;在线转换 方法一&#xff1a;使用浏览器打印功能 一般快捷键是CTRLP 然后改变目标打印机为另存为PDF 这样就可以将notebook保存为PDF了 方法二&#xff1a;使用nbconver…

【labelimg使用小技巧】

小技巧 打开labelimg后&#xff0c;在上方的视图中&#xff0c;勾选自动保存&#xff0c;即可每次操作后自行保存&#xff0c;无需确认保存所在文件位置 上述勾选完成后&#xff0c;W为新建标注框&#xff0c;进行命名后&#xff0c;S即为切换下一张图像 如何放大图片呢 &am…

linux查看emmc分区信息(10种方法 )

目录 ## 1 emmc ## 2 uboot查看 ## 3 kernel查看 方法1 方法2 方法3 方法4 方法5 方法6 方法7 方法8 方法9 方法10 ## 1 emmc 我们要说的是&#xff0c;User Data Partition中的再分区 可简化为 ## 2 uboot查看 u-boot> mmc partPartition Map for MMC device…

界面控件DevExpress WPF流程图组件,完美复制Visio UI!(二)

DevExpress WPF Diagram&#xff08;流程图&#xff09;控件帮助用户完美复制Microsoft Visio UI&#xff0c;并将信息丰富且组织良好的图表、流程图和组织图轻松合并到您的下一个WPF项目中。 在上文中&#xff08;点击这里回顾>>&#xff09;&#xff0c;我们为大家介绍…

【unity实战】基于权重的随机事件(附项目源码)

文章目录 前言开始一、简单的使用二、完善各种事件1. 完善生成金币事件2. 完善生成敌人事件敌人3. 完善生成药水事件 最终效果参考源码完结 前言 随机功能和UnityEvent前面其实我们都已经做过了&#xff0c;但是随机UnityEvent事件要怎么使用呢&#xff1f;这里就来举一个例子…

技术人如何实现颠覆式成长

前言 颠覆式成长要求个人不断创新、承担风险&#xff0c;并抓住机遇。通过创新的方法&#xff0c;充分发挥个人的优势&#xff0c;并在个人成长中突破传统、发挥独特的方式和思考&#xff0c;从而实现个人创造力和效能的突破。 颠覆式成长需要不断学习和个人发展&#xff0c;…

2015年五一杯数学建模A题不确定性条件下的最优路径问题解题全过程文档及程序

2015年五一杯数学建模 A题 不确定性条件下的最优路径问题 原题再现 目前&#xff0c;交通拥挤和事故正越来越严重的困扰着城市交通。随着我国交通运输事业的迅速发展&#xff0c;交通“拥塞”已经成为很多城市的“痼疾”。在复杂的交通环境下&#xff0c;如何寻找一条可靠、快…

(C++)字符串相乘

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 题目链接如下&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名…

Docker 容器日志查看和清理

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

山寨Stream API

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 一个需求 List<Per…

LeetCode [简单](非递归)二叉树的中序遍历

遍历左孩子&#xff0c;将他们放进栈中&#xff0c;左边走到尽头&#xff0c;出栈&#xff0c;root变为栈顶元素&#xff0c;存值&#xff0c;向右边走一个 再次遍历左孩子&#xff0c;将他们放入栈中&#xff0c;如果没有左孩子了&#xff0c;就出栈&#xff0c;root变为栈顶…