1. 程式人生 > >第五章 第一節 spring-context之ApplicationContextEvent

第五章 第一節 spring-context之ApplicationContextEvent

前言

ApplicationListener是對application生命週期的監聽體制。

類依賴圖

ApplicationListener體系

ApplicationEvent體系

ApplicationEventMulticaster

ApplicationEventMulticaster只有一個實現類SimpleApplicationEventMulticaster

原始碼詳解

ApplicationListener物件繼承了java.util.EventListener。ApplicationEvent繼承了java.util.EventObject。spring的ApplicationListener體系是基於java的event體制實現,並在上面進行擴充套件。

ApplicationEventMulticaste

public interface ApplicationEventMulticaster {

	void addApplicationListener(ApplicationListener<?> listener);

	void addApplicationListenerBean(String listenerBeanName);

	void removeApplicationListener(ApplicationListener<?> listener);

	void removeApplicationListenerBean(String listenerBeanName);

	void removeAllListeners();

	void multicastEvent(ApplicationEvent event);

	void multicastEvent(ApplicationEvent event, ResolvableType eventType);

}

事件處理器管理類,負責ApplicationListener的管理,事件的多播。multicastEvent方法是接受事件(ApplicationEvent)呼叫對應ApplicationListener

事件處理器註冊方式之向容器註冊

AbstractApplicationContext

public void addApplicationListener(ApplicationListener<?> listener) {
		Assert.notNull(listener, "ApplicationListener must not be null");
	if (this.applicationEventMulticaster != null) {
		this.applicationEventMulticaster.addApplicationListener(listener);
	}
	else {
		this.applicationListeners.add(listener);
	}
}
事件處理器註冊方式之主動識別介面

ApplicationListenerDetector

public Object postProcessAfterInitialization(Object bean, String beanName) {
	if (this.applicationContext != null && bean instanceof ApplicationListener) {
		// potentially not detected as a listener by getBeanNamesForType retrieval
		Boolean flag = this.singletonNames.get(beanName);
		if (Boolean.TRUE.equals(flag)) {
			// singleton bean (top-level or inner): register on the fly
			this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
		}
		else if (Boolean.FALSE.equals(flag)) {
			if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
				// inner bean with other scope - can't reliably process events
				logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
						"but is not reachable for event multicasting by its containing ApplicationContext " +
						"because it does not have singleton scope. Only top-level listener beans are allowed " +
						"to be of non-singleton scope.");
			}
			this.singletonNames.remove(beanName);
		}
	}
	return bean;
}
事件處理器註冊方式之註解識別
public @interface EventListener {

	@AliasFor("classes")
	Class<?>[] value() default {};

	@AliasFor("value")
	Class<?>[] classes() default {};

	String condition() default "";

}

EventListenerMethodProcessor

protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
		if (!this.nonAnnotatedClasses.contains(targetType)) {
			Map<Method, EventListener> annotatedMethods = null;
			try {
				annotatedMethods = MethodIntrospector.selectMethods(targetType,
						new MethodIntrospector.MetadataLookup<EventListener>() {
							@Override
							public EventListener inspect(Method method) {
								return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
							}
						});
			}
			catch (Throwable ex) {
				// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
				if (logger.isDebugEnabled()) {
					logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
				}
			}
			if (CollectionUtils.isEmpty(annotatedMethods)) {
				this.nonAnnotatedClasses.add(targetType);
				if (logger.isTraceEnabled()) {
					logger.trace("No @EventListener annotations found on bean class: " + targetType);
				}
			}
			else {
				// Non-empty set of methods
				for (Method method : annotatedMethods.keySet()) {
					for (EventListenerFactory factory : factories) {
						if (factory.supportsMethod(method)) {
							Method methodToUse = AopUtils.selectInvocableMethod(
									method, this.applicationContext.getType(beanName));
							ApplicationListener<?> applicationListener =
									factory.createApplicationListener(beanName, targetType, methodToUse);
							if (applicationListener instanceof ApplicationListenerMethodAdapter) {
								((ApplicationListenerMethodAdapter) applicationListener)
										.init(this.applicationContext, this.evaluator);
							}
							this.applicationContext.addApplicationListener(applicationListener);
							break;
						}
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
							beanName + "': " + annotatedMethods);
				}
			}
		}
	}

ApplicationListener體系

ApplicationListener
public interface  ApplicationListener<E extends ApplicationEvent> extends EventListener {
	void onApplicationEvent(E event);
}

事件處理器,只負責處理ApplicationEvent的子類執行。

GenericApplicationListener
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

	boolean supportsEventType(ResolvableType eventType);

	boolean supportsSourceType(Class<?> sourceType);

}

GenericApplicationListener是ApplicationListener的子介面。主要功能是主動提供監控的事件。而不是像ApplicationListener通過類宣告中泛型得到事件。同時提供GenericApplicationListener的實現類GenericApplicationListenerAdapter統一GenericApplicationListener與ApplicationListener的行為

ApplicationEvent| | |

| ------------ | ------------ | | | | | | |

public abstract class ApplicationEvent extends EventObject {

	private static final long serialVersionUID = 7099057708183571937L;

	private final long timestamp;
	
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}

	public final long getTimestamp() {
		return this.timestamp;
	}

}

事件型別目前分ApplicationContextEvent與RequestHandledEvent兩大類。ApplicationContextEvent是對應應用上下文的事件,與RequestHandledEvent對應http服務事件。

ApplicationContextEvent

  • ContextRefreshedEvent
  • ContextClosedEvent
  • ContextStartedEvent
  • ContextStoppedEvent

RequestHandledEvent

  • ServletRequestHandledEvent

事件被觸發的點

ContextRefreshedEvent
	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}
ContextClosedEvent
protected void doClose() {
	if (this.active.get() && this.closed.compareAndSet(false, true)) {
		if (logger.isInfoEnabled()) {
			logger.info("Closing " + this);
		}

		LiveBeansView.unregisterApplicationContext(this);

		try {
			// Publish shutdown event.
			publishEvent(new ContextClosedEvent(this));
		}catch (Throwable ex) {
			logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
		}

		// Stop all Lifecycle beans, to avoid delays during individual destruction.
		try {
			getLifecycleProcessor().onClose();
		}catch (Throwable ex) {
			logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
			}
		// Destroy all cached singletons in the context's BeanFactory.
		destroyBeans();
		// Close the state of this context itself.
		closeBeanFactory();
		// Let subclasses do some final clean-up if they wish...
		onClose();
		this.active.set(false);
	}
}
ContextStartedEvent
public void start() {
	getLifecycleProcessor().start();
	publishEvent(new ContextStartedEvent(this));
}
ContextStoppedEvent
@Override
public void stop() {
	getLifecycleProcessor().stop();
	publishEvent(new ContextStoppedEvent(this));
}

ApplicationEventPublisher

public interface ApplicationEventPublisher {

	void publishEvent(ApplicationEvent event);

	void publishEvent(Object event);

}

大家會奇怪已經有處理類了,為什麼需要一個ApplicationEventPublisher介面。application有屬於自己的行文操作,這些操作屬於application的。有哪些行為操作請看下面的程式碼

protected void publishEvent(Object event, ResolvableType eventType) {
	ApplicationEvent applicationEvent;
	// 判斷是否是ApplicationEvent
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		// 不是進行一次封裝
		applicationEvent = new PayloadApplicationEvent<Object>(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
		}
	}
	// 在spring啟動的的時候,發生的事件都會儲存在earlyApplicationEvents。等啟動成功之後,會被全部執行
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	}
	else {
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
	}

	// 如果有parent容器,讓parent執行一次
	if (this.parent != null) {
		if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
		}
		else {
			this.parent.publishEvent(event);
		}
	}
}

總結

  1. ApplicationContextEvent體系分為event子體系,listener子體系,ApplicationEventMulticaster子體系
  2. event(事件)可以自定義。目前spring裡面分為 ApplicationConetx事件與web事件。只需要呼叫ApplicationContext.multicastEvent(ApplicationEvent event),就可以觸發事件了。
  3. 事件發現的方式有兩種,一種是從ApplicationListener泛型得到,一種是從GenericApplicationListener的supportsEventType方法得到
  4. listenrner可以非同步執行
  5. 第一次執行事件,會迭代所有listenrner,匹配出執行該事件的listenrner。並以envent(事件)為Key,泛型為listenrner的list物件為value,快取起來。
  6. ApplicationContextEvent體系使用的是多播模式,並不是事件驅動模式。沒有事件註冊。每個listenrner註冊會重新清空快取。
  7. ApplicationContextEvent體系使用的是多播模式,並不是事件驅動模式。沒有事件註冊。每個listenrner註冊會重新清空快取。
  8. ApplicationContextEvent體系使用的是多播模式,並不是事件驅動模式。沒有事件註冊。每個listenrner註冊會重新清空快取。