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

相关推荐
hqxstudying14 分钟前
Java异常处理
java·开发语言·安全·异常
代码老y15 分钟前
ASP.NET Core 高并发万字攻防战:架构设计、性能优化与生产实践
后端·性能优化·asp.net
我命由我123453 小时前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list
武子康5 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
舒一笑6 小时前
我的开源项目-PandaCoder迎来史诗级大更新啦
后端·程序员·intellij idea
@昵称不存在7 小时前
Flask input 和datalist结合
后端·python·flask
zhuyasen7 小时前
Go 分布式任务和定时任务太难?sasynq 让异步任务从未如此简单
后端·go
东林牧之8 小时前
Django+celery异步:拿来即用,可移植性高
后端·python·django
YuTaoShao8 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw8 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友