Spring源码分析(二十五)finishRefresh
摘要: 本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。
在 Spring 中还提供了 Lifecycle 接口, Lifecycle 中包含start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在Spring关闭的时候调用 stop方法来结束生命周期,通常用来配置后台程序,在启动后一直运行(如对 MQ 进行轮询等)。而ApplicationContext的初始化最后正是保证了这一功能的实现。
- /**
- * Finish the refresh of this context, invoking the LifecycleProcessor's
- * onRefresh() method and publishing the
- * {@link org.springframework.context.event.ContextRefreshedEvent}.
- */
- protected void finishRefresh() {
- // Clear context-level resource caches (such as ASM metadata from scanning).
- clearResourceCaches();
- // 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启动或停止时,它会通过LifecycleProcessor来与所有声明的bean的周期做状态更新,而在LifecycleProcessor的使用前首先需要初始化。
- /**
- * Initialize the LifecycleProcessor.
- * Uses DefaultLifecycleProcessor if none defined in the context.
- * @see org.springframework.context.support.DefaultLifecycleProcessor
- */
- 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 {
- DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
- defaultProcessor.setBeanFactory(beanFactory);
- this.lifecycleProcessor = defaultProcessor;
- beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
- if (logger.isTraceEnabled()) {
- logger.trace("Unable to locate LifecycleProcessor with name '" +
- LIFECYCLE_PROCESSOR_BEAN_NAME +
- "': using default [" + this.lifecycleProcessor + "]");
- }
- }
- }
二、onRefresh
启动所有实现了Lifecycle接口的bean。
- @Override
- public void onRefresh() {
- startBeans(true);
- this.running = true;
- }
- // Internal helpers
- private void startBeans(boolean autoStartupOnly) {
- Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
- Map<Integer, LifecycleGroup> phases = new HashMap<>();
- 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);
- }
- });
- if (!phases.isEmpty()) {
- List<Integer> keys = new ArrayList<>(phases.keySet());
- Collections.sort(keys);
- for (Integer key : keys) {
- phases.get(key).start();
- }
- }
- }
三、publishEvent
当完成ApplicationContext初始化的时候,要通过Spring中的事件发布机制来发出ContextRefreshedEvent事件,以保证对应的监听器可以做进一步的逻辑处理。
- /**
- * Publish the given event to all listeners.
- * <p>Note: Listeners get initialized after the MessageSource, to be able
- * to access it within listener implementations. Thus, MessageSource
- * implementations cannot publish events.
- * @param event the event to publish (may be an {@link ApplicationEvent}
- * or a payload object to be turned into a {@link PayloadApplicationEvent})
- */
- @Override
- public void publishEvent(Object event) {
- publishEvent(event, null);
- }
- /**
- * Publish the given event to all listeners.
- * @param event the event to publish (may be an {@link ApplicationEvent}
- * or a payload object to be turned into a {@link PayloadApplicationEvent})
- * @param eventType the resolved event type, if known
- * @since 4.2
- */
- protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
- Assert.notNull(event, "Event must not be null");
- // Decorate event as an ApplicationEvent if necessary
- ApplicationEvent applicationEvent;
- if (event instanceof ApplicationEvent) {
- applicationEvent = (ApplicationEvent) event;
- }
- else {
- applicationEvent = new PayloadApplicationEvent<>(this, event);
- if (eventType == null) {
- eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
- }
- }
- // Multicast right now if possible - or lazily once the multicaster is initialized
- if (this.earlyApplicationEvents != null) {
- this.earlyApplicationEvents.add(applicationEvent);
- }
- else {
- getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
- }
- // Publish event via parent context as well...
- if (this.parent != null) {
- if (this.parent instanceof AbstractApplicationContext) {
- ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
- }
- else {
- this.parent.publishEvent(event);
- }
- }
- }
Spring源码分析(二十五)finishRefresh的更多相关文章
- Spring源码分析(十五)获取单例
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例be ...
- ABP源码分析二十五:EventBus
IEventData/EventData: 封装了EventData信息,触发event的源对象和时间 IEventBus/EventBus: 定义和实现了了一系列注册,注销和触发事件处理函数的方法. ...
- Vue.js 源码分析(二十五) 高级应用 插槽 详解
我们定义一个组件的时候,可以在组件的某个节点内预留一个位置,当父组件调用该组件的时候可以指定该位置具体的内容,这就是插槽的用法,子组件模板可以通过slot标签(插槽)规定对应的内容放置在哪里,比如: ...
- Spring源码分析(十八)创建bean
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- spark 源码分析之十五 -- Spark内存管理剖析
本篇文章主要剖析Spark的内存管理体系. 在上篇文章 spark 源码分析之十四 -- broadcast 是如何实现的?中对存储相关的内容没有做过多的剖析,下面计划先剖析Spark的内存机制,进而 ...
- Spring源码分析(十二)FactoryBean的使用
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 一般情况下,Spring通过反射机制利用bean的class属性指定实现 ...
- Spring源码分析(十九)容器的功能扩展概览
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单 ...
- Spring源码分析(十六)准备创建bean
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 我们不可能指望在一个函数中完成一个复杂的逻辑,而且我们跟踪了这么多Spring ...
- Android源码分析(十五)----GPS冷启动实现原理分析
一:原理分析 主要sendExtraCommand方法中传递两个参数, 根据如下源码可以知道第一个参数传递delete_aiding_data,第二个参数传递null即可. @Override pub ...
随机推荐
- PHP中常用的魔术方法
我们在PHP中经常用到魔术方法,像构造方法,析构方法等等魔术变量,下面总结一下一些常用的魔术变量: __construct(),__destruct(),__clone(),__autoload(), ...
- CSS属性之attr()
attr()准确的说,不应该是一个属性,而是一个CSS的函数,我们先看看MDN上的介绍吧: Summary The attr() CSS function is used to retrieve th ...
- C# 2个List<T>比较内部项是否相等(全部相等则相等,反之不相等)
static void Main(string[] args) { List<string> a = new List<string>() { "a", & ...
- opencv3.2.0形态学滤波之开运算、闭运算
/* 一.开运算: (1)开运算,其实就是先腐蚀后膨胀的过程. (2)数学表达式:dst = open(src,element) = dilate(erode(src,element)) (3)作用: ...
- 管理DnS服务器知识点
DNS服务器是计算机域名系统 (Domain Name System 或Domain Name Service) 的缩写,它是由域名解析器和域名服务器组成的.域名服务器是指保存有该网络中所有主机的域名 ...
- Ubuntu添加源列表
1.首先备份源列表:sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup 2.清空原来的/etc/apt/sources.list,添加 ...
- linux ubuntu 本地镜像 软件源 制作方法
1.配置当前软件源,镜像非常大,所以首先要配置一下载速度快的软件源http://fffo.blog.163.com/blog/static/2119130682014322104136601/2.安装 ...
- MySQL案例09:Last_IO_Error: Got fatal error 1236 from master when reading data from binary log
刚处理完“挖矿”事件,在做最后一个MySQL NBU备份的时候,发现从库有问题,好奇的是怎么主从状态异常没有告警呢?先不管这么多了,处理了这个问题再完善告警内容. 一.错误信息 从库show slav ...
- mysql-5.7 持久化统计信息详解
一.持久化统计信息的意义: 统计信息用于指导mysql生成执行计划,执行计划的准确与否直接影响到SQL的执行效率:如果mysql一重启 之前的统计信息就没有了,那么当SQL语句来临时,那么mysql就 ...
- 导出AD用户所属组,查询AD用户(aduser)
$ous="admin","bladmin","af","dd"for($i=0;$i -lt 2;$i++) { $o ...