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 类似,都通过 InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues 方法实现。

相关推荐
程序员cxuan4 分钟前
Gemini 4 Argon 正式发布!
人工智能·后端·程序员
StevenLdh9 分钟前
第八期 · 情绪闯关挑战盒:一个「无惩罚」成就系统的数据建模
java·微信小程序
小陈phd13 分钟前
深入理解agent学习笔记(五)——KV Cache友好的上下文设计
笔记·学习·spring
Wang's Blog17 分钟前
Java 项目实战: 交友项目 - 入门案例:编写 Dubbo 服务消费者
java·dubbo·交友
IT研究室25 分钟前
最新计算机毕业设计选题推荐-基于spring boot的教育学习平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
亚林瓜子27 分钟前
Spring Boot 集成 ip2region 离线 IP 库实战指南
java·spring boot·后端·ip·ip2region
盛世宏博智慧档案1 小时前
恒湿净化一体机联动开发:档案馆温湿度阈值判断与启停控制实践
java·后端·struts·恒湿机·加湿除湿消毒净化一体机
兔子零10241 小时前
FastAPI 零基础入门教程:写过 Node.js,就能轻松学会 Python 后端开发(一)
前端·后端·python
Thneonl1 小时前
ZK、etcd、Consul 怎么选:差别不在共识,在壳
后端·架构
vipxieliang1 小时前
ValidX 应用于 HR系统员工信息验证:入职、离职、社保数据
java·spring boot·后端