[Spring] @Autowired的工作原理

本文深入探讨了Spring中@Autowired注解的工作原理,包括其放置位置、实现逻辑和主要步骤。@Autowired的实现涉及AutowiredAnnotationBeanPostProcessor后置处理器,通过postProcessMergedBeanDefinition方法解析依赖,然后在postProcessProperties方法中完成属性注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Autowired的作用是自动装配,那么@Autowired是如何实现这个功能的呢?

我们进入@Autowired的源码看看

一、@Autowired的放置位置

首先可以看到Autowired上有三个注解,其中@Traget限制了Autowired的放置位置

@Autowired可以放置在构造方法、普通方法、参数、属性以及另一个注解上。

//@Target注解的作用是:指定可以放置注解的位置

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

二、@Autowired的实现原理

Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor(后置处理器)。 它实现了MergedBeanDefinitionPostProcessor接口,进而实现了接口中的 postProcessMergedBeanDefinition方法,@Autowired注解正是通过这个方法实现注入类型的预解析,将需要依赖注入的属性信息封装到InjectionMetadata类中。

Spring容器启动时,AutowiredAnnotationBeanPostProcessor被注册到容器(refresh方法中registerBeanPostProcessors(beanFactory)),当执行finishBeanFactoryInitialization(beanFactory)方法对非延迟初始化的单例bean进行初始化时,会执行到AbstractAutowireCapableBeanFactory类的doCreateBean方法。在此方法中会执行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)。深入方法中会发现最后调用的是AutowiredAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition方法。

postProcessMergedBeanDefinition方法

此方法调用findAutoWringMetadata方法,是为了找到需要自动装配的元素。

 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
        metadata.checkConfigMembers(beanDefinition);
    }

findAutoWiringMetadata方法

该方法会去调用buildAutowiringMetadata()方法构建元数据信息。

 private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
        String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();

        //检查缓存中是否存在bean

        InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized(this.injectionMetadataCache) {

                检查缓存中是否存在bean

                metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }

                    // 获取目标类对应的自动注入相关的元数据信息
                    metadata = this.buildAutowiringMetadata(clazz);

                    //存入缓存
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }

        return metadata;
    }

 buildAutowiringMetadata方法

通过findAutowiredAnnotation(field)方法查找此属性是否被@Autowired注解修饰,如果带有@Autowired注解,通过反射获取目标类中所有的属性、方法,将每个属性或者方法解析到的元信息保存到List<InjectionMetadata.InjectedElement> elements集合中,属性对应的是AutowiredFieldElement类型,方法对应的则是AutowiredMethodElement类型。将所有的元信息封装成InjectionMetadata并返回。

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;
 
    do {
        // 存放找到的元数据信息
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
 
        // 通过反射获取目标类中所有的字段,并遍历每一个字段,然后通过findAutowiredAnnotation()方法判断字段是否使用@Autowired和@Value修饰,
        // 如果字段被@Autowired和@Value修饰,则返回注解的相关属性信息
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // findAutowiredAnnotation(): 判断字段是否使用@Autowired和@Value修饰,并返回相关属性
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
                // 校验@Autowired和@Value修饰注解是否应用在static方法上
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                // 获取到@Autowired注解的required()的值
                boolean required = determineRequiredStatus(ann);
                // 将该字段封成AutowiredFieldElement对象
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });
 
        // 前面是通过反射获取目标类中所有的字段,这里是通过反射获取目标类中所有的方法
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            AnnotationAttributes 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;
                }
                // 判断方法的参数个数是否为0
                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);
                // 将该字段封成AutowiredMethodElement对象
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });
 
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    // 循环处理父类需要自动装配的元素
    while (targetClass != null && targetClass != Object.class);
    // 将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后合并到Bean定义中
    // 包含所有带有@Autowired注解修饰的一个InjectionMetadata集合. 由两部分组成: 一是我们处理的目标类,二就是上述方法获取到的所以elements集合。
    return new InjectionMetadata(clazz, elements);
}

执行完doCreateBean方法后,执行populateBean方法。此方法中会执行InstantiationAwareBeanPostProcessor的postProcessProperties方法。深入方法中会发现最后调用的是AutowiredAnnotationBeanPostProcessor的postProcessProperties方法。

postProcessProperties方法

findAutowiringMetadata()方法将目标类对应的@Autowired注解元信息都已经解析好存入到缓存injectionMetadataCache中,所以 这里我们直接从缓存中获取即可。

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 首先尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 循环InjectionMetadata的injectedElements属性,挨个调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值
        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;
}

metadata.inject(bean, beanName, pvs)方法。 

在AutowiredAnnotationBeanPostProcessor类中,定义了AutowiredFieldElement以及AutowiredMethodElement:这两个类继承了InjectMetadata.InjectedElement。所以当执行element.inject(target, beanName, pvs)方法的时候,也是调用AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement或AutowiredMethodElement中的inject()方法。

 public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectionMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
        if (!((Collection)elementsToIterate).isEmpty()) {
            Iterator var6 = ((Collection)elementsToIterate).iterator();
             // 循环elementsToIterate, 挨个调用InjectionMetadata.InjectedElement.inject方法,                通过反射方式设置属性的值;
            while(var6.hasNext()) {
                InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var6.next();
                element.inject(target, beanName, pvs);
            }
        }

    }

AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement 中的inject()方法

依赖的对象获取成功后,将会通过反射方式field.set(bean, value)设置bean对象中的被@Autowired修饰的属性的值。

 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 = AutowiredAnnotationBeanPostProcessor.this.resolvedCachedArgument(beanName, this.cachedFieldValue);
                } catch (NoSuchBeanDefinitionException var7) {
                    value = this.resolveFieldValue(field, bean, beanName);
                }
            } else {
               // 通过beanFactory.resolveDependency()方法从bean工厂中获取依赖的对象。跟踪下resolveDependency()方法可以发现,
                //底层会调用到org.springframework.beans.factory.config.DependencyDescriptor中的resolveCandidate()方法,
                //而resolveCandidate()方法内部其实是通过beanFactory.getBean("beanName")从bean容器中获取到这个bean对象
                value = this.resolveFieldValue(field, bean, beanName);
            }

            if (value != null) {
                //field是bean对象的属性
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }

        }

三、总结:

Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor(后置处理器)

主要分为两个步骤:

1.找出需要自动装配的元素:postProcessMergedBeanDefinition方法;
2.注入属性:postProcessProperties方法;

---------------------------------------------------------------------------------------------------------------------------------
参考:https://blog.youkuaiyun.com/Weixiaohuai/article/details/123005140

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值