Spring註解系列二十九:ApplicationListener原理

一、ApplicationListener:監聽容器中發佈的事件。事件驅動模型開發;
public interface ApplicationListener<E extends ApplicationEvent>監聽 ApplicationEvent 及其下面的子事件;
1、監聽器 MyApplicationListener 實現了 ApplicationListener 類,用來監聽 ApplicationEvent及其子類下的某個事件。

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

	//當容器中發佈此事件以後,方法觸發
	@Override
	public void onApplicationEvent(ApplicationEvent event) {

		System.out.println("收到事件:"+event);
	}

}

2、只要容器中有相應事件的發佈,我們就能監聽到這個事件;
 ContextRefreshedEvent:容器刷新完成(所有bean都完全創建)會發布這個事件;
 ContextClosedEvent:關閉容器會發布這個事件;
3、發佈一個事件:applicationContext.publishEvent();

@Test
public void test01(){
	AnnotationConfigApplicationContext applicationContext  = new AnnotationConfigApplicationContext(ExtConfig.class);

	//發佈事件;
	applicationContext.publishEvent(new ApplicationEvent(new String("我發佈的時間")){});
	
	applicationContext.close();
}

控制檯輸出:

收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@59906517: startup date [Sun Jun 16 11:36:56 CST 2019]; root of context hierarchy]

二、ApplicationListener 源碼解析
ContextRefreshedEvent、IOCTest_Ext$1[source=我發佈的時間]、ContextClosedEvent;
1、ContextRefreshedEvent事件:
 (1)、容器創建對象:refresh();

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}
public void refresh() throws BeansException, IllegalStateException {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        this.prepareBeanFactory(beanFactory);

        try {
            this.postProcessBeanFactory(beanFactory);
            this.invokeBeanFactoryPostProcessors(beanFactory);
            this.registerBeanPostProcessors(beanFactory);
            this.initMessageSource();
            this.initApplicationEventMulticaster();
            this.onRefresh();
            this.registerListeners();
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }

            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }

    }
}

  initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
    1)、先去容器中找有沒有id=“applicationEventMulticaster”的組件;
    2)、如果沒有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);並且加入到容器中,我們就可以在其他組件要派發事件,自動注入這個applicationEventMulticaster。
  registerListeners();從容器中拿到所有的監聽器,把他們註冊到applicationEventMulticaster中;

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//將listener註冊到ApplicationEventMulticaster中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

 (2)、finishRefresh():容器刷新完成會發布ContextRefreshedEvent事件;

protected void finishRefresh() {
    this.initLifecycleProcessor();
    this.getLifecycleProcessor().onRefresh();
    this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
    LiveBeansView.registerApplicationContext(this);
}

 (3)、publishEvent(new ContextRefreshedEvent(this));
   1)、獲取事件的多播器(派發器):getApplicationEventMulticaster()
   2)、multicastEvent派發事件;
   3)、獲取到所有的ApplicationListener;
     for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {}
     如果有Executor,可以支持使用Executor進行異步派發;Executor executor = getTaskExecutor()
     否則,同步的方式直接執行listener方法;invokeListener(listener, event); 拿到listener回調onApplicationEvent方法;

public void publishEvent(ApplicationEvent event) {
    this.publishEvent(event, (ResolvableType)null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);
    }

    Object applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent)event;
    } else {
        applicationEvent = new PayloadApplicationEvent(this, event);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
        }
    }

    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    } else {
        this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
    }

    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
        } else {
            this.parent.publishEvent(event);
        }
    }

}
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    Iterator var4 = this.getApplicationListeners(event, type).iterator();

    while(var4.hasNext()) {
        final ApplicationListener<?> listener = (ApplicationListener)var4.next();
        Executor executor = this.getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                }
            });
        } else {
            this.invokeListener(listener, event);
        }
    }

}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    ErrorHandler errorHandler = this.getErrorHandler();
    if (errorHandler != null) {
        try {
            this.doInvokeListener(listener, event);
        } catch (Throwable var5) {
            errorHandler.handleError(var5);
        }
    } else {
        this.doInvokeListener(listener, event);
    }

}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        listener.onApplicationEvent(event);
    } catch (ClassCastException var6) {
        String msg = var6.getMessage();
        if (msg != null && !msg.startsWith(event.getClass().getName())) {
            throw var6;
        }

        Log logger = LogFactory.getLog(this.getClass());
        if (logger.isDebugEnabled()) {
            logger.debug("Non-matching event type for listener: " + listener, var6);
        }
    }

}

2、自己發佈事件;applicationContext.publishEvent();
3、容器關閉會發布ContextClosedEvent;applicationContext.close();

public void close() {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.doClose();
        if (this.shutdownHook != null) {
            try {
                Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
            } catch (IllegalStateException var4) {
                ;
            }
        }

    }
}
protected void doClose() {
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Closing " + this);
        }

        LiveBeansView.unregisterApplicationContext(this);

        try {
            this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this)));
        } catch (Throwable var3) {
            this.logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", var3);
        }

        try {
            this.getLifecycleProcessor().onClose();
        } catch (Throwable var2) {
            this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2);
        }

        this.destroyBeans();
        this.closeBeanFactory();
        this.onClose();
        this.active.set(false);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章