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

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

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

一、角色

在這里插入圖片描述

事件類

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

事件發(fā)布者

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

事件監(jiān)聽者

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

事件廣播器

ApplicationEventMulticaster:
|------AbstractApplicationEventMulticaster:提供了基本的偵聽器注冊功能
        |------SimpleApplicationEventMulticaster:實現(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抽象類 實現(xiàn)了:

  • 創(chuàng)建集合用于存儲事件監(jiān)聽者(Listener)
  • 實現(xiàn)將事件監(jiān)聽者(Listener)添加和移出集合的方法
  • 實現(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 不同實例化需要獲取目標(biāo)
     * Class,Cglib 代理類需要獲取父類的 Class,普通實例化的不需要。接下來就是通過
     * 提取接口和對應(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 不同的實例化類型,需要判斷后獲取目標(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)系的,或者接口的實現(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類 實現(xiàn)了:

  • 實現(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ā)布者

因為這邊事件都是ApplicationContextEvent,Application是對Spring應(yīng)用上下的管理。所以這邊充當(dāng)事件發(fā)布者的是AbstractApplicationContext。 AbstractApplicationContext 間接實現(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中的事件機制

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)聽者實現(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ā)布機制及流程詳解的文章就介紹到這了,更多相關(guān)Spring事件發(fā)布機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jmerte分布式壓測及分布式壓測配置教程

    Jmerte分布式壓測及分布式壓測配置教程

    這篇文章主要介紹了Jmerte分布式壓測及分布式壓測配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • 一文總結(jié)RabbitMQ中的消息確認(rèn)機制

    一文總結(jié)RabbitMQ中的消息確認(rèn)機制

    RabbitMQ消息確認(rèn)機制指的是在消息傳遞過程中,發(fā)送方發(fā)送消息后,接收方需要對消息進行確認(rèn),以確保消息被正確地接收和處理,本文為大家整理了RabbitMQ中的消息確認(rèn)機制,需要的可以參考一下
    2023-06-06
  • 解決Feign配置RequestContextHolder.getRequestAttributes()為null的問題

    解決Feign配置RequestContextHolder.getRequestAttributes()為null的問題

    這篇文章主要介紹了解決Feign配置RequestContextHolder.getRequestAttributes()為null的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringCloud灰度發(fā)布的設(shè)計與實現(xiàn)詳解

    SpringCloud灰度發(fā)布的設(shè)計與實現(xiàn)詳解

    這篇文章主要介紹了SpringCloud灰度發(fā)布的設(shè)計與實現(xiàn)詳解,灰度從字面意思理解就是存在于黑與白之間的一個平滑過渡的區(qū)域,所以說對于互聯(lián)網(wǎng)產(chǎn)品來說,上線和未上線就是黑與白之分,而實現(xiàn)未上線功能平穩(wěn)過渡的一種方式就叫做灰度發(fā)布,需要的朋友可以參考下
    2023-09-09
  • IDEA修改生成jar包名字的兩種方法實現(xiàn)

    IDEA修改生成jar包名字的兩種方法實現(xiàn)

    本文主要介紹了IDEA修改生成jar包名字的兩種方法實現(xiàn),通過簡單的步驟,您可以修改項目名稱并在打包時使用新的名稱,具有一定的參考價值,感興趣的可以了解下
    2023-08-08
  • 深入理解Java中的Lambda表達式

    深入理解Java中的Lambda表達式

    這篇文章主要介紹了深入理解Java中的Lambda表達式,Lambda在各編程語言中都是非常重要的特性,而Java中則加入得有些太晚...需要的朋友可以參考下
    2015-07-07
  • springboot集成mybatisplus實例詳解

    springboot集成mybatisplus實例詳解

    這篇文章主要介紹了springboot集成mybatisplus實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • 詳解springboot整合ehcache實現(xiàn)緩存機制

    詳解springboot整合ehcache實現(xiàn)緩存機制

    這篇文章主要介紹了詳解springboot整合ehcache實現(xiàn)緩存機制,ehcache提供了多種緩存策略,主要分為內(nèi)存和磁盤兩級,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Java反射的使用和原理詳解

    Java反射的使用和原理詳解

    這篇文章主要介紹了Java反射的使用和原理詳解,反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查并且對內(nèi)部的成員進行操作,需要的朋友可以參考下
    2024-01-01
  • java實現(xiàn)系統(tǒng)托盤示例

    java實現(xiàn)系統(tǒng)托盤示例

    桌面的系統(tǒng)托盤即當(dāng)程序最小化或者關(guān)閉按鈕程序并沒有退出,而是最小化在任務(wù)狀態(tài)區(qū)域,下面是使用java實現(xiàn)系統(tǒng)托盤示例
    2014-03-03

最新評論