欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringApplicationRunListener監(jiān)聽器源碼詳解

 更新時間:2023年11月15日 09:20:25   作者:立小研先森  
這篇文章主要介紹了SpringApplicationRunListener監(jiān)聽器源碼詳解,springboot提供了兩個類SpringApplicationRunListeners、SpringApplicationRunListener(EventPublishingRunListener),spring框架還提供了一個ApplicationListener接口,需要的朋友可以參考下

前言

springboot提供了兩個類SpringApplicationRunListeners、SpringApplicationRunListener(EventPublishingRunListener),spring框架還提供了一個ApplicationListener接口,那么這幾個類或接口的關(guān)系又是如何呢?

首先SpringApplicationRunListeners類是SpringApplicationRunListener接口的代理類,可以批量調(diào)用SpringApplicationRunListener接口方法,SpringApplicationRunListener接口只有一個實現(xiàn)類EventPublishingRunListener,其有一個屬性SimpleApplicationEventMulticaster,SimpleApplicationEventMulticaster即是一個ApplicationListener監(jiān)聽器接口的代理實現(xiàn)類,可以批量的執(zhí)行監(jiān)聽器的onApplicationEvent方法。

1.SpringApplicationRunListener接口源碼

SpringApplicationRunListener是對org.springframework.boot.SpringApplication類的run方法進行監(jiān)聽,SpringApplicationRunListener實現(xiàn)類是通過SpringFactoriesLoader類加載(即springboot SPI);并且需要聲明一個包含SpringApplication實例及String[]的參數(shù)構(gòu)造方法。

public interface SpringApplicationRunListener {
	/**
	 * 當run方法第一次啟動時立即調(diào)用,可用于非常早期的初始化
	 */
	default void starting() {
	}
	/**
	 * 在ApplicationContext創(chuàng)建之前,一旦環(huán)境environment準備好就調(diào)用。
	 * @param environment the environment
	 */
	default void environmentPrepared(ConfigurableEnvironment environment) {
	}
	/**
	 * 在資源(可以理解為配置主類)被加載完成之前,一旦ApplicationContext被創(chuàng)建并準備好就立馬調(diào)用,
	 * @param context the application context
	 */
	default void contextPrepared(ConfigurableApplicationContext context) {
	}
	/**
	 * 在資源加載完成之后,但在刷新之前調(diào)用
	 * @param context the application context
	 */
	default void contextLoaded(ConfigurableApplicationContext context) {
	}
	/**
	 * 上下文已刷新,應(yīng)用程序已啟動,但是CommandLineRunner和ApplicationRunner尚未調(diào)用。
	 * @param context the application context.
	 * @since 2.0.0
	 */
	default void started(ConfigurableApplicationContext context) {
	}
	/**
	 * 當ApplicationContext已經(jīng)refresh且所有的CommandLineRunner和ApplicationRunner都已被調(diào)用時,在run方法完成之前立即調(diào)用。
	 * @param context the application context.
	 * @since 2.0.0
	 */
	default void running(ConfigurableApplicationContext context) {
	}
	/**
	 * 在運行應(yīng)用程序時發(fā)生故障時調(diào)用
	 * @param context 應(yīng)用程序上下文,可能為null(在應(yīng)用程序上下文創(chuàng)建之前)
	 * @param exception the failure
	 * @since 2.0.0
	 */
	default void failed(ConfigurableApplicationContext context, Throwable exception) {
	}

2.EventPublishingRunListener

SpringApplicationRunListener接口唯一實現(xiàn)類EventPublishingRunListener

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
	//啟動類實例對象
	private final SpringApplication application;
	//參數(shù)
	private final String[] args;
	//ApplicationListener監(jiān)聽器接口代理廣播類
	private final SimpleApplicationEventMulticaster initialMulticaster;
	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
    //獲取應(yīng)用程序的監(jiān)聽器類,并循環(huán)添加到代理類的監(jiān)聽器助手屬性對象中
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}
}

其中application.getListeners()獲取通過SPI方式定義的所有ApplicationListener監(jiān)聽器接口定義的監(jiān)聽器類,其初始化是在SpringApplication類中通過構(gòu)造函數(shù)的方式,如下:

//監(jiān)聽器對象集合
private List<ApplicationListener<?>> listeners;

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
  	//通過SPI方式初始化應(yīng)用程序初始化器
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//通過SPI方式獲取ApplicationListener監(jiān)聽器
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

spring.factories配置文件:

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

3.SpringApplicationRunListeners

SpringApplicationRunListener接口實現(xiàn)類集合類SpringApplicationRunListeners

class SpringApplicationRunListeners {

	private final Log log;
	//存儲SpringApplicationRunListener監(jiān)聽器集合
	private final List<SpringApplicationRunListener> listeners;

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

4.獲取SpringApplicationRunListeners對象

org.springframework.boot.SpringApplication#run(java.lang.String…)方法中通過SPI方式獲取SpringApplicationRunListeners對象

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
    //通過SPI方式獲取SpringApplicationRunListener監(jiān)聽器對象集合
		SpringApplicationRunListeners listeners = getRunListeners(args);
    //啟動監(jiān)聽器,傳遞ApplicationStartingEvent事件
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      //environment準備好之后調(diào)用監(jiān)聽器environmentPrepared方法
      //傳遞ApplicationEnvironmentPreparedEvent事件
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
      //資源加載之前調(diào)用監(jiān)聽器的contextPrepared方法,傳遞ApplicationContextInitializedEvent事件
      //資源加載之后,refresh方法調(diào)用之前調(diào)用監(jiān)聽器的contextLoaded方法,傳遞ApplicationPreparedEvent事件
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
      //應(yīng)用程序refresh之后調(diào)用,傳遞ApplicationStartedEvent事件
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
      //應(yīng)用程序啟動過程中出現(xiàn)異常調(diào)用failed方法
      //傳遞ApplicationFailedEvent事件
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}
		try {
      //在應(yīng)用程序run方法運行結(jié)束之前調(diào)用,傳遞ApplicationReadyEvent事件
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
	//通過SPI方式獲取SpringApplicationRunListener接口實現(xiàn)類,并創(chuàng)建SpringApplicationRunListeners集合類
	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}

spring.factories配置文件如下:

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

到此這篇關(guān)于SpringApplicationRunListener監(jiān)聽器源碼詳解的文章就介紹到這了,更多相關(guān)SpringApplicationRunListener監(jiān)聽器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分享7款開源Java反編譯工具

    分享7款開源Java反編譯工具

    今天我們要來分享一些關(guān)于Java的反編譯工具,反編譯聽起來是一個非常高上大的技術(shù)詞匯,通俗的說,反編譯是一個對目標可執(zhí)行程序進行逆向分析,從而得到原始代碼的過程。尤其是像.NET、Java這樣的運行在虛擬機上的編程語言,更容易進行反編譯得到源代碼
    2014-09-09
  • Java Map.entry案例詳解

    Java Map.entry案例詳解

    這篇文章主要介紹了Java Map.entry案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在

    mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在

    這篇文章主要介紹了mybatis批量添加,批量更新之前如何判斷是否已經(jīng)存在,具有很好的參考價值,希望對的有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 生成8位隨機不重復(fù)的數(shù)字編號的方法

    生成8位隨機不重復(fù)的數(shù)字編號的方法

    生成隨機不重復(fù)的數(shù)字編號在某些情況下也會用到,本文以生成8位隨機不重復(fù)的數(shù)字編號為例與大家分享下具體的實現(xiàn)過程,感興趣的朋友可以參考下
    2013-09-09
  • Springboot簡單熱部署實現(xiàn)步驟解析

    Springboot簡單熱部署實現(xiàn)步驟解析

    這篇文章主要介紹了Springboot簡單熱部署實現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-12-12
  • Spring中的@ExceptionHandler注解詳解與應(yīng)用示例

    Spring中的@ExceptionHandler注解詳解與應(yīng)用示例

    本文詳細介紹了Spring框架中的@ExceptionHandler注解的用法,包括基本用法、全局異常處理、結(jié)合@ResponseStatus注解以及返回值類型,通過示例展示了如何使用@ExceptionHandler注解處理不同類型的異常,并提供定制化的異常處理響應(yīng),需要的朋友可以參考下
    2024-11-11
  • Java 遍歷 String 字符串所有字符的操作

    Java 遍歷 String 字符串所有字符的操作

    這篇文章主要介紹了Java 遍歷 String 字符串所有字符的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java中正則表達式匹配過程實例詳解

    Java中正則表達式匹配過程實例詳解

    正則匹配即是在給定字符串中查找符合正則表達式的字符,下面這篇文章主要給大家介紹了關(guān)于Java中正則表達式匹配過程的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • spring boot動態(tài)切換數(shù)據(jù)源的實現(xiàn)

    spring boot動態(tài)切換數(shù)據(jù)源的實現(xiàn)

    這篇文章主要介紹了spring boot動態(tài)切換數(shù)據(jù)源的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • HashMap鏈表與紅黑樹轉(zhuǎn)換詳解

    HashMap鏈表與紅黑樹轉(zhuǎn)換詳解

    這篇文章主要介紹了HashMap鏈表與紅黑樹轉(zhuǎn)換詳解,HashMap是Java中的一種數(shù)據(jù)結(jié)構(gòu),它實現(xiàn)了Map接口,提供了鍵值對的存儲和檢索功能,它基于哈希表的原理,通過將鍵映射到哈希表中的位置來存儲和獲取值,從而實現(xiàn)了快速的查找和插入操作,需要的朋友可以參考下
    2023-11-11

最新評論