专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

spring 源码之 @Autowired @Value 是怎么实现的

常用的@Autowired

这个估计是使用spring最常用的注解了,往一个bean添加依赖,作用应该众所周知

@Value

@Value 一般用作配置类,比如:

   @Value("${file.server.host}")
    private String basicHost;

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 是解析这两个注解的关键

 * @see Autowired
 * @see Value
 */
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
        }

可以看到这个类,继承了InstantiationAwareBeanPostProcessorAdapter实现了父类方法postProcessProperties。并且实现了MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition。这两个bean后置处理器再bean实例化,初始化过程都有有作用的,详情请见 tech.souyunku.com5efefb…

AutowiredAnnotationBeanPostProcessor实例化做了什么

    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
 .......省略添加 @Inject 的方法
    }

实例化的时候往 autowiredAnnotationTypes 这个set集合放入 Autowired 和value这两个classs。

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    //重要方法,往下走
        InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
//......校验获取缓存key,省略
//从缓存中获取 InjectionMetadata
        InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        //重复校验,从缓存取,省略
        //重要,往下走就会解析
                    metadata = buildAutowiringMetadata(clazz);
        //将获取到的metadata放到缓存中,让下次的后置处理器来取(postProcessProperties)         
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }
        return metadata;
    }

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

        do {
            final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//对属性的解析 遍历 autowiredAnnotationTypes(初始化的时候塞了三个注解进去)
//看是否这个类的属性有这三个注解,如果有就放到List中缓存下来
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
            //找属性是否有@Autowired @Value @Inject
                AnnotationAttributes ann = findAutowiredAnnotation(field);
                if (ann != null) {
                //判断注解的 require 属性
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });
//.....上面是对属性的解析,下面是对方法的解析方法也可以@Autowire等注解
//大概意思差不多就省略,只是两个解析后的结果封装的对象不同
//属性:AutowiredFieldElement 方法:AutowiredMethodElement  
//都是继承  InjectionMetadata.InjectedElement

        }
        while (targetClass != null && targetClass != Object.class);
//将解析完之后的elements(List) 放到 InjectionMetadata对象中,然后缓存到map中
        return new InjectionMetadata(clazz, elements);
    }

将解析出来之后的数据放到缓存之后,肯定有人取get缓存然后处理,如果了解bean的初始化就知道是哪个类的哪个方法去取这个缓存来解析的

AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

这个方法也在spring的后置处理器中讲过了,主要是往bean中填充属性等等

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//调用上面的findAutowiringMetadata这个方法
//这个方法刚才也看了,一进去就会往缓存中取数据
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
        //调用inject,往下看inject做了什么
            metadata.inject(bean, beanName, pvs);
        }
        return pvs;
    }

    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//............
//循环injectedElements 这个就是刚才解析完放到缓存的List
            for (InjectedElement element : elementsToIterate) {
            //往下看inject做了什么
                element.inject(target, beanName, pvs);
            }
        }
    }

以属性的解析为例

@Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
...........
//这个很重要,主要存放bean属性的一些描述
//比如属性的class,属性的名称,属性是否必须等等
                DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
                Assert.state(beanFactory != null, "No BeanFactory available");
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                try {
                //重要,从spring中获取依赖,其实这里才是依赖注入的核心
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                }
                 //....一些校验等省略
            }
            if (value != null) {
            //调用反射,将属性设置进去,如果是方法其实也是调用反射
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }
        }
    }

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

    //.......去掉对属性类型的判断,比如Optional,ObjectFactory,ObjectProvider等判断
    //....
            if (result == null) {
            //真正干活的来了,往下走
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }


@Nullable public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { //........不影响主流程的 忽略 //这个可以看下,主要是判断依赖注入的属性是不是map,list,array等集合数组 //所以spring可以 @Autowire 一个List,map,当然前提是他们有多个实现 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } //.....省略有关集合数组等处理,正常情况下很少用到 if (instanceCandidate instanceof Class) { //最主要的来了 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } //......... }
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);这句代码做了什么往下点进去

    public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
            throws BeansException {
//其实就是调用beanFactory的getBean取获取实例
        return beanFactory.getBean(beanName);
    }

到这里算是解析完了,最后还是调用bean工厂的getBean获取到依赖的bean然后用反射注入进去

总结

AutowiredAnnotationBeanPostProcessor 主要是解决@Autowired 和 @Value注解的关键, AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter这两个,再bean的实例化过程分别先后被调用相应的方法 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 是先调用解析出需要依赖注入的属性,放到缓存中。 InstantiationAwareBeanPostProcessorAdapte#postProcessProperties 后执行,这是后缓存中已经有了需要依赖注入的属性集合,直接拿,然后解析,最终通过bean工厂的getBean方法从spring容器中获取依赖,调用反射注入进去。

文章永久链接:https://tech.souyunku.com/26703

未经允许不得转载:搜云库技术团队 » spring 源码之 @Autowired @Value 是怎么实现的

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们