国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent,【Spring Boot2.X】,spring boot,事件發(fā)布

Pre

Spring Boot - Application Events 的發(fā)布順序_ApplicationEnvironmentPreparedEvent


概述

Spring Boot 的廣播機(jī)制是基于觀察者模式實(shí)現(xiàn)的,它允許在 Spring 應(yīng)用程序中發(fā)布和監(jiān)聽事件。這種機(jī)制的主要目的是為了實(shí)現(xiàn)解耦,使得應(yīng)用程序中的不同組件可以獨(dú)立地改變和復(fù)用邏輯,而無需直接進(jìn)行通信。

在 Spring Boot 中,事件發(fā)布和監(jiān)聽的機(jī)制是通過 ApplicationEvent、ApplicationListener 以及事件發(fā)布者(ApplicationEventPublisher)來實(shí)現(xiàn)的。其中,ApplicationEvent 是所有自定義事件的基礎(chǔ),自定義事件需要繼承自它。

ApplicationListener 是監(jiān)聽特定事件并做出響應(yīng)的接口,開發(fā)者可以通過實(shí)現(xiàn)該接口來定義自己的監(jiān)聽器。事件發(fā)布者(通常由 Spring 的 ApplicationContext 擔(dān)任)負(fù)責(zé)發(fā)布事件。


Code

package com.artisan.event;

import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.context.ApplicationListener;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class AvailabilityChangeListener implements ApplicationListener<AvailabilityChangeEvent> {
    /**
     * AvailabilityChangeEvent 當(dāng)應(yīng)用程序的“活動(dòng)”和“就緒”狀態(tài)發(fā)生更改時(shí)觸發(fā)。
     * 例如,當(dāng)應(yīng)用程序從 LivenessState.CORRECT to 指示應(yīng)用程序處于活動(dòng)狀態(tài),從 ReadinessState.ACCEPTING_TRAFFIC to 指示應(yīng)用程序已準(zhǔn)備好處理傳入請(qǐng)求時(shí),可以觸發(fā)它
     *
     * 為了處理 AvailabilityChangeEvent ,我們可以通過實(shí)現(xiàn) AvailabilityChangeEvent 作為泛型類型的 ApplicationListener 接口來創(chuàng)建一個(gè)自定義事件偵聽器。
     * 此偵聽器可以在主應(yīng)用程序類中手動(dòng)注冊(cè)
     *
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(AvailabilityChangeEvent event) {
        System.out.println("--------------------> Handling AvailabilityChangeEvent here!");
    }
}
    

如何使用呢?

方式一:

@SpringBootApplication
public class LifeCycleApplication {

    /**
     * 除了手工add , 在 META-INF下面 的 spring.factories 里增加
     * org.springframework.context.ApplicationListener=自定義的listener 也可以
     *
     * @param args
     */
    public static void main(String[] args) {
      
        SpringApplication springApplication = new SpringApplication(LifeCycleApplication.class);

        // 在執(zhí)行 Spring Boot 應(yīng)用程序時(shí),我們可以用來 AvailabilityChangeEvent 更新狀態(tài)。任何應(yīng)用程序組件都可以發(fā)送此類事件來更新應(yīng)用程序的狀態(tài)
       springApplication.addListeners(new AvailabilityChangeListener());

       springApplication.run(args);
    }


}

方式二: 通過spring.factories 配置

Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent,【Spring Boot2.X】,spring boot,事件發(fā)布

org.springframework.context.ApplicationListener=\
com.artisan.event.AvailabilityChangeListener

運(yùn)行日志

Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent,【Spring Boot2.X】,spring boot,事件發(fā)布


源碼分析

首先main方法啟動(dòng)入口

SpringApplication.run(LifeCycleApplication.class, args);

跟進(jìn)去

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

繼續(xù)

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

這里首先關(guān)注 new SpringApplication(primarySources)

new SpringApplication(primarySources)

	/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified primary sources (see {@link SpringApplication class-level}
	 * documentation for details. The instance can be customized before calling
	 * {@link #run(String...)}.
	 * @param resourceLoader the resource loader to use
	 * @param primarySources the primary bean sources
	 * @see #run(Class, String[])
	 * @see #setSources(Set)
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	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();
		this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

聚焦 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));


run

繼續(xù)run

// 開始啟動(dòng)Spring應(yīng)用程序
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch(); // 創(chuàng)建一個(gè)計(jì)時(shí)器
    stopWatch.start(); // 開始計(jì)時(shí)
    
    DefaultBootstrapContext bootstrapContext = createBootstrapContext(); // 創(chuàng)建引導(dǎo)上下文
    ConfigurableApplicationContext context = null; // Spring應(yīng)用上下文,初始化為null
    
    configureHeadlessProperty(); // 配置無頭屬性(如:是否在瀏覽器中運(yùn)行)

    SpringApplicationRunListeners listeners = getRunListeners(args); // 獲取運(yùn)行監(jiān)聽器
    listeners.starting(bootstrapContext, this.mainApplicationClass); // 通知監(jiān)聽器啟動(dòng)過程開始
    
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 創(chuàng)建應(yīng)用參數(shù)
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 預(yù)備環(huán)境
        configureIgnoreBeanInfo(environment); // 配置忽略BeanInfo
        
        Banner printedBanner = printBanner(environment); // 打印Banner
        context = createApplicationContext(); // 創(chuàng)建應(yīng)用上下文
        context.setApplicationStartup(this.applicationStartup); // 設(shè)置應(yīng)用啟動(dòng)狀態(tài)
        
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 準(zhǔn)備上下文
        refreshContext(context); // 刷新上下文,執(zhí)行Bean的生命周期
        afterRefresh(context, applicationArguments); // 刷新后的操作
        
        stopWatch.stop(); // 停止計(jì)時(shí)
        if (this.logStartupInfo) { // 如果需要記錄啟動(dòng)信息
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); // 記錄啟動(dòng)信息
        }
        listeners.started(context); // 通知監(jiān)聽器啟動(dòng)完成
        
        callRunners(context, applicationArguments); // 調(diào)用Runner
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, listeners); // 處理運(yùn)行失敗
        throw new IllegalStateException(ex); // 拋出異常
    }

    try {
        listeners.running(context); // 通知監(jiān)聽器運(yùn)行中
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, null); // 處理運(yùn)行失敗
        throw new IllegalStateException(ex); // 拋出異常
    }
    return context; // 返回應(yīng)用上下文
}

我們重點(diǎn)看

listeners.started(context);

繼續(xù)

void started(ConfigurableApplicationContext context) {
		doWithListeners("spring.boot.application.started", (listener) -> listener.started(context));
	}


繼續(xù) listener.started(context)

 	@Override
	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}

關(guān)注AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);

 

請(qǐng)關(guān)注: getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

繼續(xù)

 public static <S extends AvailabilityState> void publish(ApplicationContext context, S state) {
		Assert.notNull(context, "Context must not be null");
		publish(context, context, state);
	}

public static <S extends AvailabilityState> void publish(ApplicationEventPublisher publisher, Object source,
			S state) {
		Assert.notNull(publisher, "Publisher must not be null");
		publisher.publishEvent(new AvailabilityChangeEvent<>(source, state));
	}
/**
 * 發(fā)布一個(gè)事件,這個(gè)事件可以被訂閱者處理。
 *
 * @param event 事件對(duì)象,不能為null
 * @param eventType 事件類型,用于類型匹配和事件處理器的選擇
 */
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    // 斷言事件對(duì)象不能為null
    Assert.notNull(event, "Event must not be null");
    
    // 如果事件本身就是ApplicationEvent的實(shí)例,直接使用
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    // 否則,使用PayloadApplicationEvent進(jìn)行包裝
    else {
        applicationEvent = new PayloadApplicationEvent<>(this, event);
        // 如果事件類型為null,從PayloadApplicationEvent中獲取
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
        }
    }
    
    // 如果有提前注冊(cè)的事件,直接添加到列表中
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    }
    // 否則,使用ApplicationEventMulticaster進(jìn)行廣播
    else {
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }
    
    // 如果有父上下文,也發(fā)布事件
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        } else {
            this.parent.publishEvent(event);
        }
    }
}



繼續(xù)getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
		ErrorHandler errorHandler = getErrorHandler();
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			doInvokeListener(listener, event);
		}
	}
/**
 * 調(diào)用一個(gè)事件監(jiān)聽器的方法。
 *
 * @param listener 要調(diào)用的監(jiān)聽器
 * @param event 要處理的事件
 */
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        // 直接調(diào)用監(jiān)聽器的onApplicationEvent方法
        listener.onApplicationEvent(event);
    }
    catch (ClassCastException ex) {
        String msg = ex.getMessage();
        // 如果消息為null或者消息匹配事件類的預(yù)期類型,則忽略異常并記錄debug日志
        if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
            Log logger = LogFactory.getLog(getClass());
            if (logger.isTraceEnabled()) {
                logger.trace("Non-matching event type for listener: " + listener, ex);
            }
        }
        // 否則,拋出異常
        else {
            throw ex;
        }
    }
}

繼續(xù) 就會(huì)調(diào)到我們自己的業(yè)務(wù)邏輯了

   @Override
    public void onApplicationEvent(AvailabilityChangeEvent event) {
        System.out.println("--------------------> Handling AvailabilityChangeEvent here!");
    }

Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent,【Spring Boot2.X】,spring boot,事件發(fā)布文章來源地址http://www.zghlxwxcb.cn/news/detail-813667.html

到了這里,關(guān)于Spring Boot - Application Events 的發(fā)布順序_AvailabilityChangeEvent的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Spring Boot - Application Events 同步 VS 異步 發(fā)布訂閱事件實(shí)戰(zhàn)

    Spring Boot - Application Events 同步 VS 異步 發(fā)布訂閱事件實(shí)戰(zhàn)

    Spring Boot - Application Events 的發(fā)布順序_ApplicationStartingEvent Spring Boot - Application Events 的發(fā)布順序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的發(fā)布順序_ApplicationContextInitializedEvent Spring Boot - Application Events 的發(fā)布順序_ApplicationPreparedEvent Spring Boot - Application Events 的發(fā)布順

    2024年01月17日
    瀏覽(21)
  • 聊聊Spring Boot配置文件:優(yōu)先級(jí)順序、加載順序、bootstrap.yml與application.yml區(qū)別詳解

    在 Spring Boot 中,配置文件的優(yōu)先級(jí)順序是: application-{profile}.yml ( application-{profile}.properties ) application.yml ( application.properties ) bootstrap.yml ( bootstrap.properties )。其中, {profile} 表示不同的環(huán)境配置,如 dev 、 test 、 prod 等。 優(yōu)先級(jí)從高到低,高優(yōu)先級(jí)的配置覆蓋低優(yōu)先級(jí)

    2024年01月25日
    瀏覽(31)
  • 【SpringBoot筆記34】Spring Events事件驅(qū)動(dòng)編程之事件的發(fā)布和監(jiān)聽操作

    這篇文章,主要介紹Spring Events事件驅(qū)動(dòng)編程之事件的發(fā)布和監(jiān)聽操作。 目錄 一、基于接口實(shí)現(xiàn) 1.1、自定義事件 1.2、主動(dòng)發(fā)布事件 1.3、監(jiān)聽事件對(duì)象

    2024年02月16日
    瀏覽(25)
  • Spring Boot中使用Server-Sent Events (SSE) 實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)推送教程

    Server-Sent Events (SSE) 是HTML5引入的一種輕量級(jí)的服務(wù)器向?yàn)g覽器客戶端單向推送實(shí)時(shí)數(shù)據(jù)的技術(shù)。在Spring Boot框架中,我們可以很容易地集成并利用SSE來實(shí)現(xiàn)實(shí)時(shí)通信。 ???????? 在Spring Boot項(xiàng)目中,無需額外引入特定的依賴,因?yàn)镾pring Web MVC模塊已經(jīng)內(nèi)置了對(duì)SSE的支持。 輔助

    2024年03月18日
    瀏覽(31)
  • 【Spring Boot】application 配置文件(2)

    【Spring Boot】application 配置文件(2)

    server.servlet.session. timeout =1800 ?定義了 HTTP 會(huì)話的超時(shí)時(shí)間,單位是秒,在此設(shè)置中,會(huì)話的超時(shí)時(shí)間被設(shè)置為 1800秒 即30分鐘。這意味著 ,如果30分鐘內(nèi)用戶沒有與服務(wù)器進(jìn)行任何活動(dòng)(如請(qǐng)求頁面),那么會(huì)話將自動(dòng)過期。 ?spring.jackson.time-zone=GMT+8 這個(gè)設(shè)置指定了jackson 庫

    2024年01月23日
    瀏覽(41)
  • Spring Boot Application.properties和yaml配置文件

    Spring Boot Application.properties和yaml配置文件

    全局配置文件能夠?qū)σ恍┠J(rèn)配置值進(jìn)行修改。Spring Boot使用一個(gè)application.properties或者application.yaml的文件作為全局配置文件,該文件存放在src/main/resource目錄或者類路徑的/config,一般會(huì)選擇resource目錄。 使用Spring Initializr方式創(chuàng)建項(xiàng)目——PropertiesDemo 單擊【Next】按鈕 添加W

    2024年01月24日
    瀏覽(25)
  • Java實(shí)戰(zhàn):Spring Boot application.yml配置文件詳解

    本文將詳細(xì)介紹Spring Boot application.yml 配置文件的使用和配置項(xiàng)。我們將探討 application.yml 文件的基本概念,以及如何使用它來配置Spring Boot應(yīng)用程序的各個(gè)方面。此外,我們將通過具體的示例來展示如何配置不同的Spring Boot組件,如數(shù)據(jù)源、數(shù)據(jù)庫、緩存、郵件服務(wù)等。本文適

    2024年04月24日
    瀏覽(24)
  • Spring Boot學(xué)習(xí)隨筆-第一個(gè)SpringBoot項(xiàng)目快速啟動(dòng)(org.springframework.boot、@SpringBootApplication、application.yml)

    Spring Boot學(xué)習(xí)隨筆-第一個(gè)SpringBoot項(xiàng)目快速啟動(dòng)(org.springframework.boot、@SpringBootApplication、application.yml)

    學(xué)習(xí)視頻:【編程不良人】2021年SpringBoot最新最全教程 創(chuàng)建第一個(gè)Module 環(huán)境要求 jdk1.8+ maven3.2+ Spring Framework 5.x+ Tomcat 9.0+ IDEA 2021 自動(dòng)保存刷新pom 在resources下添加application.yml文件后,即可啟動(dòng)springboot應(yīng)用 由于tomcat內(nèi)嵌在springboot里面了,所以我們?cè)谛薷亩丝谔?hào)等設(shè)置也在配置

    2024年02月05日
    瀏覽(38)
  • 【Spring Boot基礎(chǔ)】解決ERROR org.springframework.boot.SpringApplication -- Application run failed報(bào)錯(cuò)問題

    【Spring Boot基礎(chǔ)】解決ERROR org.springframework.boot.SpringApplication -- Application run failed報(bào)錯(cuò)問題

    一、問題描述 在學(xué)習(xí)SpringBoot配置profile的時(shí)候,.yml文件內(nèi)容明明跟老師敲的一模一樣,但還是報(bào)錯(cuò)ERROR org.springframework.boot.SpringApplication -- Application run failed 原.yml文件內(nèi)容: 報(bào)錯(cuò)如下: ?二、解決方法 按照“ERROR org.springframework.boot.SpringApplication -- Application run failed”搜索答案

    2024年02月13日
    瀏覽(86)
  • spring-boot項(xiàng)目啟動(dòng)類錯(cuò)誤: 找不到或無法加載主類 com.**Application

    spring-boot項(xiàng)目啟動(dòng)類錯(cuò)誤: 找不到或無法加載主類 com.**Application

    問題:Springboot項(xiàng)目啟動(dòng)報(bào)錯(cuò):錯(cuò)誤: 找不到或無法加載主類 com.**Application 解決步驟: 1.File–Project Structure 2.Modules–選中你的項(xiàng)目–點(diǎn)擊“-”移除 3.重新導(dǎo)入:點(diǎn)擊“+”號(hào),選擇Import Module,找到項(xiàng)目所在路徑,選中要導(dǎo)入的項(xiàng)目,點(diǎn)擊OK。 選擇maven,點(diǎn)擊ok 4.重新編譯:點(diǎn)擊

    2024年04月17日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包