springboot源码解析(2)启动过程的生命周期和观察者模式

1. 简介

在深入springboot启动源码之前,我们先学习一下springboot启动过程中的生命周期划分和其中用到的观察者模式。这对我们之后分析启动过程的源码至关重要。同时,我们也可以进一步理解到观察者的使用。

2.springboot启动过程图解

按下图,整个生命周期分为:监听器初始化、环境准备、容器实例化、Bean加载、容器刷新、Runner调用。
在这几个生命周期之间,利用监听器,实现相关的处理。
springboot启动图解

![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/b58ee1e944a2766ed54480d63fa612e2.png

3.观察者模式的具体实现(源码)

springboot启动过程中的观察者模式,主要是用一下几个接口/类实现的:

  • SpringApplicationRunListeners
  • SpringApplicationRunListener接口(具体实现是org.springframework.boot.context.event.EventPublishingRunListener
  • ApplicationListener(监听器)

3.1 SpringApplicationRunListeners

所有监听器的调用都是通过SpringApplicationRunListeners listeners对象实现的。在getRunListeners(args)方法中,会从spring-boot/META-INF/spring.factories寻找并实例化类。并注入到SpringApplicationRunListenerslisteners属性中。
在这里插入图片描述

class SpringApplicationRunListeners {

	private final Log log;

	private final List<SpringApplicationRunListener> listeners;
	}
	void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}
	//..........以下省略,同上
SpringApplicationRunListeners listeners = getRunListeners(args);
 	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}

3.2 EventPublishingRunListener

EventPublishingRunListener的实例化中,会实例化一个SimpleApplicationEventMulticaster对象,并将SpringApplication中已有的监听器注册到这个广播器中。

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

	private final SpringApplication application;

	private final String[] args;

	private final SimpleApplicationEventMulticaster initialMulticaster;
    //初始化时会新建一个事件广播器,同时将之前实例化的监听器注册到广播器中
	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}
    //优先级是最高的
	@Override
	public int getOrder() {
		return 0;
	}
    //发布ApplicationStartingEvent事件
    // run方法第一次启动立即被调用。可以用于非常早期的初始化
	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}
    //发布ApplicationEnvironmentPreparedEvent事件
    //环境environment 准备好之后,容器ApplicationContext创建之前,调用。
	@Override
	public void environmentPrepared(ConfigurableEnvironment environment) {
		this.initialMulticaster
				.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
	}
    //发布ApplicationContextInitializedEvent事件
    //容器已经创建好了,资源加载之前---调用。
	@Override
	public void contextPrepared(ConfigurableApplicationContext context) {
		this.initialMulticaster
				.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
	}
    //发布ApplicationPreparedEvent事件
    // 容器加载资源之后,在refresh刷新之前  --调用
	@Override
	public void contextLoaded(ConfigurableApplicationContext context) {
		for (ApplicationListener<?> listener : this.application.getListeners()) {
			if (listener instanceof ApplicationContextAware) {
				((ApplicationContextAware) listener).setApplicationContext(context);
			}
			context.addApplicationListener(listener);
		}
		this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
	}
     //发布ApplicationPreparedEvent和AvailabilityChangeEvent事件
     //容器启动后,CommandLineRunners和ApplicationRunners还没有执行前--调用
	@Override
	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}
   //发布ApplicationReadyEvent和AvailabilityChangeEvent事件
   //在run()方法结束前,CommandLineRunners和ApplicationRunners执行后--调用
	@Override
	public void running(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}
    //发布ApplicationFailedEvent事件
    //出现异常时调用
	@Override
	public void failed(ConfigurableApplicationContext context, Throwable exception) {
		ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
		if (context != null && context.isActive()) {
			// Listeners have been registered to the application context so we should
			// use it at this point if we can
			context.publishEvent(event);
		}
		else {
			// An inactive context may not have a multicaster so we use our multicaster to
			// call all of the context's listeners instead
			if (context instanceof AbstractApplicationContext) {
				for (ApplicationListener<?> listener : ((AbstractApplicationContext) context)
						.getApplicationListeners()) {
					this.initialMulticaster.addApplicationListener(listener);
				}
			}
			this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
			this.initialMulticaster.multicastEvent(event);
		}
	}

	private static class LoggingErrorHandler implements ErrorHandler {

		private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class);

		@Override
		public void handleError(Throwable throwable) {
			logger.warn("Error calling ApplicationEventListener", throwable);
		}

	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值