在Spring启动流程文章中讲到,容器的初始化是从refresh方法开始的,其在初始化的过程中会调用finishBeanFactoryInitialization方法。
而在该方法中则会调用DefaultListableBeanFactory#preInstantiateSingletons方法,该方法的核心作用是初始化非延迟加载的Bean,且提供了两个扩展点。源码及注释如下:
@Override
public void preInstantiateSingletons() throws BeansException {
//该方法先复制一份BeanDefinition名称列表,为了防止在初始化过程中有新的BeanDefinition被注册,
//从而导致遍历过程中的并发修改异常
List beanNames = new ArrayList<>(this.beanDefinitionNames);
//对于每个非抽象、单例且非懒加载的 BeanDefinition,如果它是一个 FactoryBean,
//则获取 FactoryBean 的实例,如果 FactoryBean 实现了 `SmartFactoryBean` 接口,
//则调用 `isEagerInit` 方法判断是否需要预先实例化,默认为需要预先实例化。
//如果该 Bean 需要预先实例化,则调用 `getBean` 方法进行实例化。
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) ((SmartFactoryBean) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 这里就是普通单例Bean正式初始化了
getBean(beanName);
}
}
}
//对于每个实现了SmartInitializingSingleton接口的单例Bean,调用其afterSingletonsInstantiated方法
// 执行时机是在bean的生命周期最后,即在bean完成实例化、属性注入、相关初始化操作后
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction