Spring源码中如何处理Autowire 和 resource的

133 阅读4分钟

先看一个案例

package com.example.demo.car;

public interface Engine {
    void run();
}

@Component
public class BMWEngine implements Engine {
    @Override
    public void run() {
        System.out.println("BMWEngine running");
    }
}

@Component
public class MazdaEngine  {
}

我们只定义一个Engine实现类BMWEngine,对于需要自动注入的类

@Component
public class CarA {

    // 1. @Autowired 按类型注入,配合 @Qualifier 按名称
    @Autowired
    private Engine mazdaEngine;
}

@Component
public class CarB {

    // 2. @Resource 默认按名称注入
    @Resource
    private Engine mazdaEngine;
}

看起来两个除了注解不一样(@Resource 和 @Autowired)其他都一样, 只有一个Engine 实现类,能正确注入。

但是 CarA 在找不到mazdaEngine名称的Engine实现类会@Autowired根据类型找到BMWEngine,而CarB则根据mazdaEngine找到了对应的类但发现类型不一致抛了异常

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'mazdaEngine' is expected to be of type 'com.example.demo.car.Engine' but was actually of type 'com.example.demo.car.MazdaEngine'
	at org.springframework.beans.factory.support.AbstractBeanFactory.adaptBeanInstance(AbstractBeanFactory.java:417)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:398)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:550)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:520)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:673)
	at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:228)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329)
	... 12 more

具体在spring源码如何处理这两个注解的?

首先看下 spring 的初始化流程

你可能疑问,这B咋还不引入正题,其实这两个注解是初始化流程的一部分,是不能脱离初始化过程来弹得
每个 Spring 类会放在 BeanDefinition 中,BeanDefinition 包含初始化对象的相关信息,如有所属类、class、ID、factory method、factory class、scope(单例or原型) 等属性。BeanDefinition 一般放置在 Map 中,即 BeanDefinitionMap,在一个 Spring 进程中只有一份。

Spring初始化时会按beanDefinitionMap循环调用初始化方法,该方法在BeanFactory.getBean中。BeanFactory.getBean会先在singletonOobjectsMap(也是一个map,key是类名,value是具体实例对象)中查找,若找不到则执行bean初始化过程。初始化这些对象时会递归调用BeanFactory.getBean,此时会有循环依赖问题,Spring通过三级缓存处理。对象初始化完才会放到singletonObjectMap中。通过ApplicationContext来获取的getBean其实本身也是通过BeanFactory.getBean,只是做了一层门面。 image.png

org.springframework.context.annotation.AnnotationConfigApplicationContext 实际使用的 org.springframework.beans.factory.support.DefaultListableBeanFactory

image.png

以下是创建bean的流程

populateBean处理需要依赖注入的属性,解析 @Resource 或 @Autowire的注解

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 1. 实例化 bean
        Object beanInstance = createBeanInstance(beanName, mbd, args);

        // 2. 处理循环依赖(提前暴露 bean)
        if (allowCircularReferences) {
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, beanInstance));
        }

        // 3. 填充属性(依赖注入)
        populateBean(beanName, mbd, instanceWrapper);

        // 4. 初始化 bean
        Object exposedObject = initializeBean(beanName, beanInstance, mbd);

        // 5. AOP 代理处理
        // 6. 注册销毁回调

        return exposedObject;
    }
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        // 1. 检查 bean 是否已实例化
        if (bw == null) return;

        // 2. 处理 InstantiationAwareBeanPostProcessor
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors()) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return; // 跳过后续属性注入
            }
        }

        // 3. 获取属性值
        PropertyValues pvs = mbd.getPropertyValues();

        // 4. 允许后置处理器修改属性值(如处理@Autowired、@Resource等)
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors()) {
            pvs = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            // 兼容老接口
            if (pvs == null) {
                pvs = bp.postProcessPropertyValues(pvs, bw.getPropertyDescriptors(), bw.getWrappedInstance(), beanName);
            }
        }

        // 5. 应用属性值(依赖注入)
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        // 1. 处理 Aware 接口
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }

        // 2. BeanPostProcessor 前置处理
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 3. 调用初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);

        // 4. BeanPostProcessor 后置处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

        // 5. 返回
        return wrappedBean;
    }
}

在看看注解处理器具体代码

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

截屏2025-05-10 15.51.16.png

image.png 都实现了 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
       return null;
    }

    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
       return true;
    }

    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
          throws BeansException {

    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
          PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

       return pvs;
    }

}

postProcessPropertyValues 是Deprecated的,剩下两个方法是从BeanPostProcessor继承的直接空实现了,现在只要看两个类的 postProcessProperties 实现有什么不同就可以了
这里写的比较简略,只标注了差异部分,小伙伴可以直接打开spring源码看

Autowire

AutowiredAnnotationBeanPostProcessor最终调用到DefaultListableBeanFactory的resolveDependency, findAutowireCandidates 会根据类型找到符合的Bean,如果有多个再根据名称筛一遍

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
        @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        // 省略
        // 1. 查找所有候选bean(按类型、限定符等)
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            // 5. 没有找到候选bean,且依赖是必须的,抛出异常
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }
        // 省略
        String autowiredBeanName;
        Object instanceCandidate;
        // 省略
        if (matchingBeans.size() > 1) {
            // 有多个候选bean,优先选择@Primary/@Priority或名称匹配的bean
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            // 省略
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        } else {
            // 只有一个候选bean,直接使用
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }
        // 省略
        Object result = instanceCandidate;
        return result;
}
}

Resource

CommonAnnotationBeanPostProcessor 最后调用到AbstractAutowireCapableBeanFactory.getBean, 如果找到对应名称的类不符合要求的类型会报错 BeanNotOfRequiredTypeException

public abstract class AbstractAutowireCapableBeanFactory
	@Override
	public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			return getBean(name, descriptor.getDependencyType());
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}
}

结论

@Resource 和 @Autowire 均用于 Java 中 Spring 的自动注入 IOC。它们的区别在于来源不同,Resource 是 JavaEE 中的,Autowire 是 Spring 框架中的。Resource 主要先根据名称,再根据类型。若名称匹配但类型与接受类型不兼容则会报错, 若名称不匹配且找不到才会根据类型,此时若有对应类型才会匹配。Autowire 则先根据类型再根据名称,当类型匹配多个时才会去找名称,且名称要与 Spring 注册的类匹配。若名称与具体类不同,可加上 Qualifier 注解指定要匹配的类,即它们注入类的查找方式不同。