Spring 事件机制总结

1.Spring事件类型

    在Spring中,事件是由org.springframework.context.ApplicationEvent实例来表示的,这个抽象类继承扩展了java.util.EventObject,可以使用EventObject中的getSource方法,我们可以很容易地获得所发生的给定事件的对象;在Spring应用中,事件主要分为两大类型,容器生命周期相关和请求过程相关,如下,为ApplicationEvent相关的UML图,通过子类基础结构不难看出,RequestHandledEvent表示请求相关联的事件,ApplicationContextEvent表示容器上下文相关联的事件。
Spring 事件机制总结_第1张图片

1.1 容器上下文事件

    所有这种类型的事件都继承自org.springframework.context.event.ApplicationContextEvent类,其构造函数传入的是ApplicationContext类型的参数,如下,为其代码定义:

public abstract class ApplicationEvent extends EventObject {
     

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened. */
	private final long timestamp;


	/**
	 * Create a new ApplicationEvent.
	 * @param source the object on which the event initially occurred (never {@code null})
	 */
	public ApplicationEvent(Object source) {
     
		super(source);
		this.timestamp = System.currentTimeMillis();
	}


	/**
	 * Return the system time in milliseconds when the event happened.
	 */
	public final long getTimestamp() {
     
		return this.timestamp;
	}

}

     通过该类以及其子类,我们就可以直接通过应用程序上下文的生命周期来得到所发生的事件,对应的子类所代表的事件类型如下:

  • ContextStartedEvent :在上下文启动时被触发
  • ContextStoppedEvent :上下文暂停时出发
  • ContextRefreshedEvent : 容器执行refresh方法时触发
  • ContextClosedEvent: 上下文关闭时触发

     每个事件在哪里广播出去的,我们后面在分析Spring容器启动过程再一一点名,此处,只需要知道这些代表的是哪些事件即可。

1.2 与request 请求相关联

     该类型的事件由org.springframework.web.context.support.RequestHandledEvent实例来表示,当在ApplicationContext中处理请求时,它们被引发。

2.事件广播器

     事件Event现在有了,现在需要一个专门广播各种不同事件的对象,在Spring中,这个是由org.springframework.context.event.ApplicationEventMulticaster接口的实现表示。此接口定义了3种方法:

  • 添加新的监听器:定义了两种方法来添加新的监听器: addApplicationListener(ApplicationListener listener)和addApplicationListenerBean(String listenerBeanName)。当监听器对象已知时,可以应用第一个。如果使用第二个,我们需要将bean name 得到listener对象(依赖查找DL),然后再将其添加到listener列表中。
  • 删除监听器:添加方法一样,我们可以通过传递对象来删除一个监听器(**removeApplicationListener(ApplicationListener listener)**或通过传递bean名称(removeApplicationListenerBean(String listenerBeanName)), 第三种方法,**removeAllListeners()**用来删除所有已注册的监听器
  • 将事件发送到已注册的监听器:由multicastEvent(ApplicationEvent event)源码注释可知,它用来向所有注册的监听器发送事件。实现可以从org.springframework.context.event.SimpleApplicationEventMulticaster中找到,如下所示:
@Override
	public void multicastEvent(ApplicationEvent event) {
     
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
     
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
     
			if (executor != null) {
     
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
     
				invokeListener(listener, event);
			}
		}
	}
	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);
		}
	}
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
     
		try {
     
			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.isTraceEnabled()) {
     
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
     
				throw ex;
			}
		}
	}

3.事件监听器

     事件监听器,既监听事件,执行不同的动作,其实通过上面事件广播起的代码可以很清除知道,在Spring中,事件监听器是由org.springframework.context.ApplicationListener所表示的,如下,为该接口的定义,该接口仅仅定义了一个方法onApplicationEvent,在事件广播器源码我们也知道,该方式是事件广播器通知事件监听器的入口。

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
     

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

4.总结

     事件编程包括在信号发送到应用程序时触发并执行某些操作。这个信号必须有一个监听器在监听。在Spring中,由于监听器中的泛型定义(void onApplicationEvent(E event) ),事件可以很容易地被listeners所捕获。通过它,如果所触发的事件对应于监听器所预期的事件,我们无须多余的检查(说的啰嗦了,就是符合所需求的类型即可,省去很多麻烦,我们可以直接根据泛型就可以实现很多不同的处理)。我们还发现,默认情况下,监听器是以同步方式执行的。所以在调用线程同时执行比如视图生成或数据库处理的操作是不行的。

你可能感兴趣的:(Spring,Spring事件机制)