第五章 第一節 spring-context之ApplicationContextEvent

前言

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

類依賴圖

ApplicationListener體系

ApplicationEvent體系

ApplicationEventMulticaster

ApplicationEventMulticaster只有一個實現類SimpleApplicationEventMulticasterweb

源碼詳解

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

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緩存

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

AbstractApplicationContextapp

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 "";

}

EventListenerMethodProcessoride

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的子類執行。post

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

	boolean supportsEventType(ResolvableType eventType);

	boolean supportsSourceType(Class<?> sourceType);

}

GenericApplicationListener是ApplicationListener的子接口。主要功能是主動提供監控的事件。而不是像ApplicationListener經過類聲明中泛型獲得事件。同時提供GenericApplicationListener的實現類GenericApplicationListenerAdapter統一GenericApplicationListener與ApplicationListener的行爲this

ApplicationEvent| | |

| ------------ | ------------ | | | | | | |lua

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註冊會從新清空緩存。
相關文章
相關標籤/搜索