最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot工程啟動(dòng)順序與自定義監(jiān)聽(tīng)超詳細(xì)講解

 更新時(shí)間:2022年11月10日 16:48:21   作者:頑石九變  
這篇文章主要介紹了SpringBoot工程啟動(dòng)順序與自定義監(jiān)聽(tīng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧

SpringBoot在2.4版本以后默認(rèn)不加載bootstrap.yml配置項(xiàng)。

如果需要加載該配置項(xiàng),需要引入依賴(lài),通常Spring Cloud工程配合nacos這種配置中心或注冊(cè)中心使用時(shí),需要引入該依賴(lài)。

SpringBoot單體工程無(wú)需引入該依賴(lài),所有配置放在application.yml中即可。

<!-- bootstrap 啟動(dòng)器 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

配置項(xiàng)

SpringBoot工程在啟動(dòng)時(shí),會(huì)通過(guò)SpringFactoriesLoader檢索META-INF/spring.factories文件,并加載其中的配置項(xiàng)。

常見(jiàn)的配置項(xiàng)有如下幾種:

  • ApplicationContextInitializer:為在ApplicationContext執(zhí)行refresh之前,調(diào)用ApplicationContextInitializer的initialize()方法,對(duì)ApplicationContext做進(jìn)一步的設(shè)置和處理
  • SpringApplicationRunListener:SpringBoot只提供一個(gè)實(shí)現(xiàn)類(lèi)EventPublishingRunListener,在SpringBoot啟動(dòng)過(guò)程中,負(fù)責(zé)注冊(cè)ApplicationListener監(jiān)聽(tīng)器,在不同的時(shí)點(diǎn)發(fā)布不同的事件類(lèi)型,如果有哪些ApplicationListener的實(shí)現(xiàn)類(lèi)監(jiān)聽(tīng)了這些事件,則可以接收并處理
  • ApplicationListener:事件監(jiān)聽(tīng)器,其作用可以理解為在SpringApplicationRunListener發(fā)布通知事件時(shí),由ApplicationListener負(fù)責(zé)接收

啟動(dòng)順序說(shuō)明

構(gòu)造函數(shù):初始化web容器,加載ApplicationContextInitializer的實(shí)現(xiàn)類(lèi)并將其實(shí)例化,加載ApplicationListener的實(shí)現(xiàn)類(lèi)并將其實(shí)例化

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// 初始化web容器類(lèi)型,默認(rèn)SERVLET,如果存在org.springframework.web.reactive.DispatcherHandler,則是REACTIVE
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	this.bootstrapRegistryInitializers = new ArrayList<>(
			getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
	//找到*META-INF/spring.factories*中聲明的所有ApplicationContextInitializer的實(shí)現(xiàn)類(lèi)并將其實(shí)例化
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	//找到*META-INF/spring.factories*中聲明的所有ApplicationListener的實(shí)現(xiàn)類(lèi)并將其實(shí)例化
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	//獲得當(dāng)前執(zhí)行main方法的類(lèi)對(duì)象
	this.mainApplicationClass = deduceMainApplicationClass();
}

啟動(dòng)方法

public ConfigurableApplicationContext run(String... args) {
	long startTime = System.nanoTime();
	// 創(chuàng)建bootstrap上下文
	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
	ConfigurableApplicationContext context = null;
	configureHeadlessProperty();
		//通過(guò)*SpringFactoriesLoader*檢索*META-INF/spring.factories*,
		//找到聲明的所有SpringApplicationRunListener的實(shí)現(xiàn)類(lèi)并將其實(shí)例化,
		//之后逐個(gè)調(diào)用其started()方法,廣播SpringBoot要開(kāi)始執(zhí)行了。
	SpringApplicationRunListeners listeners = getRunListeners(args);
	listeners.starting(bootstrapContext, this.mainApplicationClass);
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		//創(chuàng)建并配置當(dāng)前SpringBoot應(yīng)用將要使用的Environment(包括配置要使用的PropertySource以及Profile),
		//并遍歷調(diào)用所有的SpringApplicationRunListener的environmentPrepared()方法,廣播Environment準(zhǔn)備完畢。
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		//決定是否打印Banner
		configureIgnoreBeanInfo(environment);
		Banner printedBanner = printBanner(environment);
		//根據(jù)webApplicationType的值來(lái)決定創(chuàng)建何種類(lèi)型的ApplicationContext對(duì)象
		//如果是SERVLET環(huán)境,則創(chuàng)建AnnotationConfigServletWebServerApplicationContext
		//如果是REACTIVE環(huán)境,則創(chuàng)建AnnotationConfigReactiveWebServerApplicationContext
		//否則創(chuàng)建AnnotationConfigApplicationContext
		context = createApplicationContext();
		context.setApplicationStartup(this.applicationStartup);
		//為ApplicationContext加載environment,之后逐個(gè)執(zhí)行ApplicationContextInitializer的initialize()方法來(lái)進(jìn)一步封裝ApplicationContext,
		//并調(diào)用所有的SpringApplicationRunListener的contextPrepared()方法,【EventPublishingRunListener只提供了一個(gè)空的contextPrepared()方法】,
		//之后初始化IoC容器,并調(diào)用SpringApplicationRunListener的contextLoaded()方法,廣播ApplicationContext的IoC加載完成,
		//這里就包括通過(guò)**@EnableAutoConfiguration**導(dǎo)入的各種自動(dòng)配置類(lèi)。
		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
		//初始化所有自動(dòng)配置類(lèi),調(diào)用ApplicationContext的refresh()方法
		refreshContext(context);
		//目前該方法為空
		afterRefresh(context, applicationArguments);
		Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
		}
		//調(diào)用所有的SpringApplicationRunListener的started()方法,廣播SpringBoot已經(jīng)完成了ApplicationContext初始化的全部過(guò)程。
		listeners.started(context, timeTakenToStartup);
		//遍歷所有注冊(cè)的ApplicationRunner和CommandLineRunner,并執(zhí)行其run()方法。
		//該過(guò)程可以理解為是SpringBoot完成ApplicationContext初始化前的最后一步工作,
		//我們可以實(shí)現(xiàn)自己的ApplicationRunner或者CommandLineRunner,來(lái)對(duì)SpringBoot的啟動(dòng)過(guò)程進(jìn)行擴(kuò)展。
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, listeners);
		throw new IllegalStateException(ex);
	}
	try {
		Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
		listeners.ready(context, timeTakenToReady);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

擴(kuò)展SpringApplication

我們的程序經(jīng)常需要在啟動(dòng)過(guò)程中或啟動(dòng)完成后做一些額外的邏輯處理,那么可以通過(guò)以下三種方式處理:

1、創(chuàng)建ApplicationContextInitializer的實(shí)現(xiàn)類(lèi)

1)創(chuàng)建實(shí)現(xiàn)類(lèi)

public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        logger.info("MyApplicationContextInitializer, {}", applicationContext.getApplicationName());
    }
}

2)配置META-INF/spring.factories

org.springframework.context.ApplicationContextInitializer=\
  com.hsoft.demo.MyApplicationContextInitializer

3)或者修改啟動(dòng)方法,調(diào)用addInitializers添加

public static void main(String[] args) {
    SpringApplication springApplication = new SpringApplication(Application.class);
    springApplication.addInitializers(new MyApplicationContextInitializer());
    springApplication.run(args);
}

2、創(chuàng)建ApplicationListener的實(shí)現(xiàn)類(lèi)

ApplicationListener也有兩種方式,首先創(chuàng)建實(shí)現(xiàn)類(lèi),然后修改啟動(dòng)方法,調(diào)用addListeners添加,或者直接添加注解@Component

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        logger.info("MyApplicationListener,{}",event.toString());
    }
}
public static void main(String[] args) {
    SpringApplication springApplication = new SpringApplication(Application.class);
    springApplication.addListeners(new MyApplicationListener());
    springApplication.run(args);
}

也可以通過(guò)配置META-INF/spring.factories實(shí)現(xiàn)

# Application Listeners
org.springframework.context.ApplicationListener=\
com.hsoft.demo.MyApplicationListener

推薦直接使用注解@ComponentaddListeners()方式,如果配置META-INF/spring.factories,因bootstrap配置分開(kāi)加載所以監(jiān)聽(tīng)程序會(huì)被觸發(fā)兩次

3、創(chuàng)建ApplicationRunner和CommandLineRunner的實(shí)現(xiàn)類(lèi)

只需創(chuàng)建一個(gè)實(shí)現(xiàn)類(lèi)型,并在實(shí)現(xiàn)類(lèi)上面增加注解@Component即可

@Component
public class MyApplicationRunner implements ApplicationRunner {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("MyApplicationRunner, {}",args.getOptionNames());
    }
}
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void run(String... args) throws Exception {
        logger.info("MyCommandLineRunner, {}", args);
    }
}

生成war包在web容器(tomcat)中部署

如果SpringBoot工程要在Tomcat中部署,需要通過(guò)如下操作:

1、修改成war工程

2、嵌入式Tomcat依賴(lài)scope指定provided

3、編寫(xiě)SpringBootServletInitializer類(lèi)子類(lèi),并重寫(xiě)configure方法

/**
 * web容器中進(jìn)行部署
 *
 */
public class MyServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MyApplication.class);
    }
}

到此這篇關(guān)于SpringBoot工程啟動(dòng)順序與自定義監(jiān)聽(tīng)超詳細(xì)講解的文章就介紹到這了,更多相關(guān)SpringBoot工程啟動(dòng)順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

肃宁县| 习水县| 卓尼县| 娄烦县| 桃源县| 会泽县| 山丹县| 宜章县| 稻城县| 汝州市| 化德县| 婺源县| 赫章县| 无为县| 大化| 军事| 车险| 开封市| 托克托县| 水城县| 博爱县| 清河县| 海南省| 汨罗市| 肇庆市| 东方市| 长岛县| 新宁县| 沙坪坝区| 友谊县| 湘西| 禄丰县| 滁州市| 丰县| 土默特右旗| 绍兴县| 衡东县| 容城县| 上杭县| 乐亭县| 临夏县|