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 方法实现。

相关推荐
五岳23 分钟前
深入研究使用DozerMapper复制List<Ojbect>前后元素类型不一致的问题
java·爬坑
人生在勤,不索何获-白大侠33 分钟前
day15——Java常用API(二):常见算法、正则表达式与异常处理详解
java·算法·正则表达式
Bug退退退12337 分钟前
RabbitMQ 高级特性之消息确认
java·分布式·rabbitmq
master-dragon1 小时前
spring-ai 工作流
人工智能·spring·ai
考虑考虑1 小时前
使用jpa中的group by返回一个数组对象
spring boot·后端·spring
GiraKoo1 小时前
【GiraKoo】C++11的新特性
c++·后端
MO2T1 小时前
使用 Flask 构建基于 Dify 的企业资金投向与客户分类评估系统
后端·python·语言模型·flask
云动雨颤1 小时前
Java并发性能优化|读写锁与互斥锁解析
java
光溯星河1 小时前
【实践手记】Git重写已提交代码历史信息
后端·github
ldj20201 小时前
Centos 安装Jenkins
java·linux