Spring @Autowired自动装配的实现机制

Spring @Autowired自动装配的实现机制

  • [`@Autowired` 注解实现原理详解](#@Autowired 注解实现原理详解)
    • [一、`@Autowired` 注解定义](#一、@Autowired 注解定义)
    • [二、@Qualifier 注解辅助指定 Bean 名称](#二、@Qualifier 注解辅助指定 Bean 名称)
    • [三、BeanFactory:按类型获取 Bean](#三、BeanFactory:按类型获取 Bean)
    • 四、注入逻辑实现
    • 五、小结

源码见:mini-spring

@Autowired 注解实现原理详解

@Autowired 的注入机制与 @Value 注解非常相似,不同之处在于:

  • @Value 主要注入的是常量值或配置项(如 ${} 表达式);

  • @Autowired 注入的是 Spring 容器中的 Bean 实例,也即对象引用。


一、@Autowired 注解定义

java 复制代码
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

默认情况下,@Autowired 按类型注入(byType)。如果容器中存在多个相同类型的 Bean,会默认注入第一个;如需精确指定,可以配合 @Qualifier 使用。


二、@Qualifier 注解辅助指定 Bean 名称

java 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target({
    ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
    ElementType.TYPE, ElementType.ANNOTATION_TYPE
})
@Inherited
@Documented
public @interface Qualifier {
    String value() default "";
}

@Qualifier 允许通过名称精确指定注入的 Bean,从而避免类型冲突或歧义。


三、BeanFactory:按类型获取 Bean

为了支持类型注入,我们需要在 BeanFactory 接口中添加一个按类型获取 Bean 的方法:

java 复制代码
/**
 * 根据指定类型获取 Bean 实例。
 * 若存在多个该类型的 Bean,可能抛出异常。
 */
<T> T getBean(Class<T> requiredType);

DefaultListableBeanFactory 中进行实现:

java 复制代码
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
    List<String> beanNames = new ArrayList<>();
    for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
        Class<?> beanClass = entry.getValue().getBeanClass();
        if (requiredType.isAssignableFrom(beanClass)) {
            beanNames.add(entry.getKey());
        }
    }

    if (beanNames.size() == 1) {
        return super.getBean(beanNames.get(0), requiredType);
    }

    throw new BeansException(requiredType + 
        " expected single bean but found " + 
        beanNames.size() + ": " + beanNames);
}

四、注入逻辑实现

@Autowired 的实现依赖于 Spring 的扩展点 BeanPostProcessor,更具体地说,是在 InstantiationAwareBeanPostProcessor 接口中重写的 postProcessPropertyValues 方法完成注入逻辑。

以下是字段注入的核心实现逻辑(简化版):

java 复制代码
for (Field field : declaredFields) {
    // 检查是否标注 @Autowired
    Autowired autowired = field.getAnnotation(Autowired.class);
    if (autowired != null) {
        Class<?> type = field.getType();
        Object dependentBean;

        // 优先检查 @Qualifier 注解
        Qualifier qualifier = field.getAnnotation(Qualifier.class);
        if (qualifier != null) {
            String beanName = qualifier.value();
            dependentBean = beanFactory.getBean(beanName);
        } else {
            // 根据类型获取 Bean
            dependentBean = beanFactory.getBean(type);
        }

        // 直接通过反射注入字段(此处未处理复杂依赖)
        BeanUtil.setFieldValue(bean, field.getName(), dependentBean);

        // 原生 Spring 会构建 PropertyValue 并走完整依赖注入流程
        // pvs.addPropertyValue(new PropertyValue(field.getName(), dependentBean));
    }
}

本实现简化了原生 Spring 中的依赖注入逻辑,未处理循环依赖、构造器注入、多候选 Bean 等复杂情况。

五、小结

  • @Autowired 实现基于反射和后置处理器(BeanPostProcessor);

  • 默认按类型注入,配合 @Qualifier 可精确按名称注入;

  • 实际注入发生在 Bean 实例化之后,属性填充阶段;

  • @Value 类似,都通过 InstantiationAwareBeanPostProcessorpostProcessPropertyValues 方法实现。

相关推荐
xin_nai1 小时前
LeetCode热题100(Java)(6)矩阵
java·leetcode·矩阵
代码AI弗森6 小时前
一文理清楚“算力申请 / 成本测算 / 并发评估”
java·服务器·数据库
Old Uncle Tom7 小时前
OpenClaw 记忆系统 -- 记忆预加载
java·数据结构·算法·agent
小小小米粒7 小时前
Collection单列集合、Map(Key - Value)双列集合,多继承实现。
java·开发语言·windows
前端一小卒7 小时前
我用 Claude Code 的 Superpowers 技能链写了个服务,部署前差点把服务器搞炸
前端·javascript·后端
摇滚侠7 小时前
expdp 查看帮助
java·数据库·oracle
:1218 小时前
java基础
java·开发语言
曹牧9 小时前
Spring:@RequestMapping注解,匹配的顺序与上下文无关
java·后端·spring
daixin88489 小时前
cursor无法正常使用gpt5.5等模型解决方案
java·redis·cursor
韦禾水9 小时前
记录一次项目部署到tomcat的异常
java·tomcat