Appearance
createBeanInstance源码解析
一、createBeanInstance
的核心作用
createBeanInstance
的主要职责是:根据RootBeanDefinition
(合并后的bean定义),选择合适的实例化策略(工厂方法、构造函数注入、默认构造函数),创建bean的原始实例。
它的输入是:
beanName
:bean的名称;mbd
:合并后的RootBeanDefinition
(包含bean的类信息、工厂方法、构造函数参数等);args
:显式传入的构造函数/工厂方法参数(如getBean("beanName", args)
中的args
)。
输出是:bean的原始实例(未进行依赖注入和初始化)。
二、createBeanInstance
的源码流程剖析
我们直接看AbstractAutowireCapableBeanFactory
中的createBeanInstance
方法源码(Spring 5.3.x版本),并分步骤解析:
java
protected Object createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1. 解析bean的Class对象(从mbd中加载,若未解析则用ClassLoader加载)
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 2. 处理InstanceSupplier(Spring 5.0+新增,优先用供应商提供实例)
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return instanceSupplier.get();
}
// 3. 处理工厂方法(若有factoryMethodName,用工厂方法实例化)
if (mbd.hasFactoryMethod()) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 4. 处理构造函数注入(无工厂方法时进入)
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 4.1 检查缓存的构造函数(避免重复解析)
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 4.2 使用缓存的构造函数:若需要自动装配,调用autowireConstructor;否则用默认构造函数
return autowireNecessary ? autowireConstructor(beanName, mbd, null, null) : instantiateBean(beanName, mbd);
}
// 4.3 调用BeanPostProcessor获取候选构造函数(如@Autowired标注的构造函数)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 4.4 有候选构造函数/需要构造函数自动装配/有参数,调用autowireConstructor
return autowireConstructor(beanName, mbd, ctors, args);
}
// 5. 无任何特殊配置,用默认无参构造函数实例化
return instantiateBean(beanName, mbd);
}
步骤1:解析bean的Class对象
resolveBeanClass
方法从mbd
中获取bean的Class
对象(若mbd
的beanClass
是字符串,会用BeanFactory
的ClassLoader
加载)。同时检查类的访问权限:若类不是public
且未设置nonPublicAccessAllowed
(允许非公共类实例化),则抛出异常。
步骤2:处理InstanceSupplier
(优先度最高)
InstanceSupplier
是Spring 5.0引入的函数式实例供应商,用于直接提供bean实例。例如:
- 使用
@Bean(supplier = MyBean::new)
标注的方法; - 通过
BeanDefinition.setInstanceSupplier(() -> new MyBean())
设置。
若instanceSupplier
不为空,直接调用get()
方法获取实例,跳过后续所有步骤。这是最灵活的实例化方式,常用于动态创建bean。
步骤3:处理工厂方法(factoryMethod
)
若mbd
的factoryMethodName
不为空(即配置了factory-method
),则调用instantiateUsingFactoryMethod
方法,通过工厂方法实例化bean。
工厂方法分为两类:
- 静态工厂:工厂方法是静态的(如
MyFactory.createBean()
),无需工厂bean实例; - 实例工厂:工厂方法是实例方法(如
myFactory.createBean()
),需要先实例化工厂bean(factory-bean
配置)。
instantiateUsingFactoryMethod
的核心逻辑(由ConstructorResolver
实现):
- 解析工厂bean名称(
factoryBeanName
)和工厂方法名称(factoryMethodName
); - 若为实例工厂,先获取工厂bean实例(通过
getBean(factoryBeanName)
); - 解析工厂方法的参数(优先用
args
,否则用mbd
的constructorArgumentValues
); - 查找匹配的工厂方法(根据方法名称和参数类型);
- 调用工厂方法(静态方法用
Class.invoke
,实例方法用工厂bean实例invoke
)。
例子:
xml
<!-- 静态工厂 -->
<bean id="myBean" class="com.example.MyFactory" factory-method="createStaticBean"/>
<!-- 实例工厂 -->
<bean id="myFactory" class="com.example.MyFactory"/>
<bean id="myBean" factory-bean="myFactory" factory-method="createInstanceBean"/>
步骤4:处理构造函数注入(核心逻辑)
若没有工厂方法,进入构造函数注入流程。这是最常见的实例化方式(如@Autowired
标注的构造函数)。
子步骤4.1:检查缓存的构造函数
mbd
中的resolvedConstructorOrFactoryMethod
缓存了之前解析过的构造函数(或工厂方法),constructorArgumentsResolved
标记参数是否已解析。若有缓存,直接使用缓存的构造函数,避免重复解析。
子步骤4.2:获取候选构造函数(BeanPostProcessor
扩展点)
determineConstructorsFromBeanPostProcessors
方法调用**InstantiationAwareBeanPostProcessor
**的postProcessCandidateConstructors
方法,获取候选构造函数。例如:
AutowiredAnnotationBeanPostProcessor
:扫描@Autowired
或@Value
标注的构造函数;CommonAnnotationBeanPostProcessor
:扫描@Resource
标注的构造函数(较少用)。
例子:
java
@Component
public class MyBean {
private final AnotherBean anotherBean;
// @Autowired标注的构造函数会被作为候选
@Autowired
public MyBean(AnotherBean anotherBean) {
this.anotherBean = anotherBean;
}
}
子步骤4.3:选择并调用构造函数
若有候选构造函数(ctors != null
)、需要构造函数自动装配(mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
)、有构造函数参数值(mbd.hasConstructorArgumentValues()
)或显式传入args
,则调用autowireConstructor
方法:
- 选择最合适的构造函数:根据候选构造函数、参数数量/类型匹配,选择最优构造函数(如参数数量最多的、
@Autowired(required=true)
的); - 解析构造函数参数:参数值来源包括:
- 显式传入的
args
(getBean
时的参数); mbd
的constructorArgumentValues
(XML配置的<constructor-arg>
);- 自动装配(根据参数类型从
BeanFactory
中查找bean); @Value
注解解析(从配置文件或环境变量中获取值);
- 显式传入的
- 调用构造函数:用
Constructor.newInstance(args)
实例化bean。
步骤5:默认无参构造函数实例化
若以上步骤均不满足(无工厂方法、无候选构造函数、无参数),则调用instantiateBean
方法,使用默认无参构造函数实例化bean。
instantiateBean
的核心逻辑:
- 使用
BeanUtils.instantiateClass(beanClass)
(反射调用无参构造函数); - 若需要CGLIB代理(如
@Configuration
的bean、scope=prototype
且有AOP拦截),则用CGLIB
生成子类实例(SimpleInstantiationStrategy
的instantiateWithCglib
方法)。
三、关键扩展点与机制
1. InstantiationAwareBeanPostProcessor
(实例化前扩展)
InstantiationAwareBeanPostProcessor
是影响实例化的核心扩展接口,其postProcessBeforeInstantiation
方法在createBeanInstance
之前调用,若返回非null
值,则跳过后续实例化步骤,直接使用该返回值作为bean实例。例如:
- AOP的
AnnotationAwareAspectJAutoProxyCreator
:在实例化前检查是否需要代理,若需要则返回代理对象; - 自定义
InstantiationAwareBeanPostProcessor
:用于动态生成bean实例(如代理、 mock)。
例子:
java
@Component
public class MyInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass == MyBean.class) {
// 返回代理对象,跳过后续实例化
return Proxy.newProxyInstance(beanClass.getClassLoader(), new Class[]{MyBean.class}, (proxy, method, args) -> {
System.out.println("Before method: " + method.getName());
return method.invoke(new MyBean(), args);
});
}
return null;
}
}
2. 实例化策略(InstantiationStrategy
)
InstantiationStrategy
是实例化的策略接口,默认实现是SimpleInstantiationStrategy
,支持两种实例化方式:
- 反射实例化:用于无参构造函数或构造函数注入(
BeanUtils.instantiateClass
); - CGLIB实例化:用于需要代理的bean(如
@Configuration
的bean),通过CGLIB
生成子类,添加无参构造函数(若原类没有),并设置方法拦截器。
@Configuration
的bean为什么需要CGLIB?@Configuration
的bean会被CGLIB代理,目的是防止@Bean
方法重复实例化。例如:
java
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return new MyBean(anotherBean()); // 若没有CGLIB代理,anotherBean()会调用普通方法,重复实例化
}
@Bean
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
CGLIB代理会将anotherBean()
方法拦截,改为从BeanFactory
中获取已实例化的AnotherBean
,避免重复创建。
3. 构造函数选择逻辑
当有多个候选构造函数时,Spring会按以下优先级选择:
@Autowired(required=true)
标注的构造函数:必须存在且参数可解析;- 参数数量最多的构造函数:优先匹配参数数量多的构造函数;
- 参数类型匹配的构造函数:根据参数类型从
BeanFactory
中查找匹配的bean。
例子:
java
@Component
public class MyBean {
// 候选构造函数1:参数数量2
@Autowired
public MyBean(AnotherBean anotherBean, String message) { ... }
// 候选构造函数2:参数数量1
@Autowired(required=false)
public MyBean(AnotherBean anotherBean) { ... }
// 候选构造函数3:无参(默认)
public MyBean() { ... }
}
若AnotherBean
和message
(@Value
解析)均存在,Spring会选择构造函数1;若message
不存在,会选择构造函数2(required=false
);若均不存在,选择构造函数3。
四、常见问题与解决方案
1. NoSuchMethodException
(无此方法异常)
原因:构造函数/工厂方法的参数数量或类型与mbd
中的配置不匹配。
解决方案:
- 检查
mbd
的constructorArgumentValues
或factoryMethodArguments
是否正确; - 检查显式传入的
args
是否与构造函数/工厂方法的参数匹配; - 确保
@Autowired
标注的构造函数参数可解析(如AnotherBean
已被实例化)。
2. BeanCreationException
(bean创建异常):无默认构造函数
原因:bean类没有无参构造函数,且未配置构造函数注入或工厂方法。
解决方案:
- 添加无参构造函数(若允许);
- 配置构造函数注入(如
@Autowired
标注有参构造函数); - 使用工厂方法实例化。
3. @Autowired
构造函数未被调用
原因:AutowiredAnnotationBeanPostProcessor
未被注册(如未启用组件扫描或@EnableAutowired
)。
解决方案:
- 确保
@ComponentScan
扫描到MyBean
所在的包; - 确保
@EnableAutowired
或context:annotation-config
已配置(Spring Boot自动启用)。
五、总结
createBeanInstance
是Spring bean实例化的核心入口,其流程可概括为:
- 优先使用
InstanceSupplier
(最灵活); - 处理工厂方法(静态/实例工厂);
- 处理构造函数注入(
@Autowired
、自动装配); - 默认无参构造函数(兜底方案)。
通过InstantiationAwareBeanPostProcessor
、InstantiationStrategy
等扩展点,Spring允许开发者自定义实例化过程,满足各种复杂需求(如代理、动态创建bean)。深入理解createBeanInstance
的源码,有助于解决bean实例化过程中的问题,提升对Spring容器的认知。
参考资料:
- Spring Framework 5.3.x源码(
AbstractAutowireCapableBeanFactory
、ConstructorResolver
); - 《Spring源码深度解析》(郝佳);
- Spring官方文档(Bean Instantiation部分)。