引言
Spring事件
public abstract class ApplicationEvent extends EventObject {
///省略其他代碼
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
//省略其他代碼
}
Spring內置事件
事件名 | 註釋 |
ContextRefreshedEvent | Spring應用上下文就緒事件 |
ContextStartedEvent | Spring應用上下文啓動事件 |
ContextStopedEvent | Spring應用上下文停止事件 |
ContextClosedEvent | Spring應用上下文關閉事件 |
Spring事件監聽手段
2種監聽手段
方法類型 | 訪問修飾符 | 返回類型 | 參數數量 | 參數類型 | 備註 |
同步 | public | 任意類型 | 0或1 | 監聽事件類 型或其子類 |
會將返回值 作爲事件向 後傳播 |
異步 | public | void | 0或1 | 監聽事件類 型或其子類 |
如果出錯不
會傳播給調
用者。
不會向後傳
播事件
|
@EventListener原理
找入口
1.將@EventListener方法轉換爲ApplicationListener示例
2.實現BeanFactoryPostProcessor用於檢索EventListenerFactory
避免AOP增強,EventListenerFactory
public interface SmartInitializingSingleton {
/**
* 預實例化完成之後調用,保證所有常規單例Bean創建完畢
* 調用ListableBeanFactory#getBeansOfType沒有任何副作用
* 注意:
* 對於延遲加載的單例Bean,不會觸發這個回調。
* 並且其他作用域的Bean,也不會觸發這個回調。
* 謹慎使用,應僅用於引導功能。
*/
void afterSingletonsInstantiated();
}
public class EventListenerMethodProcessor {
//省略其他部分
private void processBean(final String beanName, final Class<?> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType) &&
!targetType.getName().startsWith("java") &&
!isSpringContainerClass(targetType)) {
Map<Method, EventListener> annotatedMethods = null;
try {
//找出所有EventListener註解的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup<EventListener>) method ->
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.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = this.applicationContext;
Assert.state(context != null, "No ApplicationContext set");
List<EventListenerFactory> factories = this.eventListenerFactories;
Assert.state(factories != null, "EventListenerFactory List not initialized");
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
//通過EventListenerFactory轉換爲ApplicationListenerMethodAdapter
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
//將該事件監聽器註冊到應用上下文中。
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
}
@EventListener總結
- 這個方法的邏輯就是將@EventListener的方法,
- 通過EventListenerFactory轉換爲ApplicationListenerMethodAdapter,
- 該事件監聽器註冊上線文中。
Spring的廣播器
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
// Fully synchronized building and caching of a ListenerRetriever
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
SimpleApplicationEventMulticaster總結:
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
簡述Spring Boot事件
Springboot事件
Spring Boot事件監聽手段
Spring Boot的廣播器