第五章 第一节 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注册会重新清空缓存。

猜你喜欢

转载自my.oschina.net/u/1261452/blog/1922684
今日推荐