在上一篇,记录了ioc容器的初始化,当ioc容器初始化之后,里面保存了BeanDefinition的信息,但此时 bean还不存在。
初始化bean有两个地方触发,一个是在容器的初始化的refresh方法里面的 finishBeanFactoryInitialization(beanFactory) 方法
该方法里面其实也是调用了getBean()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
//该方法创建一个ioc容器 并加载xml中的资源转为beanDefinition对象填充进去
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//设置beanFactory的后置处理
postProcessBeanFactory(beanFactory);
//调用beanFactory的后置处理器 这些后置处理器是在beanDefinition中向容器注册的
invokeBeanFactoryPostProcessors(beanFactory);
//注册bean的后置处理器 在bean的创建过程中调用
registerBeanPostProcessors(beanFactory);
//对上下文中的消息源进行初始化
initMessageSource();
//初始化上下文的事件机制
initApplicationEventMulticaster();
//始化其他特殊的bean 比如说springboot里面内置的tomcat
onRefresh();
//检查监听bean 并将这些bean向容器注册
registerListeners();
//实例化所有不是懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//发布容器事件,接收refresh过程
finishRefresh();
}
另一个地方就是ioc的getBean()方法,第一次调用这个方法获取这个bean的时候,如果这个bean没有被创建的话,就会触发bean的初始化。
先看下 finishBeanFactoryInitialization(beanFactory) 方法,
这个方法 会先获取所有实现了LoadTimeWeaverAware接口的bean的名字,然后挨个调用getBean方法进行初始化,最后调用 beanFactory.preInstantiateSingletons();初始化其他 单例非懒加载的类型的bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//先初始化ConversionService这个bean
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.
//获取所有可以提前加载的bean的名字 实现了LoadTimeWeaverAware接口的bean 用于需要被初始化阶段就能收到容器的通知的bean
//比如说tomcat有这个需求
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
//todo 核心方法 加载这些可以提前加载的bean的名字
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.
//todo 实例化 单例非懒加载的类型
beanFactory.preInstantiateSingletons();
}
看下preInstantiateSingletons方法
1.获取所有的beanNames ,beanDefinitionNames里面按顺序存储了所有的beanDefinition的beanNames
2.触发 所有的 非懒加载的单例bean 挨个进行初始化
3.通过beanName获取BeanDefinition ,该方法会从父容器和子容器合并集合中查找BeanDefinition
4.如果 BeanDefinition 非抽象,是单例 且非懒加载 那么继续下一个流程 否则忽略
5.检查是否是FactoryBean类型 如果不是 ,直接跳转到调用getBean
6. 判断是FactoryBean 调用getBean( FACTORY_BEAN_PREFIX + beanName) Bea