Spring源码解析(2)之扩展原理ApplicationListener事件发布源码解析

一、Spring是发布事件源码流程

1.1)首先我们自己写一个TulingApplicationListener 实现ApplicationListener​接口,并且把该组件加入到容器中.

/**
 * 创建一个监听器
 */
@Component
public class TulingApplicationListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("TulingApplicationListener 接受到了一个事件"+event);
    }
}

        然后我们自己又手动去发布一个事件。

public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
        ctx.publishEvent(new ApplicationEvent("我手动发布了一个事件") {
            @Override
            public Object getSource() {
                return super.getSource();
            }
        });
        
        容器关闭也发布事件
        ctx.close();
    }
}

        运行结果,这里我们也发现了当容器关闭的时候也会发布事件。

我拦截到了
TulingApplicationListener 接受到了一个事件org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@191beef: startup date [Sat Oct 09 15:03:27 CST 2021]; root of context hierarchy]
TulingApplicationListener 接受到了一个事件com.tuling.testapplicationlistener.MainClass$1[source=我手动发布了一个事件]
TulingApplicationListener 接受到了一个事件org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@191beef: startup date [Sat Oct 09 15:03:27 CST 2021]; root of context hierarchy]

        1.2Spring事件发布源码解析

        源码位置:org.springframework.context.support.AbstractApplicationContext#refresh

        

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given annotated classes and automatically refreshing the context.
	 * @param annotatedClasses one or more annotated classes,
	 * e.g. {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
        // 这里面进行事件的注册与发布
		refresh();
	}

        org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster,这里进行初始化事件多播器,我们的事件的多播器就是用来注册事件,以及执行事件的。

        下面是注册多播器的源码,他首先先判断IOC容器中是否包含applicationEventMulticaster(事件多播器)的Bean的name,如果存在则创建一个applicationEventMulticaster的Bean存在在IOC容器总,bean的name为applicationEventMulticaster。

        如果容器中不包含一个名为applicationEventMulticaster的多播器的组件,那么他就会创建一个SimpleApplicationEventMulticaster的多播器并注册到容器中去。

	/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // /判断IOC容器中包含applicationEventMulticaster 事件多播器的Bean的name
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            // /创建一个applicationEventMulticaster的bean放在IOC 容器中,bean的name 为applicationEventMulticaster
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
        //容器中不包含一个beanName 为applicationEventMulticaster的多播器组件
		else {
            创建一个SimpleApplicationEventMulticaster 多播器
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            //注册到容器中
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}

         把容器中的监听器注册到多播器上去 源码解析。

  1.          首先我们会先去容器中把ApplicationListener的查找出来,然后注册到多播器上,这里一般都是一些系统的ApplicationListener.
  2.         其次就会去扫描我们实现ApplicationListener的组件然后注册到多播器。
  3.         这里小伙伴们可能就会发现,如果在我们多播器没有初始化的时候,那早期想发布事件该怎么办,所以第三Spring就想到了这一点,他第三步的时候就会发布早期堆积的事件。
	/**
	 * Add beans that implement ApplicationListener as listeners.
	 * Doesn't affect other listeners, which can be added without being beans.
	 */
	protected void registerListeners() {
        // 去容器中把applicationListener 捞取出来注册到多播器上去(系统的)
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

        // 这里是扫描自己定义实现了的ApplicationListener的组件
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
        // 在这里之前,我们早期想发布的事件 由于没有多播器没有发布,在这里我们总算有了自己的多播器,可以在这里发布早期堆积的事件了
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

        下面来看下他具体发布事件的源码,首先获取所有的监听器,然后看看Spring容器是否支持异步执行事件。

	public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        // 获取到所有的监听器
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
            // 看spring 容器中是否支持线程池 异步发送事件
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

        点进去invokeListener,Spring命名有个习惯,真正干事情的method,一般都是以doxxxxx开头。

	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);
		}
	}
    
    // 真正去执行事件的method
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
            // 调用对于listener的onApplicationEvent事件
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isDebugEnabled()) {
					logger.debug("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/jokeMqc/article/details/120671404