一、问题引入:为什么需要推断构造方法?
在Spring框架中,当需要创建一个Bean实例时,必须调用该类的某个构造方法。但一个类可能有多个构造方法,Spring如何决定使用哪一个呢?
// 多个构造方法的类示例
@Component
public class UserService {
// 构造方法1:无参
public UserService() {
System.out.println("无参构造方法");
}
// 构造方法2:单参数
public UserService(OrderService orderService) {
System.out.println("单参数构造方法");
}
// 构造方法3:双参数
public UserService(OrderService orderService, UserRepository userRepository) {
System.out.println("双参数构造方法");
}
}
核心问题:当Spring创建UserService时,应该使用哪个构造方法?
二、推断构造方法的基本规则
2.1 简单情况:只有一个构造方法
情况1:只有一个无参构造方法
@Component
public class UserService {
public UserService() {
// 只能使用这个构造方法
}
}
情况2:只有一个有参构造方法
@Component
public class UserService {
// 只有一个有参构造方法
public UserService(OrderService orderService) {
// ...
}
}
关键点:
-
使用
AnnotationConfigApplicationContext:Spring会根据构造方法参数类型查找Bean并传入 -
使用
ClassPathXmlApplicationContext:-
可以在XML中手动指定构造方法参数值
-
或配置
autowire="constructor"让Spring自动寻找
-
2.2 复杂情况:多个构造方法
当类中存在多个构造方法时,Spring的选择逻辑如下:

流程图如下所示:

三、开发者指定构造方法的方式
3.1 通过XML配置指定
<bean id="userService" class="com.example.UserService">
<!-- 指定构造方法参数,从而确定使用哪个构造方法 -->
<constructor-arg index="0" ref="orderService"/>
<constructor-arg index="1" ref="userRepository"/>
</bean>
3.2 通过@Autowired注解指定
@Component
public class UserService {
// 无参构造方法
public UserService() {
System.out.println("无参构造");
}
// 使用@Autowired注解指定使用这个构造方法
@Autowired
public UserService(OrderService orderService) {
System.out.println("被@Autowired指定的构造方法");
}
}
重要规则:
-
只能有一个构造方法标注
@Autowired或@Autowired(required=true) -
可以有多个构造方法标注
@Autowired(required=false),此时Spring需要自动选择一个
3.3 @Autowired(required=false)的特殊情况
@Component
public class UserService {
@Autowired(required = false)
public UserService() {
System.out.println("可选的无参构造");
}
@Autowired(required = false)
public UserService(OrderService orderService) {
System.out.println("可选的有参构造");
}
}
这种情况下,Spring需要从这些可选的构造方法中自动选择一个。
四、源码深度解析:推断构造方法的完整流程
4.1 核心方法:createBeanInstance()
// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd,
@Nullable Object[] args) {
// 1. 获取Class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 2. 如果存在Supplier,直接调用
if (mbd.getSupplier() != null) {
return obtainFromSupplier(mbd.getSupplier(), beanName);
}
// 3. 如果存在工厂方法
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 4. 是否已经推断过构造方法
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null && mbd.constructorArgumentsResolved) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 5. 如果已经推断过,直接使用
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
return instantiateBean(beanName, mbd);
}
}
// 6. 调用SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 7. 根据情况选择构造方法
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 8. 使用无参构造方法
return instantiateBean(beanName, mbd);
}
4.2 关键方法:determineConstructorsFromBeanPostProcessors()
这个方法会调用所有SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法。
// AutowiredAnnotationBeanPostProcessor是关键的处理器
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeanCreationException {
// 1. 检查是否有@Lookup注解的方法
if (!this.lookupMethodsChecked.contains(beanName)) {
// 处理@Lookup注解
}
// 2. 检查是否有@Autowired注解的构造方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanClass, null);
Collection<InjectionMetadata.InjectedElement> elements = metadata.getInjectedElements();
// 3. 过滤出构造方法
List<Constructor<?>> candidates = new ArrayList<>();
for (InjectionMetadata.InjectedElement element : elements) {
if (element instanceof AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement) {
Method method = ((AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement) element).getMethod();
if (method.getName().equals("<init>")) { // 构造方法
candidates.add((Constructor<?>) method);
}
}
}
// 4. 处理@Autowired(required=false)的情况
if (candidates.isEmpty()) {
return null; // 让Spring自动选择
}
return candidates.toArray(new Constructor<?>[0]);
}
思维导图参考:

4.3 核心算法:autowireConstructor()
当Spring需要自动选择构造方法时,会调用autowireConstructor()方法:
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
// 1. 检查是否已经有缓存的构造方法
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
// 2. 如果调用getBean时指定了参数,使用这些参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
} else {
// 尝试从缓存中获取
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, argsToResolve,
constructorToUse);
}
}
// 3. 如果没有确定的构造方法,开始推断
if (constructorToUse == null || argsToUse == null) {
// 3.1 获取所有候选构造方法
Constructor<?>[] candidates = ctors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
candidates = beanClass.getDeclaredConstructors();
}
// 3.2 如果只有一个无参构造方法,直接使用
if (candidates.length == 1 && explicitArgs == null &&
!mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// 3.3 需要自动装配的情况
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
// 3.4 确定最小参数个数
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
} else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 3.5 对构造方法排序(参数多的在前)
AutowireUtils.sortConstructors(candidates);
// 3.6 遍历所有构造方法
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();
// 如果参数个数小于最小要求,跳过
if (paramTypes.length < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
// 3.7 解析参数
if (resolvedValues != null) {
try {
// 获取参数名称(可能通过字节码获取)
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 创建参数持有器
argsHolder = createArgumentArray(beanName, mbd, resolvedValues,
bw, paramTypes, paramNames,
candidate, autowiring);
} catch (UnsatisfiedDependencyException ex) {
// 依赖不满足,继续尝试下一个构造方法
continue;
}
} else {
// 如果参数个数不匹配,继续尝试
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 3.8 计算匹配分数
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) :
argsHolder.getAssignabilityWeight(paramTypes));
// 选择分数最低(最匹配)的构造方法
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
} else if (constructorToUse != null &&
typeDiffWeight == minTypeDiffWeight) {
// 分数相同,记录歧义
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
// 3.9 处理歧义情况
if (constructorToUse == null) {
throw new BeanCreationException(...);
} else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(...);
}
}
// 4. 使用选择的构造方法实例化Bean
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = argsToUse;
}
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
4.4 匹配分数计算机制
Spring使用MethodInvoker.getTypeDifferenceWeight()方法计算匹配分数:
// 测试匹配分数计算
public class TypeMatchTest {
static class A {}
static class B extends A {}
static class C extends B {}
interface D {}
static class E extends A implements D {}
public static void main(String[] args) {
Object[] objects = new Object[]{new E()};
// 完全匹配:0分
System.out.println(MethodInvoker.getTypeDifferenceWeight(
new Class[]{E.class}, objects)); // 0
// 父类匹配:2分
System.out.println(MethodInvoker.getTypeDifferenceWeight(
new Class[]{A.class}, objects)); // 2
// 接口匹配:1分
System.out.println(MethodInvoker.getTypeDifferenceWeight(
new Class[]{D.class}, objects)); // 1
// 更远的父类:4分
System.out.println(MethodInvoker.getTypeDifferenceWeight(
new Class[]{Object.class}, objects)); // 4
}
}
匹配规则:
-
完全匹配:0分(最优先)
-
接口匹配:1分
-
直接父类匹配:2分
-
间接父类匹配:每多一级+2分
为什么分数越低优先级越高?
分数代表类型转换的成本,分数越低表示类型越匹配,转换成本越小。
五、@Bean方法重载的特殊处理
5.1 @Bean方法的基本解析
5.1.1 静态@Bean方法
@Configuration
public class AppConfig {
@Bean
public static UserService userService() {
return new UserService();
}
}
生成的BeanDefinition属性:
-
factoryBeanName:"appConfig"(AppConfig的beanName) -
factoryMethodName:"userService" -
factoryClass:AppConfig.class
5.1.2 非静态@Bean方法
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
生成的BeanDefinition属性:
-
factoryBeanName:null -
factoryMethodName:"userService" -
factoryClass:AppConfig.class
5.2 @Bean方法重载的情况
@Configuration
public class AppConfig {
@Bean
public static UserService userService() {
return new UserService();
}
@Bean
public UserService userService(OrderService orderService) {
return new UserService(orderService);
}
}
处理流程:
-
Spring解析第一个
@Bean方法,生成BeanDefinition,isFactoryMethodUnique = true -
解析第二个
@Bean方法,发现beanDefinitionMap中已存在userService的BeanDefinition -
将已存在的BeanDefinition的
isFactoryMethodUnique改为false -
不会生成新的BeanDefinition
5.3 工厂方法推断的逻辑
当isFactoryMethodUnique = false时,Spring需要从多个方法中选择一个:
// SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName,
BeanFactory owner) {
// 如果isFactoryMethodUnique为true,直接使用缓存的方法
if (bd.getResolvedFactoryMethod() != null) {
return instantiateUsingFactoryMethod(bd, beanName, owner,
bd.getResolvedFactoryMethod(), null);
}
// 否则需要推断工厂方法
return instantiateUsingFactoryMethod(bd, beanName, owner, null, null);
}
// ConstructorResolver.java
public BeanWrapper instantiateUsingFactoryMethod(...) {
// 1. 获取所有候选方法
Method[] candidates = getCandidateMethods(factoryClass, mbd);
// 2. 过滤出合适的方法
List<Method> candidateList = new ArrayList<>();
for (Method candidate : candidates) {
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
mbd.isFactoryMethod(candidate)) {
candidateList.add(candidate);
}
}
// 3. 如果只有一个候选方法,直接使用
if (candidateList.size() == 1) {
Method uniqueCandidate = candidateList.get(0);
// 缓存结果
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
// 执行方法创建Bean
return executeFactoryMethod(uniqueCandidate, ...);
}
// 4. 多个候选方法,需要推断(逻辑类似构造方法推断)
// 排序、匹配分数计算、选择最佳方法
// ...
}
六、实战案例与最佳实践
6.1 案例1:强制使用指定构造方法
@Component
public class PaymentService {
private PaymentGateway gateway;
private PaymentValidator validator;
// 默认构造方法
public PaymentService() {
this.gateway = new DefaultPaymentGateway();
this.validator = new BasicValidator();
}
// 指定使用这个构造方法
@Autowired
public PaymentService(PaymentGateway gateway, PaymentValidator validator) {
this.gateway = gateway;
this.validator = validator;
}
}
6.2 案例2:可选构造方法与条件注入
@Component
@ConditionalOnClass(name = "com.example.AdvancedFeature")
public class FeatureService {
private AdvancedFeature feature;
// 如果有AdvancedFeature,使用这个构造方法
@Autowired(required = false)
public FeatureService(AdvancedFeature feature) {
this.feature = feature;
}
// 否则使用这个构造方法
@Autowired(required = false)
public FeatureService() {
this.feature = null;
}
}
6.3 案例3:多实现的选择
@Component
public class NotificationService {
private final NotificationSender sender;
// Spring会根据匹配分数选择最合适的构造方法
public NotificationService(EmailSender emailSender) {
this.sender = emailSender; // 如果EmailSender可用
}
public NotificationService(SmsSender smsSender) {
this.sender = smsSender; // 如果SmsSender可用
}
public NotificationService(NotificationSender sender) {
this.sender = sender; // 通用实现
}
}
6.4 最佳实践
-
优先使用构造器注入
@Component public class UserService { private final UserRepository repository; @Autowired public UserService(UserRepository repository) { this.repository = repository; } } -
避免歧义构造方法
// 不推荐:两个构造方法参数类型相同 public UserService(UserRepository repository) { ... } public UserService(OrderRepository repository) { ... } // 容易歧义 // 推荐:使用@Qualifier消除歧义 public UserService(@Qualifier("userRepo") UserRepository repository) { ... } public UserService(@Qualifier("orderRepo") OrderRepository repository) { ... } -
合理使用@Autowired(required=false)
@Component public class FlexibleService { @Autowired(required = false) public FlexibleService(OptionalDependency dep) { // 可选依赖 } public FlexibleService() { // 默认实现 } }
七、常见问题与解决方案
Q1:Spring为什么不能解决构造器的循环依赖?
原因:
-
时机问题:构造器调用发生在实例化阶段,此时Bean还未完全创建
-
缓存未就绪:三级缓存在实例化之后才添加
-
无法获取引用:构造器需要完整对象,无法使用早期引用
解决方案:
-
使用setter注入替代构造器注入
-
使用
@Lazy注解延迟注入
Q2:多个@Autowired构造方法导致冲突怎么办?
@Component
public class ConflictService {
@Autowired // 冲突:多个required=true的@Autowired
public ConflictService(DepA a) { ... }
@Autowired // 冲突!
public ConflictService(DepB b) { ... }
}
解决:
-
只保留一个
@Autowired(或@Autowired(required=true)) -
其他使用
@Autowired(required=false)
Q3:如何调试构造方法推断过程?
// 1. 在AbstractAutowireCapableBeanFactory.createBeanInstance()设置断点
// 2. 在ConstructorResolver.autowireConstructor()设置断点
// 3. 观察candidates数组和匹配分数计算
// 添加调试日志
@Component
public class DebugService {
public DebugService() {
System.out.println("无参构造被调用");
}
@Autowired
public DebugService(OtherService service) {
System.out.println("有参构造被调用");
}
}
Q4:@Bean方法重载时的选择策略?
当有多个@Bean方法重载时,Spring的选择策略:
-
参数匹配:优先匹配参数能够完全满足的方法
-
匹配分数:类似构造方法,计算类型匹配分数
-
默认选择:无参方法作为备选
八、性能优化与注意事项
8.1 性能考虑
-
缓存机制:Spring会缓存推断结果,避免重复计算
-
参数解析:参数名称发现(通过字节码)可能影响性能
-
排序开销:构造方法排序在Bean首次创建时执行
8.2 内存优化
// 避免过多构造方法
@Component
public class OptimizedService {
// 保持构造方法数量合理(建议不超过3个)
// 过多的构造方法会增加推断开销
}
8.3 并发安全
-
构造方法推断过程是线程安全的
-
推断结果会被缓存,后续请求直接使用缓存
-
使用双重检查锁确保单例Bean的正确创建
九、源码学习建议
9.1 关键类与位置
-
AbstractAutowireCapableBeanFactory :
createBeanInstance()方法 -
ConstructorResolver :
autowireConstructor()方法 -
AutowiredAnnotationBeanPostProcessor :
determineCandidateConstructors()方法 -
SimpleInstantiationStrategy:工厂方法实例化逻辑
9.2 调试技巧
-
条件断点:在关键方法设置条件断点
// 只对特定Bean名中断 "userService".equals(beanName) -
观察变量:
-
candidates:候选构造方法数组 -
minTypeDiffWeight:最小匹配分数 -
constructorToUse:最终选择的构造方法
-
-
日志输出:开启Spring调试日志
properties
logging.level.org.springframework.beans.factory.support=DEBUG
9.3 学习路径
-
理解基本规则:单构造方法、多构造方法的选择
-
掌握注解使用:@Autowired、@Qualifier的正确使用
-
深入源码:跟踪autowireConstructor()的执行流程
-
实践验证:编写测试代码验证各种场景
十、总结
Spring的构造方法推断机制是其依赖注入功能的核心组成部分,通过精心设计的算法实现了:
-
灵活性:支持多种构造方法选择方式
-
智能性:自动选择最匹配的构造方法
-
扩展性:通过BeanPostProcessor支持自定义推断逻辑
-
性能优化:缓存机制减少重复计算
关键要点回顾:
-
单构造方法:直接使用该构造方法
-
多构造方法:开发者指定或Spring自动选择
-
@Autowired:明确指定使用的构造方法
-
匹配分数:类型越匹配分数越低,优先级越高
-
@Bean重载:类似构造方法推断的逻辑
最佳实践总结:
-
优先使用构造器注入,保证依赖不可变
-
避免构造方法歧义,使用@Qualifier明确指定
-
合理使用@Autowired(required=false)实现条件注入
-
保持构造方法数量合理,避免过度复杂