一、依赖注入全景图: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
-
创建userService1时,static orderService被注入值A
-
创建userService2时,static orderService被注入值B(覆盖A)
-
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注入失败
排查步骤:
-
检查Bean是否被Spring管理(@Component等注解)
-
检查注入点类型是否正确
-
检查是否有多个同类型Bean未指定@Qualifier
-
检查required属性(默认为true)
Q2: 注入null值
可能原因:
-
Bean未定义或未扫描到
-
作用域不匹配(如request作用域在非Web环境)
-
条件注解@Conditional未满足条件
Q3: 原型Bean注入单例Bean
@Component
@Scope("prototype")
public class PrototypeBean {
@Autowired
private SingletonBean singletonBean; // 正确:原型依赖单例
@Autowired
@Lazy // 需要@Lazy,否则会注入相同的原型实例
private PrototypeBean anotherPrototypeBean;
}
九、总结:Spring依赖注入的设计哲学
1. 设计原则
-
开闭原则:通过BeanPostProcessor扩展点支持新注解
-
单一职责:每个注入处理器职责明确
-
依赖倒置:依赖抽象而非具体实现
2. 核心机制
-
两级缓存:注入点缓存和依赖解析缓存
-
双重检查:类型检查 + 名称检查
-
递归处理:支持继承链上的注入点查找
-
泛型感知:完整的泛型类型支持
3. 扩展能力
-
自定义注解:通过实现BeanPostProcessor支持新注解
-
条件注入:结合@Conditional实现条件化注入
-
动态代理:支持AOP代理对象的注入
4. 性能考虑
-
懒加载:@Lazy注解延迟注入
-
缓存优化:多级缓存减少重复计算
-
短路判断:快速失败机制