前言
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);
}
}
}
总结
- ApplicationContextEvent体系分为event子体系,listener子体系,ApplicationEventMulticaster子体系
- event(事件)可以自定义。目前spring里面分为 ApplicationConetx事件与web事件。只需要调用ApplicationContext.multicastEvent(ApplicationEvent event),就可以触发事件了。
- 事件发现的方式有两种,一种是从ApplicationListener泛型得到,一种是从GenericApplicationListener的supportsEventType方法得到
- listenrner可以异步执行
- 第一次执行事件,会迭代所有listenrner,匹配出执行该事件的listenrner。并以envent(事件)为Key,泛型为listenrner的list对象为value,缓存起来。
- ApplicationContextEvent体系使用的是多播模式,并不是事件驱动模式。没有事件注册。每个listenrner注册会重新清空缓存。
- ApplicationContextEvent体系使用的是多播模式,并不是事件驱动模式。没有事件注册。每个listenrner注册会重新清空缓存。
- ApplicationContextEvent体系使用的是多播模式,并不是事件驱动模式。没有事件注册。每个listenrner注册会重新清空缓存。