- Spring Boot 应用启动入口
Spring Boot 应用通常从 SpringApplication.run 方法开始启动,这个方法会创建并刷新应用上下文。 - 刷新应用上下文
SpringApplication.run 方法内部会调用 refreshContext 方法,最终调用 AbstractApplicationContext 的 refresh 方法来刷新应用上下文,这个方法是 Bean 创建过程的核心入口。以下是 refresh 方法的关键代码片段:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新上下文环境
prepareRefresh();
// 获取 BeanFactory 并进行预刷新操作
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 配置 BeanFactory
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对 BeanFactory 进行后置处理
postProcessBeanFactory(beanFactory);
// 调用 BeanFactory 后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 Bean 后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化应用事件多播器
initApplicationEventMulticaster();
// 在特定上下文子类中初始化其他特殊 Bean
onRefresh();
// 注册监听器
registerListeners();
// 实例化所有剩余的(非懒加载)单例 Bean
finishBeanFactoryInitialization(beanFactory);
// 完成刷新,发布相应事件
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"canceling refresh attempt: " + ex);
}
// 销毁已创建的单例 Bean 以避免资源泄漏
destroyBeans();
// 重置 'active' 标志
cancelRefresh(ex);
// 将异常传播出去
throw ex;
} finally {
// 重置公共缓存
resetCommonCaches();
}
}
}
- 实例化剩余的单例 Bean
finishBeanFactoryInitialization 方法会调用 preInstantiateSingletons 方法来实例化所有剩余的(非懒加载)单例 Bean,以下是关键代码:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// 获取所有 Bean 定义的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 循环实例化所有非懒加载的单例 Bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() &&!bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 实例化普通 Bean
getBean(beanName);
}
}
}
// 触发所有实现了 SmartInitializingSingleton 接口的 Bean 的 afterSingletonsInstantiated 方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
- 创建 Bean 的核心方法 doCreateBean
getBean 方法最终会调用 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法来创建 Bean,以下是该方法的关键代码:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 创建 Bean 实例
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 允许 Bean 后置处理器修改合并后的 Bean 定义
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 处理 Bean 的循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 填充 Bean 的属性
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 处理循环引用
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 注册 Bean 的销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
总结
Spring Boot 中 Bean 的创建过程主要包括应用上下文的刷新、实例化非懒加载的单例 Bean 以及创建 Bean 的具体步骤(实例化、属性填充、初始化等)。