在 Spring 5 的源码中,实例化单例 Bean 的调用链可以从 Spring Boot 的主类 SpringApplication 的 run 方法开始。
下是大致的调用链路:
这是 Spring Boot 应用程序启动的入口方法。它创建了一个新的 Spring 应用上下文,并启动了应用程序。
该方法在 run 方法内部被调用,用于完成应用上下文的初始化和刷新。
这是 Spring Framework 中 ApplicationContext 接口的实现类的方法。它负责完成应用上下文的刷新过程。
该方法负责创建或获取新的 BeanFactory 实例,BeanFactory 是 Spring IoC 容器的核心。如果已经存在 BeanFactory 实例,则会重用。
该方法使用在步骤4中获取的 BeanFactory 实例进行应用上下文的配置和初始化。
该方法用于预实例化所有的单例 Bean。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
该方法负责遍历容器中的所有 BeanDefinition,检查是否是单例模式,并执行相应的实例化操作。
此方法继承自 AbstractBeanFactory.preInstantiateSingletons,它实际上会调用 AbstractBeanFactory.doGetBean 方法来创建单例 Bean 的实例。
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
while(true) {
String beanName;
Object bean;
do {
while(true) {
RootBeanDefinition bd;
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
while(var2.hasNext()) {
beanName = (String)var2.next();
Object singletonInstance = this.getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, this.getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
return;
}
beanName = (String)var2.next();
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract());
} while(!bd.isSingleton());
} while(bd.isLazyInit());
if (this.isFactoryBean(beanName)) {
bean = this.getBean("&" + beanName);
break;
}
this.getBean(beanName);
}
} while(!(bean instanceof FactoryBean));
FactoryBean<?> factory = (FactoryBean)bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
SmartFactoryBean var10000 = (SmartFactoryBean)factory;
((SmartFactoryBean)factory).getClass();
isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
}
}
该方法是获取 Bean 实例的核心方法,其中包括了解决循环依赖、实例化 Bean 对象和执行初始化操作等逻辑。
该方法是 AbstractBeanFactory.doGetBean 方法的一个关键步骤,用于创建 Bean 实例。它会调用相关的实例化策略和处理器来创建 Bean 对象。
该方法使用实例化策略(InstantiationStrategy)来实例化 Bean 对象,具体的实例化策略根据不同情况可能会有所不同。
这是 Spring 默认的实例化策略,默认使用反射来实例化 Bean 对象。
以上是大致的调用链,详细的实现细节可能因版本和具体配置而有所不同。在整个过程中,Spring 通过调用一系列的方法和处理器,完成了单例 Bean 的实例化和初始化工作,最终将可用的单例 Bean 放入容器中供其他组件使用。
术因分享而日新,每获新知,喜溢心扉。 诚邀关注公众号 『
码到三十五
』 ,获取更多技术资料。