Spring依赖注入源码深度解析:从@Autowired到@Resource的完整实现机制

一、依赖注入全景图:Spring的四种注入方式

在深入源码之前,先了解Spring支持的四种依赖注入方式及其关系:

完整依赖注入流程图


二、手动注入:XML配置的传统方式

1. Setter方法注入

复制代码
<bean name="userService" class="com.luban.service.UserService">
    <property name="orderService" ref="orderService"/>
</bean>

底层实现:通过反射调用setOrderService()方法

2. 构造器注入

复制代码
<bean name="userService" class="com.luban.service.UserService">
    <constructor-arg index="0" ref="orderService"/>
</bean>

底层实现:通过构造方法反射创建对象时传入参数


三、自动注入:XML的autowire机制

1. autowire的五种模式

复制代码
<bean id="userService" class="com.service.UserService" autowire="byType"/>
模式 说明 使用场景
byType 按类型自动注入 属性类型在容器中唯一时
byName 按名称自动注入 属性名与beanName匹配时
constructor 构造器自动注入 通过构造方法注入时
default 默认值 继承<beans>标签的设置
no 关闭自动注入 明确不自动注入时

2. autowire的底层实现原理

2.1 PropertyDescriptor:方法解析器

Spring解析类中的所有方法,生成PropertyDescriptor对象:

复制代码
public class PropertyDescriptor {
    private String name;              // 处理后的属性名(去掉get/set/is前缀)
    private Method readMethod;        // get/is方法
    private Method writeMethod;       // set方法
    private Class<?> propertyType;    // 属性类型
}

方法识别规则

  • get方法:无参,以"get"开头,或"is"开头且返回boolean

  • set方法:一个参数,以"set"开头,返回void

2.2 byType注入流程
复制代码
// 伪代码表示byType注入逻辑
for (PropertyDescriptor pd : propertyDescriptors) {
    if (pd.getWriteMethod() != null) {  // 有set方法
        Class<?> paramType = pd.getWriteMethod().getParameterTypes()[0];
        Object bean = beanFactory.getBean(paramType);  // 按类型查找
        pd.getWriteMethod().invoke(targetBean, bean);  // 调用set方法
    }
}
2.3 byName注入流程
复制代码
// 伪代码表示byName注入逻辑
for (PropertyDescriptor pd : propertyDescriptors) {
    String propertyName = pd.getName();  // 属性名
    if (beanFactory.containsBean(propertyName)) {
        Object bean = beanFactory.getBean(propertyName);
        pd.getWriteMethod().invoke(targetBean, bean);
    }
}
2.4 constructor注入

相当于byType和byName的结合:先按类型查找,找到多个时再按参数名确定。


四、@Autowired注解:细粒度的自动注入

@Autowired注解流程图如下所示:

1. @Autowired vs XML autowire

Spring官方文档明确指出:

"@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性。"

核心区别

  • XML autowire:控制整个Bean的所有属性

  • @Autowired:控制单个属性/方法/构造方法

2. @Autowired的三种使用方式

2.1 字段注入
复制代码
@Component
public class UserService {
    @Autowired
    private OrderService orderService;
}

注入流程:先按类型(OrderService)查找,找到多个再按字段名(orderService)确定

2.2 Setter方法注入
复制代码
@Component
public class UserService {
    private OrderService orderService;
    
    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}
2.3 构造器注入
复制代码
@Component
public class UserService {
    private final OrderService orderService;
    
    @Autowired
    public UserService(OrderService orderService) {
        this.orderService = orderService;
    }
}

3. @Autowired的源码实现

3.1 寻找注入点

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()中:

复制代码
protected void findAutowiringMetadata(String beanName, Class<?> clazz) {
    // 1. 遍历所有字段
    for (Field field : clazz.getDeclaredFields()) {
        // 检查是否有@Autowired、@Value、@Inject注解
        if (field.isAnnotationPresent(Autowired.class)) {
            // 跳过static字段
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            // 构建AutowiredFieldElement
            elements.add(new AutowiredFieldElement(field, required));
        }
    }
    
    // 2. 遍历所有方法
    for (Method method : clazz.getDeclaredMethods()) {
        // 处理桥接方法
        Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
        if (bridgedMethod.isAnnotationPresent(Autowired.class)) {
            // 跳过static方法
            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }
            // 构建AutowiredMethodElement
            elements.add(new AutowiredMethodElement(method, required));
        }
    }
    
    // 3. 递归处理父类
    if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
        findAutowiringMetadata(beanName, clazz.getSuperclass());
    }
}
3.2 为什么static字段/方法不支持注入?
复制代码
@Component
@Scope("prototype")
public class UserService {
    @Autowired
    private static OrderService orderService;  // 错误!不支持static字段注入
}

原因分析:假设UserService是原型Bean

  1. 创建userService1时,static orderService被注入值A

  2. 创建userService2时,static orderService被注入值B(覆盖A)

  3. userService1.orderService的值变成了B,造成数据混乱

3.3 桥接方法处理

当类实现泛型接口时,编译器会生成桥接方法:

复制代码
public interface UserInterface<T> {
    void setOrderService(T t);
}

@Component
public class UserService implements UserInterface<OrderService> {
    @Override
    @Autowired
    public void setOrderService(OrderService orderService) {
        // 实际方法
    }
    
    // 编译器生成的桥接方法
    @Autowired
    public synthetic bridge void setOrderService(Object orderService) {
        setOrderService((OrderService) orderService);
    }
}

Spring需要处理这种情况,找到真正的原方法而不是桥接方法。

4. 注入点注入过程

AutowiredAnnotationBeanPostProcessor.postProcessProperties()中:

4.1 字段注入
复制代码
// AutowiredFieldElement.inject()
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    Field field = this.field;
    Object value;
    
    // 1. 构建DependencyDescriptor
    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    
    // 2. 解析依赖
    value = beanFactory.resolveDependency(desc, beanName);
    
    // 3. 反射设置值
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}
4.2 方法注入
复制代码
// AutowiredMethodElement.inject()
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    Method method = this.method;
    Object[] arguments;
    
    // 1. 为每个参数构建DependencyDescriptor
    DependencyDescriptor[] descriptors = new DependencyDescriptor[paramCount];
    for (int i = 0; i < paramCount; i++) {
        MethodParameter methodParam = new MethodParameter(method, i);
        descriptors[i] = new DependencyDescriptor(methodParam, this.required);
    }
    
    // 2. 解析所有依赖
    arguments = beanFactory.resolveDependencies(descriptors, beanName);
    
    // 3. 反射调用方法
    ReflectionUtils.makeAccessible(method);
    method.invoke(bean, arguments);
}

五、依赖解析:resolveDependency()的深度剖析

resolveDependency流程图如下所示:

1. resolveDependency方法签名

复制代码
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, 
                        @Nullable String requestingBeanName,
                        @Nullable Set<String> autowiredBeanNames,
                        @Nullable TypeConverter typeConverter) throws BeansException;

2. 核心解析流程

复制代码
// DefaultListableBeanFactory.resolveDependency()
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    
    // 1. 解析注解值(如@Value("${property}"))
    Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
    if (value != null) {
        return evaluateBeanDefinitionString((String) value, descriptor.getDependencyName());
    }
    
    // 2. 处理集合/数组类型
    Class<?> type = descriptor.getDependencyType();
    if (type.isArray() || Collection.class.isAssignableFrom(type) || 
        Map.class.isAssignableFrom(type)) {
        return resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    }
    
    // 3. 查找匹配的Bean
    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    
    // 4. 如果没找到,检查required属性
    if (matchingBeans.isEmpty()) {
        if (descriptor.isRequired()) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
        }
        return null;
    }
    
    // 5. 如果找到多个,需要确定唯一的一个
    String autowiredBeanName;
    Object instanceCandidate;
    if (matchingBeans.size() > 1) {
        autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
        instanceCandidate = matchingBeans.get(autowiredBeanName);
    } else {
        Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
        autowiredBeanName = entry.getKey();
        instanceCandidate = entry.getValue();
    }
    
    // 6. 添加到已自动注入的Bean名称集合
    if (autowiredBeanNames != null) {
        autowiredBeanNames.add(autowiredBeanName);
    }
    
    return instanceCandidate;
}

3. findAutowireCandidates()实现

流程图

复制代码
protected Map<String, Object> findAutowireCandidates(
        String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    
    // 1. 按类型查找所有候选Bean名称
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        this, requiredType, true, descriptor.isEager());
    
    Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    
    // 2. 从resolvableDependencies中查找
    for (Map.Entry<Class<?>, Object> entry : this.resolvableDependencies.entrySet()) {
        if (entry.getKey().isAssignableFrom(requiredType)) {
            result.put(null, entry.getValue());
        }
    }
    
    // 3. 遍历候选Bean名称
    for (String candidateName : candidateNames) {
        // 3.1 检查autowireCandidate属性
        if (!isAutowireCandidate(candidateName, descriptor)) {
            continue;
        }
        
        // 3.2 检查@Qualifier注解
        if (descriptor.getQualifier() != null) {
            if (!checkQualifiers(candidateName, descriptor.getQualifier())) {
                continue;
            }
        }
        
        // 3.3 添加到结果集
        result.put(candidateName, getBean(candidateName));
    }
    
    return result;
}

4. 泛型依赖注入

Java的Type体系:

  • Class:普通类型

  • ParameterizedType:泛型类型(如List<String>)

  • GenericArrayType:泛型数组(如T[])

  • TypeVariable:类型变量(如T、K)

  • WildcardType:通配符类型(如? extends Number)

4.1 泛型注入示例
复制代码
// 泛型父类
public class BaseService<O, S> {
    @Autowired
    protected O o;  // 泛型字段
    
    @Autowired  
    protected S s;
}

// 具体实现
@Component
public class UserService extends BaseService<OrderService, StockService> {
    public void test() {
        System.out.println(o);  // o的实际类型是OrderService
    }
}
4.2 Spring的泛型解析
复制代码
// 获取泛型具体类型
Class<?> userServiceClass = UserService.class;
Type genericSuperclass = userServiceClass.getGenericSuperclass();  
// 得到:BaseService<OrderService, StockService>

// 获取父类的泛型变量
TypeVariable<?>[] typeParameters = userServiceClass.getSuperclass().getTypeParameters();
// [O, S]

// 获取实际泛型参数
if (genericSuperclass instanceof ParameterizedType) {
    Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
    // [OrderService.class, StockService.class]
}

Type类型测试代码

复制代码
public class TypeTest<T> {
    private int i;                    // 基本类型
    private Integer it;               // 普通Class
    private List<String> slist;       // ParameterizedType
    private T t;                      // TypeVariable
    private T[] tarray;               // GenericArrayType
    
    public static void test(Field field) {
        System.out.println(field.getName() + "的类型:");
        System.out.println("是基本类型:" + field.getType().isPrimitive());
        System.out.println("是泛型类型:" + (field.getGenericType() instanceof ParameterizedType));
        System.out.println("是泛型变量:" + (field.getGenericType() instanceof TypeVariable));
        System.out.println("是泛型数组:" + (field.getGenericType() instanceof GenericArrayType));
    }
}

5. @Qualifier的使用:解决多实现问题

5.1 自定义Qualifier注解
复制代码
// 随机策略注解
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("random")
public @interface Random {
}

// 轮询策略注解  
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("roundRobin")
public @interface RoundRobin {
}
5.2 策略实现
复制代码
// 策略接口
public interface LoadBalance {
    String select();
}

// 随机策略
@Component
@Random
public class RandomStrategy implements LoadBalance {
    @Override
    public String select() {
        return "随机选择";
    }
}

// 轮询策略
@Component
@RoundRobin
public class RoundRobinStrategy implements LoadBalance {
    @Override
    public String select() {
        return "轮询选择";
    }
}
5.3 使用@Qualifier指定实现
复制代码
@Component
public class UserService {
    @Autowired
    @RoundRobin  // 明确指定使用轮询策略
    private LoadBalance loadBalance;
    
    public void test() {
        System.out.println(loadBalance.select());  // 输出:轮询选择
    }
}

六、@Resource注解:JSR-250标准注入

1. @Resource vs @Autowired

特性 @Autowired @Resource
标准 Spring专属 JSR-250标准
来源 Spring框架 Java EE/Jakarta EE
查找顺序 先byType,再byName 先byName,再byType
required 支持 不支持
泛型支持 支持 支持

2. @Resource的查找顺序

复制代码
@Component
public class UserService {
    @Resource(name = "orderService")  // 1. 按指定name查找
    private OrderService orderService;
    
    @Resource  // 2. 按字段名查找,再按类型
    private OrderService orderService;
}

@Resource工作流程图

3. @Resource的源码实现

复制代码
// CommonAnnotationBeanPostProcessor处理@Resource
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
        implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        // 查找@Resource注解的注入点
        InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
        
        // 执行注入
        metadata.inject(bean, beanName, pvs);
        return pvs;
    }
    
    protected void injectResource(Object target, String beanName, PropertyValues pvs) throws Throwable {
        // 获取@Resource注解
        Resource resource = field.getAnnotation(Resource.class);
        
        // 1. 如果指定了name,按name查找
        if (resource.name() != null && !resource.name().isEmpty()) {
            Object value = beanFactory.getBean(resource.name());
            field.set(target, value);
            return;
        }
        
        // 2. 按字段名查找
        String defaultName = field.getName();
        if (beanFactory.containsBean(defaultName)) {
            Object value = beanFactory.getBean(defaultName);
            field.set(target, value);
            return;
        }
        
        // 3. 按类型查找
        Class<?> type = field.getType();
        Object value = beanFactory.getBean(type);
        field.set(target, value);
    }
}

七、依赖注入的性能优化与缓存

1. 注入点缓存

Spring会对注入点进行缓存,避免重复解析:

复制代码
// AutowiredAnnotationBeanPostProcessor中的缓存
private final ConcurrentMap<Class<?>, InjectionMetadata> injectionMetadataCache = 
    new ConcurrentHashMap<>(256);

protected InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz) {
    // 先查缓存
    InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
    if (metadata == null) {
        // 缓存未命中,解析并缓存
        metadata = buildAutowiringMetadata(clazz);
        this.injectionMetadataCache.put(clazz, metadata);
    }
    return metadata;
}

2. 依赖解析缓存

对于原型Bean,Spring会缓存依赖解析结果:

复制代码
// 依赖描述符和结果beanName的缓存
private final Map<DependencyDescriptor, String> resolvedBeanNamesCache = 
    new ConcurrentHashMap<>(256);

protected String resolveBeanName(DependencyDescriptor descriptor) {
    // 先查缓存
    String beanName = this.resolvedBeanNamesCache.get(descriptor);
    if (beanName == null) {
        // 解析并缓存
        beanName = doResolveBeanName(descriptor);
        this.resolvedBeanNamesCache.put(descriptor, beanName);
    }
    return beanName;
}

八、最佳实践与常见问题

1. 注入方式选择建议

场景 推荐方式 理由
必选依赖 构造器注入 保证依赖不为null,利于不可变对象
可选依赖 Setter注入 灵活性高,可重新注入
框架扩展 字段注入 代码简洁,适合框架类
多实现选择 @Qualifier 明确指定具体实现

2. 解决循环依赖

复制代码
@Component
public class ServiceA {
    @Autowired
    @Lazy  // 延迟注入,打破循环
    private ServiceB serviceB;
}

@Component
public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

3. 常见问题排查

Q1: @Autowired注入失败

排查步骤

  1. 检查Bean是否被Spring管理(@Component等注解)

  2. 检查注入点类型是否正确

  3. 检查是否有多个同类型Bean未指定@Qualifier

  4. 检查required属性(默认为true)

Q2: 注入null值

可能原因

  1. Bean未定义或未扫描到

  2. 作用域不匹配(如request作用域在非Web环境)

  3. 条件注解@Conditional未满足条件

Q3: 原型Bean注入单例Bean
复制代码
@Component
@Scope("prototype")
public class PrototypeBean {
    @Autowired
    private SingletonBean singletonBean;  // 正确:原型依赖单例
    
    @Autowired
    @Lazy  // 需要@Lazy,否则会注入相同的原型实例
    private PrototypeBean anotherPrototypeBean;
}

九、总结:Spring依赖注入的设计哲学

1. 设计原则

  • 开闭原则:通过BeanPostProcessor扩展点支持新注解

  • 单一职责:每个注入处理器职责明确

  • 依赖倒置:依赖抽象而非具体实现

2. 核心机制

  1. 两级缓存:注入点缓存和依赖解析缓存

  2. 双重检查:类型检查 + 名称检查

  3. 递归处理:支持继承链上的注入点查找

  4. 泛型感知:完整的泛型类型支持

3. 扩展能力

  • 自定义注解:通过实现BeanPostProcessor支持新注解

  • 条件注入:结合@Conditional实现条件化注入

  • 动态代理:支持AOP代理对象的注入

4. 性能考虑

  • 懒加载:@Lazy注解延迟注入

  • 缓存优化:多级缓存减少重复计算

  • 短路判断:快速失败机制

相关推荐
Victor3563 小时前
Hibernate(26)什么是Hibernate的透明持久化?
后端
盖世英雄酱581363 小时前
不是所有的this调用会导致事务失效
java·后端
Victor3564 小时前
Hibernate(25)Hibernate的批量操作是什么?
后端
少许极端4 小时前
Redis入门指南(五):从零到分布式缓存-其他类型及Java客户端操作redis
java·redis·分布式·缓存
Thetimezipsby4 小时前
Go(GoLang)语言基础、知识速查
开发语言·后端·golang
为自己_带盐4 小时前
从零开始玩转 Microsoft Agent Framework:我的 MAF 实践之旅-第二篇
后端·microsoft·ai·.net
宠..5 小时前
优化文件结构
java·服务器·开发语言·前端·c++·qt
sheji34165 小时前
【开题答辩全过程】以 疫情物资捐赠系统为例,包含答辩的问题和答案
java
sinat_255487815 小时前
InputStream/OutputStream小讲堂
java·数据结构·算法
乌日尼乐5 小时前
【Java基础整理】java数组详解
java·后端