Spring ApplicationContext(十)finishRefresh
ApplicationContext(十)finishRefresh
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)
经过以上 11 步,ApplicationContext 的刷新工作基本完成,就剩下最后一点收尾的工作。
在 Spring 中还提供了 Lifecycle 接口, Lifecycle 中包含 start/stop 方法,实现此接口后 Spring 会保证在启动的时候调用其 start 方法开始生命周期,并在 Spring 关闭的时候调用 stop 方法来结束生命周期,通常用来配置后台程序,在启动后一直运行(如对 MQ 进行轮询等)而 ApplicationContext 的初始化最后正是保证了这一功能的实现。
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
一、initLifecycleProcessor
当 ApplicationContext 启动或停止时,它会通过 initLifecycleProcessor 来与所有声明的 bean 的周期做状态更新,而在 LifecycleProcessor 的使用前首先需要初始化。
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
}
}
二、onRefresh
启动所有实现了 Lifecycle 接口的 bean
public void onRefresh() {
startBeans(true);
this.running = true;
}
// Spring 内部用
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
Lifecycle bean = entry.getValue();
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(entry.getKey(), bean);
}
}
if (phases.size() > 0) {
List<Integer> keys = new ArrayList<Integer>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
3. publishEvent
当完成 ApplicationContext 初始化的时候,要通过 Spring 中的事件发布机制来发出 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理。
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// 1. 如果 event 不是 ApplicationEvent,则需要进行封装成 PayloadApplicationEvent
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
}
}
// 2. 发布事件 event,如果多播器懒加载,还没有初始化则将该事件先放到 earlyApplicationEvents 容器中
// 等待多播器创建好了再发布事件 ???
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 3. 父容器中也需要发布该事件 event
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
每天用心记录一点点。内容也许不重要,但习惯很重要!
Spring ApplicationContext(十)finishRefresh的更多相关文章
- Spring ApplicationContext(一)初始化过程
Spring 容器 ApplicationContext(一)初始化过程 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) ...
- 使用Arthas 获取Spring ApplicationContext还原问题现场
## 背景 最近来了个实习僧小弟,安排他实现对目标网站 连通性检测的小功能,简单讲就是将下边的shell 脚本换成Java 代码来实现 ``` 1#!/bin/bash 2URL="http ...
- Spring入门(十四):Spring MVC控制器的2种测试方法
作为一名研发人员,不管你愿不愿意对自己的代码进行测试,都得承认测试对于研发质量保证的重要性,这也就是为什么每个公司的技术部都需要质量控制部的原因,因为越早的发现代码的bug,成本越低,比如说,Dev环 ...
- 以静态变量保存 Spring ApplicationContext
package com.thinkgem.jeesite.common.utils; import java.net.HttpURLConnection; import java.net.URL; i ...
- spring Boot(十九):使用Spring Boot Actuator监控应用
spring Boot(十九):使用Spring Boot Actuator监控应用 微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台 ...
- Spring Boot(十八):使用Spring Boot集成FastDFS
Spring Boot(十八):使用Spring Boot集成FastDFS 环境:Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0 功能:使用Spring Boot将文 ...
- Spring Boot(十六):使用Jenkins部署Spring Boot
Spring Boot(十六):使用Jenkins部署Spring Boot jenkins是devops神器,介绍如何安装和使用jenkins部署Spring Boot项目 jenkins搭建 部署 ...
- Spring Boot(十五):spring boot+jpa+thymeleaf增删改查示例
Spring Boot(十五):spring boot+jpa+thymeleaf增删改查示例 一.快速上手 1,配置文件 (1)pom包配置 pom包里面添加jpa和thymeleaf的相关包引用 ...
- Spring Boot(十四):spring boot整合shiro-登录认证和权限管理
Spring Boot(十四):spring boot整合shiro-登录认证和权限管理 使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉 ...
- Spring Boot(十二):spring boot如何测试打包部署
Spring Boot(十二):spring boot如何测试打包部署 一.开发阶段 1,单元测试 在开发阶段的时候最重要的是单元测试了,springboot对单元测试的支持已经很完善了. (1)在p ...
随机推荐
- Ubuntu下安装、激活并配置Pycharm
Ubuntu下安装.激活并配置Pycharm 最近在学习Python这门语言,到了需要Python编译器学习的阶段,通过网上了解各个Python编译器的优缺点,最后选择了pycharm作为Python ...
- sql 求max和min,但是第二大,第二小怎么算?
利用子查询,但这样速度较慢. SELECT Baoming.id, Baoming.addtime AS '报名时间', CONCAT(Members.realname,Members.usernam ...
- app.route()
[app.route()] 可使用 app.route() 创建路由路径的链式路由句柄.由于路径在一个地方指定,这样做有助于创建模块化的路由,而且减少了代码冗余和拼写错误.请参考 Router() 文 ...
- python网络编程之C/S架构介绍
标签(空格分隔): c/s架构介绍 什么是C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),后续我们可以试着写个c/s软件实现服务器软件与客户端软件基于网络通信: 计 ...
- Kerberos 互信免登陆
第一步:机器加互信 将机器A的Kerberos name加到机器B的~/.k5login中,同时将机器B的Kerberos name加到机器A的~/.k5login中 例如:host/bjm6-193 ...
- centos7 mysql主从数据库同步
主:192.168.2.222:从:192.168.2.223 一:安装mysql 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql!这里依旧以mysql为例进行展示 1.先检 ...
- java 对一个字符串去重,即去掉字符串内重复元素
String str ="abc|efa|abc|efa|abc"; String str1 = str.replaceAll("(?s)(.)(?=.*\\1)&quo ...
- Appium+python自动化4-等待函数
4.1 等待函数癈使用 4.1.1 为什么要使用等待函数 我们在做自动化的时候很多时候都不是很顺利,不是因为app的问题,我们的脚本也没问题,但是很多时候都会报错,比如一个页面本来就有id为1的这个元 ...
- python——线程相关
使用python的threading中的Thread 下面是两种基本的实现线程的方式: 第一种方式———— #coding=utf-8 """ thread的第一种声明及 ...
- swift - 快速代码块 - 创建 tableview等一些控件 基本属性
1.创建tableview private lazy var cellId = "cellId" fileprivate lazy var tv : UITableView = { ...