第五章 第一節 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);
}
}
}
總結
- 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註冊會重新清空快取。