spring 中的事件

  • Post author:
  • Post category:其他


1. 应用启动的时候,初始化 事件广播器,事件广播器 调用 容器里的 监听器,调用对应的目标方法


   弄清楚Java 中的事件原理,无非要弄清楚三个角色:事件源(source)、事件对象(EventObject)、事件监听器(EventListener)。

   注:Java 中的java.util 包中的EventObject 与EventListener 是所有事件对象与监听器的最基础的类。
   流程:事件源 发布 事件  ,然后 事件源获取时间广播器 ,通过事件广播器 调用 事件 监听器 进而 调用 监听器里的方法

Spring 中是如何规划这三个角色的呢?

 角色一:事件对象: 基础类为org.springframework.context.ApplicationEvent
	        说明:
			其中ApplicationContextEvent 事件传入ApplicationContext 作为事件源,适合于所有Java 应用 
			RequestHandleEvent 中传入Object 对象作为事件源,且构造函数中附带了SessionID、请求地址、主机地址等信息,可见是专用于 Web 工程的。

角色二:事件源:

          对于不同应用事件源是不同的。此处主要学习Spring ,所以只讨论子类ApplicationContextEvent 事件对象的事件源:ApplicationContext 


    说明:ApplicationContext 直接实现了ApplicationEventPublisher 接口,该接口中定义了publishEvent 方法,图上所示的类是全部实现了该接口方法的,
	而另外有些直接或间接实现了接口ApplicationContext 的类并没有实现publishEvent 方法,只是被动的继承了该方法。publishEvent 
	的具体实现位置在图中标记的AbstractApplicationContext 抽象类中。

    监听器是在事件源中被调用的,那么事件源ApplicationContext 是怎么存放这些监听器实例的?
	在ApplicationContext 直接子类中,Spring 定义了所有监听器实例为一个集合:

     private Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
角色三:监听器类: 基础类为:org.springframework.context.ApplicationListener

 二、Spring 事件发布实现

     ApplicationContext 对象作为事件源,ApplicationEvent 作为事件对象基础类,ApplicationListener 作为事件监听器基础类。
AbstractApplicationContext 中 源码如下:
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
                // 初始化事件广播器(将来上下文  发布事件的时候就是通过 事件广播器获取 监听器列表 调用目标方法的)
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

相同的类里具体如下:

protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			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 + "]");
			}
		}
	}

打断点:

@Override
	public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        // 从父类 获取 监听器
        // LinkedList<ApplicationListener<?>> allListeners = new  LinkedList<ApplicationListener<?>>();
         
		// Set<ApplicationListener<?>> listeners;
		// Set<String> listenerBeans;
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            // 如果监听器 的方法上 加上 @Sync 就会 在 SimpleApplicationEventMulticaster 
            // 类里实例化 一个 线程池(private Executor taskExecutor;)
            
			Executor executor = getTaskExecutor();
            // 异步
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
                 // 同步
				invokeListener(listener, event);
			}
		}
	}
// 调用 监听器的方法
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
		ErrorHandler errorHandler = getErrorHandler();
		if (errorHandler != null) {
			try {
				listener.onApplicationEvent(event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			try {
				listener.onApplicationEvent(event);
			}
			catch (ClassCastException ex) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				LogFactory.getLog(getClass()).debug("Non-matching event type for listener: " + listener, ex);
			}
		}
	}

spring 中发布事件的流程:

package org.springframework.context;

public interface ApplicationEventPublisher {


	void publishEvent(ApplicationEvent event);

	void publishEvent(Object event);

}

事件源 ——>事件发布


@RestController
public class SyncEventController {


    /**
    * 事件发布
     * Spring中发布事件的接口是ApplicationEventPublisher,我们可以自定义自己的类,当然也可以使用spring现成的类
     * Spring的事件发布类
     * ApplicationContext
     * AnnotationConfigApplicationContext
     *
     * 在容器启动刷新的时候已经注入了ApplicationEventPublisher的实现,我们可以直接注入使
    *
    */
    @Resource
    private ApplicationContext applicationContext;

    @RequestMapping("syn/hello")
    public String hello(){
        System.out.println("事件开始发布消息:"+System.currentTimeMillis());
         // 自定义事件 
        applicationContext.publishEvent(new SynCustomEvent(this,"嘿嘿嘿!"));
        return "success";
    }

自定义事件:

package com.example.demo.entity.event;

import org.springframework.context.ApplicationEvent;

/**
 * @program: springboot_01
 * @description:  继承  ApplicationEvent  自定义事件;同步事件
 * @author: guoyiguang
 * @create: 2021-06-02 11:51
 **/
public class SynCustomEvent extends  ApplicationEvent  {

    
    /** 
    * 要封装的消息,可以是自定义对象
    */ 
    private String message;
    public SynCustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    /**
     * 调用 getMessage 获取 被封装的消息
     */
    public String getMessage() {
        return message;
    }

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

监听器——> (同步或者异步)接受消息

@Component
public class EventListenerRunner3 {

    /** 
    *      @Async  指定一步执行
    */ 
    @EventListener(SynCustomEvent.class)
//    @Async  // 异步接受消息
    public void onApplicationEvent(SynCustomEvent customEvent){
        System.out.println("接收到的消息为:"+customEvent.getMessage());
    }
}
AbstractApplicationContext 中发布事件的代码:
	protected void publishEvent(Object event, ResolvableType eventType) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}

		// Decorate event as an ApplicationEvent if necessary
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent) {
			applicationEvent = (ApplicationEvent) event;
		}
		else {
			applicationEvent = new PayloadApplicationEvent<Object>(this, event);
			if (eventType == null) {
				eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
			}
		}

		// Multicast right now if possible - or lazily once the multicaster is initialized
		if (this.earlyApplicationEvents != null) {
			this.earlyApplicationEvents.add(applicationEvent);
		}
		else {
            // 从容器中获取  事件广播器
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}

		// Publish event via parent context as well...
		if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext) {
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
	}

获取事件广播器后广播事件


	@Override
	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();
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);
			}
		}
	}



版权声明:本文为qq_38807606原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。