回顾
在Spring 容器初始化流程(中)中我们分析了bean工厂的后置处理器注册调用、Bean后置处理器的注册、国际化、事件广播器等 ,在最后的篇幅中,我们将会分析上下文的监听器注册,及容器生命周期等相关源码。在最后还会附上一张较为完整的容器初始化流程图哦~
开始吧~
10. registerListeners
在所有 beanDefinition 中查找 listener bean,然后注册到广播器中
// AbstractApplicationContext.java
protected void registerListeners() {
// 首先注册静态指定的侦听器。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 不要在这里初始化 FactoryBean:需要将所有常规 bean 保持未初始化状态,以便后处理器适用于它们!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 至此,已经完成将监听器注册到ApplicationEventMulticaster中,下面将发布前期的事件给监听器。
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
11. finishBeanFactoryInitialization
初始化剩下的单例Bean(非延迟加载的)
流程如下:

然后来看看源码:
// AbstractApplicationContext.java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化转换器
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));
}
// 如果之前没有注册 bean 后置处理器(例如PropertyPlaceholderConfigurer),则注册默认的解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 初始化LoadTimeWeaverAware类型的bean LoadTimeWeaverAware是类加载时进行织入
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时类加载器进行类型匹配。
beanFactory.setTempClassLoader(null);
// 冻结之前beandifinition的配置,留作后面的缓存用
beanFactory.freezeConfiguration();
// 初始化所有剩余的单例(非延迟初始化)
beanFactory.preInstantiateSingletons();
}
11.1 `LoadTimeWeaverAware`
Spring使用LoadTimeWeaver
在将类加载到Java虚拟机(JVM)时动态转换类。
11.2 `freezeConfiguration`
只是更新容器的配置状态和BeanDefinitionNames缓存
// DefaultListableBeanFactory.java
/** 是否可以缓存所有bean的bean定义元数据。 */
private volatile boolean configurationFrozen = false;
/** 缓存的bean定义名数组。 */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
11.3 `preInstantiateSingletons`
初始化所有剩余的单例(非延迟初始化),结合上面的流程图和注释
// DefaultListableBeanFactory.java
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// 迭代副本以允许 init 方法,这些方法反过来注册新的 Bean 定义。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 初始化所有非lazy init的bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 非抽象的单例类,且lazy init为false
if (isFactoryBean(beanName)) {
// 工厂bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// 判断工厂bean是否需要优先初始化
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) {
// 初始化工厂bean
getBean(beanName);
}
}
}
else {
// 非工厂bean,直接初始化
getBean(beanName);
}
}
}
// 为所有适用的bean触发初始化后的回调…
for (String beanName : beanNames) {
// 获取单例实例
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
// 如果是 SmartInitializingSingleton 类型的实例,则调用其单例初始化后的回调方法
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
11.3.1 getSingleton
这里是真正初始化的逻辑:
// DefaultListableBeanFactory.java
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从单例缓存中取,取到就直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果取不到,且单例正在初始化中
synchronized (this.singletonObjects) {
// 从早期初始化的缓存中取(在loadBeanDefinition的时候可能触发了并完成了实例化)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 如果没取到,并且允许从早期引用中获取(在loadBeanDefinition时触发但未完成实例化)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 如果能获取到早期的对象工厂,就调用对象工厂的getObject方法获取单例实例
singletonObject = singletonFactory.getObject();
// 设置到早期单例缓存对象中,以便其他依赖bean获取
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除早期的单例对象工厂
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
结合注释,比较清楚的逻辑
12. finishRefresh
完成刷新过程,通知生命周期处理器
lifecycleProcessor
刷新过程,同时发出ContextRefreshEvent
通知别人
主要是调用 LifecycleProcessor#onRefresh()
,并且发布事件(ContextRefreshedEvent
)。

// AbstractApplicationContext.java
protected void finishRefresh() {
// 清除上下文级资源缓存(如扫描中的 ASM 元数据)。
clearResourceCaches();
// 初始化上下文的生命周期处理器。
initLifecycleProcessor();
// 通知实现了Lifecycle的bean容器已经完成刷新
getLifecycleProcessor().onRefresh();
// 发布刷新完成事件。
publishEvent(new ContextRefreshedEvent(this));
// 如果配置了pring.liveBeansView.mbeanDomain属性,就尝试注册到JVM平台的MBeanServer中
// 以便通过JXM来实时查看上下文中注册了哪些bean
LiveBeansView.registerApplicationContext(this);
}
12.1 `clearResourceCaches`
// AbstractApplicationContext.java
public void clearResourceCaches() {
this.resourceCaches.clear();
}
12.2 `initLifecycleProcessor`
// AbstractApplicationContext.java
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
// 如果有配置了生命周期处理器,则实例化并注册到容器中
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
// 如果没有指定,则实例化默认的生命周期处理器,并注册到容器和bean工厂中(注册为单例bean)
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
12.3 getLifecycleProcessor#onRefresh
已默认的生命周期处理器来示例
// DefaultLifecycleProcessor.java
@Override
public void onRefresh() {
// 调用所有生命周期的start方法
startBeans(true);
// 设置订单的running状态为true
this.running = true;
}
12.3.1 startBeans
方法
对生命周期分组并排序后,调用其start方法
// DefaultLifecycleProcessor.java
private void startBeans(boolean autoStartupOnly) {
// 获取所有Lifecycle类型的bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
// 对不同阶段的bean进行遍历分组
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
// 如果有则调用生命周期组的start方法
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
getLifecycleBeans
获取所有Lifecycle类型的bean
// DefaultLifecycleProcessor.java
protected Map<String, Lifecycle> getLifecycleBeans() {
// 获取bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Map<String, Lifecycle> beans = new LinkedHashMap<>();
// 获取 Lifecycle 类型的beanName
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
// 获取真实的beanName(可能传入的是工厂bean或者alias)
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
if ((beanFactory.containsSingleton(beanNameToRegister) &&
(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
// 如果是已注册的单例bean,或者符合指定类型的bean,则进行初始化并放到Map中返回
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
return beans;
}
LifecycleGroup#start
// DefaultLifecycleProcessor.java
public void start() {
// members就是上面通过group.add方法添加进来的
if (this.members.isEmpty()) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Starting beans in phase " + this.phase);
}
Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}实际上就是调用成员的start方法,先来看看
LifecycleGroupMember
的结构// DefaultLifecycleProcessor.java
private class LifecycleGroupMember implements Comparable<LifecycleGroupMember> {
private final String name;
private final Lifecycle bean;
}只是简单的beanName及生命周期bean实例
再看看
doStart
方法// DefaultLifecycleProcessor.java
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
// 当前bean不是自己
// 获取bean的依赖,并递归调用doStart方法
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
for (String dependency : dependenciesForBean) {
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
if (logger.isTraceEnabled()) {
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
}
try {
// 启动生命周期
bean.start();
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
}
if (logger.isDebugEnabled()) {
logger.debug("Successfully started bean '" + beanName + "'");
}
}
}
}都是比较简单的逻辑,先调用依赖的start方法(如果依赖符合的话),然后再调用当前bean的start方法。
至此,Spring容器的初始化过程就算结束了,最后放一张全局的流程图(有点长):

关于BeanDefinition
的载入与Bean的实例化(doGetBean
),会有新的篇幅来详细解析,敬请期待~
49 条评论
clenbuterol acheter · 2023年6月21日 下午11:21
… [Trackback]
[…] Find More on on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
where to buy dmt vape · 2023年6月23日 上午7:01
… [Trackback]
[…] There you can find 92378 more Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เว็บ หวยยี่กี มีต้นกำเนิดมาจากไหน · 2023年7月6日 上午6:47
… [Trackback]
[…] Find More Info here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
แอร์ ยี่ห้อไหนดี · 2023年7月6日 上午7:45
… [Trackback]
[…] Read More on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
pic5678 · 2023年7月7日 上午6:19
… [Trackback]
[…] Read More Information here on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
rajabandarq · 2023年7月13日 下午4:04
… [Trackback]
[…] Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
ทำกล่องขนมกล่องเค้กราคาถูก · 2023年7月19日 上午6:54
… [Trackback]
[…] Information to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
woolworths dried mushrooms · 2023年7月21日 上午9:55
… [Trackback]
[…] Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
บาคาร่า · 2023年7月22日 上午7:48
… [Trackback]
[…] There you will find 70192 additional Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
พรมดักฝุ่นรถยนต์ · 2023年8月1日 上午7:03
… [Trackback]
[…] Find More here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Buy pounds of weed online · 2023年8月3日 上午2:39
… [Trackback]
[…] Read More on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
find more · 2023年8月4日 上午7:09
… [Trackback]
[…] Find More Information here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
รับทำ SEO · 2023年8月4日 上午7:36
… [Trackback]
[…] Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
ป้ายโฆษณา · 2023年8月5日 上午7:17
… [Trackback]
[…] Information to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
พนันบอล true money · 2023年8月6日 上午10:18
… [Trackback]
[…] There you can find 7962 additional Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
หวย24 · 2023年8月6日 上午10:44
… [Trackback]
[…] Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เครื่องกรองน้ำ coway · 2023年8月7日 上午6:34
… [Trackback]
[…] Find More on to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Payday Loans Cantley QC · 2023年8月7日 下午6:19
… [Trackback]
[…] Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
ผลิตภัณ์ Relx · 2023年8月8日 上午7:16
… [Trackback]
[…] Find More here on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
togel singapore · 2023年8月14日 下午7:35
… [Trackback]
[…] Find More on to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
sudoku · 2023年8月16日 上午12:31
… [Trackback]
[…] Read More here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
สล็อต ฝากถอน true wallet เว็บตรง 888pg · 2023年8月24日 上午6:34
… [Trackback]
[…] Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
รีวิว vivo v29 5G · 2023年8月26日 上午6:31
… [Trackback]
[…] Find More here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
หวยฮานอย · 2023年8月30日 上午6:21
… [Trackback]
[…] Find More on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
สล็อต pg เว็บตรง แตกหนัก · 2023年8月30日 上午7:53
… [Trackback]
[…] Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เว็บพนันบอล วอ ล เล็ ตเว็บพนันบอล sbobet · 2023年8月31日 上午7:20
… [Trackback]
[…] Find More to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
slot online · 2023年9月1日 下午7:06
… [Trackback]
[…] Find More to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
สล็อตออนไลน์ · 2023年9月2日 上午6:18
… [Trackback]
[…] Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
สล็อตเบทฟิก · 2023年9月3日 上午6:57
… [Trackback]
[…] Find More Info here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
condo for sale pattaya · 2023年9月3日 上午7:17
… [Trackback]
[…] There you will find 65035 more Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เว็บตรงไม่ผ่านเอเย่นต์ · 2023年9月6日 上午6:31
… [Trackback]
[…] Read More Info here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
skaties te · 2023年9月6日 下午6:05
… [Trackback]
[…] There you can find 85174 more Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
counseling long island · 2023年9月7日 上午6:08
… [Trackback]
[…] Read More Info here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
luxury pool villas in phuket · 2023年9月7日 上午6:16
… [Trackback]
[…] There you can find 18530 additional Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เขียนโปรแกรม · 2023年9月7日 上午7:09
… [Trackback]
[…] Find More Information here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
naga qq · 2023年9月9日 上午1:51
… [Trackback]
[…] Read More Information here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
สมัครyehyeh · 2023年9月9日 上午7:41
… [Trackback]
[…] Read More Information here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Data singapore · 2023年9月10日 上午1:16
… [Trackback]
[…] Find More on on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เพิ่มยอดไลค์ · 2023年9月10日 上午6:32
… [Trackback]
[…] Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
openlims.org · 2023年9月10日 下午11:58
… [Trackback]
[…] Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Data HK · 2023年9月11日 下午11:21
… [Trackback]
[…] Read More on on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
relax massage · 2023年9月12日 上午6:44
… [Trackback]
[…] Here you will find 36661 more Information on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
รปภ เชียงใหม่ · 2023年9月12日 上午7:00
… [Trackback]
[…] Here you can find 70507 more Info to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
เค้กวันเกิดบางแค · 2023年9月12日 上午7:02
… [Trackback]
[…] Find More Information here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Vape carts USA · 2023年9月14日 上午1:41
… [Trackback]
[…] Read More to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
คาสิโนสด AE Group · 2023年9月14日 上午6:32
… [Trackback]
[…] Find More Info here to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Recommended Reading · 2023年9月14日 下午10:44
… [Trackback]
[…] Info on that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
Toyota Alphard 2024 ราคา · 2023年9月15日 上午6:57
… [Trackback]
[…] Read More to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
คอนโดใหม่ · 2023年9月15日 上午7:06
… [Trackback]
[…] Information to that Topic: hugr.cn/2019/12/12/spring-容器初始化流程(下)/ […]
评论已关闭。