SpringBoot中的监听机制

139 阅读3分钟

SpringBoot中内置的监听器

内置监听器都定义在在spring.factories文件中

监听器监听事件说明
ClearCachesApplicationListenerContextRefreshedEvent当触发ContextRefreshedEvent事件会清空应用的缓存
ParentContextCloserApplicationListenerParentContextAvailableEvent触发ParentContextAvailableEvent事件会完成父容器关闭的监听器
CloudFoundryVcapEnvironmentPostProcessorApplicationPreparedEvent判断环境中是否存在VCAP_APPLICATION或者VCAP_SERVICES。如果有就添加Cloud Foundry的配置;没有就不执行任何操作。
FileEncodingApplicationListenerApplicationEnvironmentPreparedEvent文件编码的监听器
AnsiOutputApplicationListenerApplicationEnvironmentPreparedEvent根据 spring.output.ansi.enabled参数配置 AnsiOutput
ConfigFileApplicationListenerApplicationEnvironmentPreparedEventApplicationPreparedEvent完成相关属性文件的加载,application.properties、 application.yml
DelegatingApplicationListenerApplicationEnvironmentPreparedEvent监听到事件后转发给环境变量 context.listener.classes指定的那些事件监听器
ClasspathLoggingApplicationListenerApplicationEnvironmentPreparedEventApplicationFailedEvent一个SmartApplicationListener,对环境就绪事件ApplicationEnvironmentPreparedEvent/应用失败事件ApplicationFailedEvent做出响应,往日志DEBUG级别输出TCCL(thread context class loader)的classpath。
LoggingApplicationListenerApplicationStartingEvent ApplicationEnvironmentPreparedEvent ApplicationPreparedEventContextClosedEventApplicationFailedEvent配置 LoggingSystem。使用 logging.config环境变量指定的配置或者缺省配置
LiquibaseServiceLocatorApplicationListenerApplicationStartingEvent使用一个可以和Spring Boot可执行jar包配合工作的版本替换liquibase ServiceLocator
BackgroundPreinitializerApplicationStartingEventApplicationReadyEventApplicationFailedEvent尽早触发一些耗时的初始化任务,使用一个后台线程

自定义监听器和监听事件

自定义监听事件

需要继承ApplicationEvent

public class MyEvent extends ApplicationEvent {
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public MyEvent(Object source) {
        super(source);
    }
}

自定义监听器

需要实现ApplicationListener接口

/**
 * @author 26917
 * 自定义监听器
 *  监听自定义的事件
 */
public class MyCustomerEventListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("MyCustomerEventListener ----》 自定义事件触发" + event);
    }
}

ApplicationListener类图

将这个自定义的监听器加入到spring.factories文件中

org.springframework.context.ApplicationListener=\
com.nyc.listener.MyCustomerEventListener

使用这个监听器

@RestController
public class UserController {
    @Autowired
    private ApplicationContext context;
    @GetMapping("/hello")
    public String hello(){
        context.publishEvent(new MyEvent(new Object()));
        return "hello";
    }
}

监听器代码分析

类图分析

getRunListeners(args)方法

这个方法获取到事件发布器

EventPublishingRunListener 构造方法

public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    // 初始化多个监听器,其实就是我们前面加载的spring.factories文件中的11个监听器
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    // application.getListeners() 获取11个监听器
    for (ApplicationListener<?> listener : application.getListeners()) {
        // 绑定初始的11个监听器
        this.initialMulticaster.addApplicationListener(listener);
    }
}

listeners.starting()方法

触发启动事件 -》发布starting事件,那么监听starting事件的监听器就会触发

class SpringApplicationRunListeners {

	private final Log log;

	private final List<SpringApplicationRunListener> listeners;

	SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<>(listeners);
	}

	void starting() {
		// 发布器 EventPublishingRunListener
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}

	void environmentPrepared(ConfigurableEnvironment environment) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.environmentPrepared(environment);
		}
	}

	void contextPrepared(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextPrepared(context);
		}
	}

	void contextLoaded(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextLoaded(context);
		}
	}

	void started(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.started(context);
		}
	}

	void running(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.running(context);
		}
	}

	void failed(ConfigurableApplicationContext context, Throwable exception) {
		for (SpringApplicationRunListener listener : this.listeners) {
			callFailedListener(listener, context, exception);
		}
	}

	private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
			Throwable exception) {
		try {
			listener.failed(context, exception);
		}
		catch (Throwable ex) {
			if (exception == null) {
				ReflectionUtils.rethrowRuntimeException(ex);
			}
			if (this.log.isDebugEnabled()) {
				this.log.error("Error handling failed", ex);
			}
			else {
				String message = ex.getMessage();
				message = (message != null) ? message : "no error message";
				this.log.warn("Error handling failed (" + message + ")");
			}
		}
	}

}

SpringApplicationRunListeners类的作用

SpringApplicationRunListener 的集合代理类,用来统一调度并触发所有 RunListener,整体监视 Spring Boot 启动过程的各个阶段。

在源码中SpringApplicationRunListener接口的默认实现就只有,EventPublishingRunListener

EventPublishingRunListener类的starting方法。

@Override
public void starting() {
    this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}

在springboot的启动的时候会在以下几个阶段进行监听器发布,分别是启动阶段、环境配置准备阶段、容器上下文准备阶段、启动完成阶段、启动失败阶段以及运行阶段。