springboot启动二
-
上一章说到了run方法,主要分了10个步骤下面我就分别看下这些步骤都做了什么
- 属性配置不用说了 直接看第二步事件发布过程。
主要代码如下
//获取监听容器 SpringApplicationRunListeners listeners = getRunListeners(args); //发布事件 listeners.starting();
- 这里可以看到,事件发布有两个步骤,第一获取监听,第二发布事件。我们先看如何拿到监听的。
private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; //返回监听容器(getSpringFactoriesInstances方法加载了监听) return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); } ..... 代码 ..... //这里是SpringApplicationRunListeners的构造函数 SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) { this.log = log; this.listeners = new ArrayList<>(listeners); }
- 是不是有看到了熟悉的getSpringFactoriesInstances方法,这个方法按类型加载对应的spring.factories文件内的类并实例化,此步骤就是将监听全部加载实例化后,添加到了监听容器中即SpringApplicationRunListeners,下面我们事件发布starting()方法做了什么。
public void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } } //跟代码进去后可以找到EventPublishingRunListener,此类作用主要是发布SpringApplicationEvent事件 ,EventPublishingRunListener有好多种事件发布方法,针对启动过程不同而定的。比如 environmentPrepared contextLoaded等 // 我们先看下构造方法 public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; // 事件发布器 this.initialMulticaster = new SimpleApplicationEventMulticaster(); // 监听器初始化,将之前set到SpringApplication内的监听复制到发布器属性内 for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } } //我们看下事件如何发布的 @Override public void starting() { this.initialMulticaster.multicastEvent( //这里可以看到,我们发布的是ApplicationStartingEvent事件 new ApplicationStartingEvent(this.application, this.args)); }
- 我们看下SimpleApplicationEventMulticaster如何发布的,主要看如下方法
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //getApplicationListeners(event, type)是整个过程关键一步,筛选出符合的listner,通过事件类型 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { //获取异步执行器,这里可以自己添加如果没有直接同步执行 Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } } //这里可以看下getApplicationListeners实现 protected Collection<ApplicationListener<?>> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { //获取到事件发生的原始类,这里其实就是SpringApplication Object source = event.getSource(); //获取到SpringApplication的class对象 Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } //这里是缓存listner的缓存过程 这里会检查给定的类在给定的上下文中是否是缓存安全的 if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary //主要看这个方法 return retrieveApplicationListeners(eventType, sourceType, null); } } // retrieveApplicationListeners这里就是开始筛选listener,里面调用了supportsEvent方法 protected boolean supportsEvent( ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) { //判断具体是什么类型的Listener GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); }
- 这里其实就是调用每个具体listener的方法,来判断是否满足给定的条件,这里我们可以确定是SpringApplication与
ApplicationStartingEvent类型参数,那我们就明确了,直接找在SpringApplication发起的并且是
ApplicationStartingEvent类型事件的监听,我们以LoggingApplicationListener为例查看
public boolean supportsEventType(ResolvableType resolvableType) { return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES); } /**我们发现 这里是listener已经定义好 它需要监听什么类型事件的集合 EVENT_TYPES 并且监听的是什么地方发生的事件的 * 集合SOURCE_TYPES。这里不一一列举了可以查看源码 。然后能找到了listener,我们就需要调用onApplicationEvent开始执行逻辑了 */
- 这里我们就可以大概了解到,springboot事件发布的过程了。其实原理就是在哪里发生的什么事。监听器呢自己定义好,我要管那里的什么事就ok了。
- 这里我们写程序的时候就可以根据这个特点自定义监听,随着spring启动过程,做各种自己想要干的事情,是不是很舒服。
- 自定义事件可以参考者篇 博客,笔者认为已经写的非常透彻了
- 属性配置不用说了 直接看第二步事件发布过程。