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

Spring中事件發(fā)布機(jī)制及流程詳解

 更新時間:2023年11月09日 08:43:48   作者:愛敲代碼的小楚  
這篇文章主要介紹了Spring中事件發(fā)布機(jī)制及流程詳解,在分析源碼的過程中,也是大量使用了事件機(jī)制,在我分析的這篇博客中,有不少地方都運(yùn)用了事件發(fā)布機(jī)制,所以本文的目的是從SpringBoot中學(xué)習(xí)到事件的發(fā)布流程,需要的朋友可以參考下

一、角色

在這里插入圖片描述

事件類

ApplicationEvent:定義事件類型
|------ApplicationContextEvent:ApplicationContext引發(fā)的事件的基類。
        |------ContextClosedEvent:容器關(guān)閉事件
        |------ContextRefreshedEvent:容器刷新事件

事件發(fā)布者

ApplicationEventPublisher:將應(yīng)用程序事件通知此應(yīng)用程序注冊的所有偵聽器。

事件監(jiān)聽者

ApplicationListener:由應(yīng)用程序事件偵聽器實(shí)現(xiàn)的接口。

事件廣播器

ApplicationEventMulticaster:
|------AbstractApplicationEventMulticaster:提供了基本的偵聽器注冊功能
        |------SimpleApplicationEventMulticaster:實(shí)現(xiàn)事件通知具體方式

二、角色負(fù)責(zé)的功能

事件廣播器

ApplicationEventMulticaster接口

定義規(guī)范:

  • 把監(jiān)聽者加入集合
  • 把監(jiān)聽者移出集合
  • 事件通知
	// 把事件事件監(jiān)聽者加入集合
 	void addApplicationListener(ApplicationListener<?> listener);
 	// 把事件事件監(jiān)聽者加入集合
    void removeApplicationListener(ApplicationListener<?> listener);
    /**
     *  最終推送時間消息也會經(jīng)過這個接口方法來處理誰該接收事件
     *
     * @param event
     */
    void multicastEvent(ApplicationEvent event);

AbstractApplicationEventMulticaster抽象類 實(shí)現(xiàn)了:

  • 創(chuàng)建集合用于存儲事件監(jiān)聽者(Listener)
  • 實(shí)現(xiàn)將事件監(jiān)聽者(Listener)添加和移出集合的方法
  • 實(shí)現(xiàn)將符合事件的監(jiān)聽者添加入新建的集合并返回
  • 拿出集合中所有的監(jiān)聽者,根據(jù)要發(fā)生的事件判斷,該監(jiān)聽者是否感興趣
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {
	// 存放所有ApplicationListener的集合
 public final LinkedHashSet<ApplicationListener<ApplicationEvent>>
            applicationListeners =  new LinkedHashSet();

	/**
     * 方法主要是摘取符合廣播事件中的監(jiān)聽處理器,具體過濾動作在 supportsEvent 方法中。
     * @param event
     * @return
     */
 	protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event){
        LinkedList<ApplicationListener> allListeners = new LinkedList<>();
        for (ApplicationListener<ApplicationEvent> listener : applicationListeners){
            if(supportsEvent(listener, event)) allListeners.add(listener);
        }
        return allListeners;
    }
    /**
     * 監(jiān)聽器是否對該事件感興趣
     * 主要包括對 Cglib、Simple 不同實(shí)例化需要獲取目標(biāo)
     * Class,Cglib 代理類需要獲取父類的 Class,普通實(shí)例化的不需要。接下來就是通過
     * 提取接口和對應(yīng)的 ParameterizedType 和 eventClassName,方便最后確認(rèn)是否為
     * 子類和父類的關(guān)系,以此證明此事件歸這個符合的類處理。
     * @param applicationListener
     * @param event
     * @return
     */
    private boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {

        Class<? extends ApplicationListener> listenerClass = applicationListener.getClass();
        // 按照 CglibSubclassingInstantiationStrategy、
        // SimpleInstantiationStrategy 不同的實(shí)例化類型,需要判斷后獲取目標(biāo) class
        Class<?> targetClass = ClassUtils.isCglibProxyClass(listenerClass) ?
                listenerClass.getSuperclass() : listenerClass;
        Type genericInterface = targetClass.getGenericInterfaces()[0];

        Type actualTypeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
        String className = actualTypeArgument.getTypeName();

        Class<?> eventClassName;
        try {
            eventClassName = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new BeansException("wrong event class name: " + className);
        }
        // 判定此 eventClassName 對象所表示的類或接口與指定的 event.getClass() 參數(shù)所
        // 示的類或接口是否相同,或是否是其超類或超接口。
        // isAssignableFrom 是用來判斷子類和父類的關(guān)系的,或者接口的實(shí)現(xiàn)類和接口的關(guān)系的,
        // 默認(rèn)所有的類的終極父類都是 Object。如果 A.isAssignableFrom(B)結(jié)果是 true,證明 B 可以轉(zhuǎn)換成
        // 為 A,也就是 A 可以由 B 轉(zhuǎn)換而來。
        return eventClassName.isAssignableFrom(event.getClass());
    }
	......
}

SimpleApplicationEventMulticaster類 實(shí)現(xiàn)了:

  • 實(shí)現(xiàn)了事件通知(具體細(xì)節(jié)由父類完成)
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
	@Override
    public void multicastEvent(ApplicationEvent event) {
        for(final ApplicationListener listener : getApplicationListeners(event)){
            listener.onApplicationEvent(event);
        }
    }
    .......
}

事件發(fā)布者

因?yàn)檫@邊事件都是ApplicationContextEvent,Application是對Spring應(yīng)用上下的管理。所以這邊充當(dāng)事件發(fā)布者的是AbstractApplicationContext。 AbstractApplicationContext 間接實(shí)現(xiàn)ApplicationEventPublisher

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
	private ApplicationEventMulticaster applicationEventMulticaster;
	@Override
    public void refresh() throws BeansException {
    	.....
    	// 一開始就創(chuàng)建了事件廣播器
    	// 6. 初始化事件發(fā)布者
        initApplicationEventMulticaster();
	    .......
	    // 9. 發(fā)布容器刷新完成事件(發(fā)布是容器刷新事件)
        finishRefresh();
    }
    // 創(chuàng)建事件廣播器
    private void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
    private void finishRefresh() {
        publishEvent(new ContextRefreshedEvent(this));
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
        applicationEventMulticaster.multicastEvent(event);
    }
	.......
}

事件監(jiān)聽者

當(dāng)我們關(guān)心spring容器什么時候刷新,或者想在spring容器刷新的時候做一些事情。 監(jiān)聽關(guān)心的事件,主要就是在ApplicationListener中寫對應(yīng)的事件。 spring容器在刷新完容器,就會調(diào)用該方法。

public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("刷新事件(容器刷新完成):" + this.getClass().getName());
    }
}

三、使用spring中的事件機(jī)制

1.寫一個事件類(暫定我們關(guān)心的是application上下文的事件)

public class CustomEvent extends ApplicationContextEvent {

    private Long id;
    private String message;

    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public CustomEvent(Object source,Long id, String message) {
        super(source);
        this.id = id;
        this.message = message;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2.事件發(fā)布者

@Test
    public void test_event(){
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("classpath:spring.xml");

        applicationContext.publishEvent(new CustomEvent(applicationContext, 101912455552221L, "事件發(fā)布成功!"));
        //applicationContext.registerShutdownHook();
    }

3.寫對應(yīng)的監(jiān)聽者實(shí)現(xiàn)就可以了

public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("收到:" + event.getSource() + "消息;時間:" + new Date());
        System.out.println("消息:" + event.getId() + ":" + event.getMessage());
    }
}

四、整體流程

在這里插入圖片描述

到此這篇關(guān)于Spring中事件發(fā)布機(jī)制及流程詳解的文章就介紹到這了,更多相關(guān)Spring事件發(fā)布機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringCloud Hystrix-Dashboard儀表盤的實(shí)現(xiàn)

    SpringCloud Hystrix-Dashboard儀表盤的實(shí)現(xiàn)

    這篇文章主要介紹了SpringCloud Hystrix-Dashboard儀表盤的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • gradle配置國內(nèi)鏡像的實(shí)現(xiàn)

    gradle配置國內(nèi)鏡像的實(shí)現(xiàn)

    這篇文章主要介紹了gradle配置國內(nèi)鏡像的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Spring Boot自定義錯誤視圖的方法詳解

    Spring Boot自定義錯誤視圖的方法詳解

    這篇文章主要介紹了Spring Boot自定義錯誤視圖的方法詳解,需要的朋友可以參考下
    2020-08-08
  • Java向MySQL添加中文數(shù)據(jù)數(shù)據(jù)庫顯示亂碼的解決方案

    Java向MySQL添加中文數(shù)據(jù)數(shù)據(jù)庫顯示亂碼的解決方案

    在用springboot做項(xiàng)目時,由于重新安裝了本地Mysql數(shù)據(jù)庫(5.7版本)在前臺向數(shù)據(jù)庫插入和更新數(shù)據(jù)可的時候,涉及中文的時候在數(shù)據(jù)庫一直顯示異常,所以本文給大家介紹了相關(guān)的解決方案,需要的朋友可以參考下
    2024-02-02
  • Java中Map.getOrDefault()方法舉例詳解

    Java中Map.getOrDefault()方法舉例詳解

    這篇文章主要介紹了Java?8中Map接口的getOrDefault()方法,該方法在獲取鍵值對時,如果鍵不存在則返回默認(rèn)值,文中通過一個統(tǒng)計(jì)網(wǎng)站用戶點(diǎn)擊次數(shù)的應(yīng)用場景,詳細(xì)展示了getOrDefault()的用法,需要的朋友可以參考下
    2025-02-02
  • IntelliJIDEA中實(shí)現(xiàn)SpringBoot多實(shí)例運(yùn)行的兩種方式

    IntelliJIDEA中實(shí)現(xiàn)SpringBoot多實(shí)例運(yùn)行的兩種方式

    在微服務(wù)開發(fā)中,經(jīng)常需要同時啟動多個服務(wù)實(shí)例進(jìn)行測試或模擬集群環(huán)境,?IntelliJ?IDEA?作為Java開發(fā)者常用工具,提供了靈活的多實(shí)例啟動支持,本文將詳細(xì)介紹如何通過修改配置?和批量啟動?兩種方式實(shí)現(xiàn)SpringBoot多實(shí)例運(yùn)行,并解決常見問題,需要的朋友可以參考下
    2025-03-03
  • jcl與jul?log4j1?log4j2?logback日志系統(tǒng)機(jī)制及集成原理

    jcl與jul?log4j1?log4j2?logback日志系統(tǒng)機(jī)制及集成原理

    這篇文章主要介紹了jcl與jul?log4j1?log4j2?logback的集成原理,Apache?Commons-logging?通用日志框架與日志系統(tǒng)的機(jī)制,有需要的朋友可以借鑒參考下
    2022-03-03
  • java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時間

    java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時間

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)短信驗(yàn)證碼5分鐘有效時間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Nacos配置中心與本地代碼工程配置文件之間的優(yōu)先級關(guān)系詳解

    Nacos配置中心與本地代碼工程配置文件之間的優(yōu)先級關(guān)系詳解

    本文介紹了Spring Cloud生態(tài)中配置加載原理,強(qiáng)調(diào)Nacos遠(yuǎn)程配置優(yōu)先級高于本地`application.yml`但低于命令行和環(huán)境變量,覆蓋了多環(huán)境配置、動態(tài)刷新配置及安全配置外置等應(yīng)用場景,對比了Nacos配置中心與本地配置文件的優(yōu)缺點(diǎn),并給出最佳實(shí)踐建議
    2026-04-04
  • java實(shí)現(xiàn)斗地主游戲

    java實(shí)現(xiàn)斗地主游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)斗地主游戲,洗牌、發(fā)牌、看牌,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評論

龙岩市| 阜城县| 年辖:市辖区| 集贤县| 南康市| 高淳县| 丰台区| 泗水县| 周至县| 阿城市| 新宁县| 旬阳县| 兴安盟| 郓城县| 贵港市| 晴隆县| 城固县| 永年县| 张北县| 白城市| 沈阳市| 无为县| 汶上县| 景宁| 锡林郭勒盟| 渭源县| 北辰区| 恭城| 白水县| 武定县| 丰都县| 烟台市| 苏尼特右旗| 大新县| 浦城县| 尼玛县| 宣武区| 宁海县| 乐东| 丹阳市| 哈巴河县|