docs/Spring全家桶/Spring源码分析/Spring重要机制探秘/Spring探秘之Spring事件机制.md
ʽ¼ǰһ demo
MyApplicationEventpublic class MyApplicationEvent extends ApplicationEvent {
private static final long serialVersionUID = -1L;
public MyApplicationEvent(Object source) {
super(source);
}
}
MyApplicationEventListener¼ MyApplicationEvent м@Component
public class MyApplicationEventListener
implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println(Thread.currentThread().getName() + " | " + event.getSource());
}
}
һ࣬Ȳָݣ
@Configuration
@ComponentScan
public class Demo08Config {
}
ࣺ
@ComponentScan
public class Demo08Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(Demo08Config.class);
// ¼
context.publishEvent(
new MyApplicationEvent(Thread.currentThread().getName() + " | Զ¼ ..."));
}
}
ϴ붨һ¼ MyApplicationEventȻһ MyApplicationEventListener MyApplicationEvent ¼Ȼ main() У context.publishEvent(...) ¼
У£
main | main | Զ¼ ...
Կ¼ɹˡ
п֪¼ķ߳Ϊ main¼ļ߳Ҳ main
ʽǰ¼ص¼ص 4
һһ
spring ṩ¼Ϊ ApplicationEventһ̳࣬ jdk ṩ EventObject ࣬Զ¼ʱɼ̳ ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
/** timestamp */
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationEvent EventObjectǼ
/**
* EventObject jdkṩλ java.util
*/
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
// ¼
protected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* ȡ¼
*/
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
ApplicationEvent EventObject ApplicationEvent ṩԣ
source EventObject ԣ¼ݣtimestamp: ʱ¼¼ʱ䡣ʵϣspring ܷ ApplicationEvent ͵¼⣬Է Object ͵¼鿴ͿԷ һ㡣
spring ṩķΪ ApplicationEventPublisher£
public interface ApplicationEventPublisher {
/**
* ApplicationEvent͵¼
*/
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
/**
* Object͵¼
*/
void publishEvent(Object event);
}
Ǹӿڣڶ
void publishEvent(ApplicationEvent event): ApplicationEvent ͵¼void publishEvent(Object event): Object ͵¼AbstractApplicationContext ApplicationEventPublisher ࣬ǿֱӵ AbstractApplicationContext#publishEvent ¼
AbstractApplicationContext ʵ֣Ǻʱپ
㲥ǽշ¼Ȼ¼㲥£
public interface ApplicationEventMulticaster {
/**
* Ӽ
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* Ӽ beanName
*/
void addApplicationListenerBean(String listenerBeanName);
/**
* Ƴ
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* Ƴ beanName
*/
void removeApplicationListenerBean(String listenerBeanName);
/**
* Ƴеļ
*/
void removeAllListeners();
/**
* 㲥¼
*/
void multicastEvent(ApplicationEvent event);
/**
* 㲥¼
*/
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
Ӵ㲥Ҫ
spring ĬϵĹ㲥Ϊ SimpleApplicationEventMulticasterǺٷ
¼ȻһЩ£
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* ¼
*/
void onApplicationEvent(E event);
}
ڴ¼ʱҪʵ ApplicationListenerȻ onApplicationEvent(...) бдǵ¼
㲥ijʼ``עع¼㲥ijʼ``ע̡
ڴ spring AbstractApplicationContext#refresh У¼㲥ijʼ``עֱڵ 8 10
ش£
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/**
* ʼ㲥
* ¼㲥ʹõģʹĬϵ¼㲥
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// ûԶ¼㲥ʹû
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
ApplicationEventMulticaster.class);
}
else {
// ûûù㲥ʹĬϵ¼㲥
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
this.applicationEventMulticaster);
}
}
/**
* ע
*/
protected void registerListeners() {
// 1\. Ƚֶӵļŵ㲥
// AbstractApplicationContext#addApplicationListener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2\. beanFactoryлȡȡƣӵ㲥
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 3\. Ӧ¼
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
// earlyApplicationEvents Ϊ nullٷ¼
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
...
}
㲥ijʼܼ¼㲥ʹõģʹĬϵ¼㲥Ĭϵ¼㲥 SimpleApplicationEventMulticaster
ע£
AbstractApplicationContext#addApplicationListener ӼbeanFactory лȡȡƣӵ㲥Уע⣺ʱ beanFactory е bean ûгʼֻ beanName;ع̺ǴҪ㣺
ǰڵ̵棬Ƕ¼Ѿ˸ŵĸҲ¼㲥ijʼע̣ Ǿʽ¼ķˡ
demo Уǵ context.publishEvent(...) ¼Ǹ
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// ¼
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// earlyApplicationEvents Ϊ nullapplicationEventӵ earlyApplicationEvents
// ע earlyApplicationEvents Ϊ null
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// Ƿ¼IJ
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// ڸһ
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
}
ܼؼΪ
// Ƿ¼IJ
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
дȻȡ¼㲥Ȼ㲥¼
ǰᵽspring ṩĬϵ¼㲥 SimpleApplicationEventMulticasterǽ SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType) ¼Ĺ㲥̣
/**
* 㲥¼
*/
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 1\. ȡ TaskExecutor
Executor executor = getTaskExecutor();
// 2\. getApplicationListeners(...) ȡܼ¼ļ
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 3\. һ invokeListener(...)
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
Ϸ 3
getTaskExecutor()getApplicationListeners(...)invokeListener(...)ϲ¼㲥̣ú÷¡
getTaskExecutor()taskExecutor SimpleApplicationEventMulticaster һԣgetTaskExecutor() taskExecutor getter
private Executor taskExecutor;
public void setTaskExecutor(@Nullable Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Nullable
protected Executor getTaskExecutor() {
return this.taskExecutor;
}
spring Ϊṩ͵ taskExecutor
SyncTaskExecutorͬ taskExecutor execute(...) Ϊ
@Override
public void execute(Runnable task) {
Assert.notNull(task, "Runnable must not be null");
task.run();
}
ԿȷʵǸֱͬӵ Runnable#run ûµ߳
SimpleAsyncTaskExecutor첽 taskExecutor execute(...) Ϊ
@Override
public void execute(Runnable task, long startTimeout) {
Assert.notNull(task, "Runnable must not be null");
Runnable taskToUse = (this.taskDecorator != null
? this.taskDecorator.decorate(task) : task);
// doExecute(...) ɻķ
if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
this.concurrencyThrottle.beforeAccess();
doExecute(new ConcurrencyThrottlingRunnable(taskToUse));
}
else {
doExecute(taskToUse);
}
}
/**
* ɻķ
* Ӵᴴ´ִûʹ̳߳
*/
protected void doExecute(Runnable task) {
// Կﴴ̣߳߳
Thread thread = (this.threadFactory != null
? this.threadFactory.newThread(task) : createThread(task));
thread.start();
}
Կ SimpleAsyncTaskExecutor Уᴴµִ߳
ܻܲȡִأͨԷִ֣ĻȡΪ null
ִ invokeListener(...) ʱֱӵõģ
...
else {
invokeListener(listener, event);
}
...
getApplicationListeners(...)˵ȡܼ¼ļΪ AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent, ResolvableType)
/**
* 裺
* 1\. ӻлȡܻȡֱӷ
* 2\. ܴӻлȡ retrieveApplicationListeners(...) ȡ
*/
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);
// 1\. ӻлȡ
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)))) {
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
// 2\. ȡǹؼ
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
ųؼ
retrieveApplicationListeners(...) ȡǼ retrieveApplicationListeners(...)
/**
* ȡ
*
*/
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType,
@Nullable ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.retrievalMutex) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
// listeners лȡܴǰ¼ lister
for (ApplicationListener<?> listener : listeners) {
// жϵǰlistenerǷִ֧event
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
// listenerBeans лȡܴǰ¼ lister
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
// жϵǰ listenerBeanName Ƿܼ¼
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
// лȡӦbean¼ǰʼ
ApplicationListener<?> listener = beanFactory.getBean(
listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener)
&& supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
// עⵥǵ
if (beanFactory.isSingleton(listenerBeanName)) {
retriever.applicationListeners.add(listener);
}
else {
retriever.applicationListenerBeans.add(listenerBeanName);
}
}
allListeners.add(listener);
}
}
else {
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
retriever.applicationListeners.remove(listener);
}
allListeners.remove(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
}
}
}
//
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
retriever.applicationListeners.clear();
retriever.applicationListeners.addAll(allListeners);
}
return allListeners;
}
...
}
AbstractApplicationContext#registerListeners Уעʱ ע
retrieveApplicationListeners() гֵ listeners listenerBeans Ǵ͵ļġ
ϷȻе㳤dz
listenersһ supportsEvent(listener, eventType, sourceType) жϵǰ listener ܷ¼listenerBeansһ supportsEvent(beanFactory, listenerBeanName, eventType) жϵǰ listener ܷ¼ĴȽϸӣͲһһзˣĴ˼·
Ӵ listener listenerBeanName ȡ listener Classlistener ֻ listener.getClass() ɣlistenerBeanName ͨ beanFactory.getType(listenerBeanName) ȡ
ȡ listener ¼ͣһģ
public class MyApplicationEventListener
implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
...
}
}
ǿȡ MyApplicationEvent
// Щjdkṩ
ParameterizedType parameterizedType = (ParameterizedType)
MyApplicationEventListener.class.getGenericInterfaces()[0];
Class<?> type = (Class)parameterizedType.getActualTypeArguments()[0];
Ȼspring ڴⲿʱرӣϾ MyApplicationEventListener ͬʱʵ˶ӿڣ MyApplicationEventListener ĸ - - -... ӿڲ ApplicationListenerЩҪǵ
ȡܼ¼ˣжϵǰжϼǷܼ¼ˣspring ƥķΪ ResolvableType#isAssignableFrom(ResolvableType)עʵ Class.isAssignableFrom ĹܣͬʱԴϵķҲʵ Class.isAssignableFrom Ĺܡ
invokeListener(...)ڵüˣ£
/**
* ִм
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
// յõ doInvokeListener(...)
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
/**
* ִвյõ ApplicationListener#onApplicationEvent
*/
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// ʡ־ӡ
}
else {
throw ex;
}
}
}
һܼDZһȡļһ onApplicationEvent(...)
ҪעǣǰȡִķУᵽ getTaskExecutor() ĽΪ null invokeListener(...) ֱִеģûһִ߳УҪע⡣
spring Уɻᷢ ContextRefreshed ¼
Ҫ¼ҲʮּӦ Listener £
@Component
public class ContextRefreshedListener
implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("");
}
}
һʼΪ¼
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext();
context.register(Demo08Config.class);
// ¼ǰ
context.publishEvent(new MyApplicationEvent(
Thread.currentThread().getName() + " | Զ¼ ..."));
context.refresh();
кᱨ
ӴϢ˵㲥δʼ
ô㲥ʼأǰķ֪ refresh() ̵ĵ 8 ¼ķڵ 10 һ¼ֻڵ 9 ˣ
Կ¼Ϊ onRefresh() չģ
¼ķҲͼˣ
ApplicationContext context =
new AnnotationConfigApplicationContext(Demo08Config.class) {
@Override
public void onRefresh() {
// ¼
publishEvent(new MyApplicationEvent(
Thread.currentThread().getName() + " | Զ¼ ..."));
}
};
ǰԴ¼ִͬһ߳неģ demo нҲܿ
ǰѾ㲥¼ʱȻȡ executor executor ڣ executor ִУֱִУ㲥е executor Ϊ null˺ۣҪʵ첽ִУҪڹ㲥 executor ԡ
ǰͬҲspring ڳʼ㲥ʱжǷڹ㲥beanName Ϊ applicationEventMulticasterʹ SimpleApplicationEventMulticaster ĬϵĹ㲥
һֻҪԶ beanName Ϊ applicationEventMulticaster bean У
@Configuration
@ComponentScan
public class Demo08Config {
/**
* Զ㲥
* ע⣺ƱΪ applicationEventMulticaster
*/
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster applicationEventMulticaster
= new SimpleApplicationEventMulticaster();
// SimpleAsyncTaskExecutor springṩ첽ִ
applicationEventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
return applicationEventMulticaster;
}
}
SimpleApplicationEventMulticaster ʹ spring ṩ첽ִSimpleAsyncTaskExecutorУ£
SimpleAsyncTaskExecutor-2 | main | Զ¼ ...
Կ̲߳߳ͬһˡ
鵽꣬ǰѾ SimpleAsyncTaskExecutor ִйִ̣ʱϴ̣߳
protected void doExecute(Runnable task) {
// Կﴴ̣߳߳
Thread thread = (this.threadFactory != null
? this.threadFactory.newThread(task) : createThread(task));
thread.start();
}
100 ¼
for(int i = 0; i < 100; i++) {
context.publishEvent(new MyApplicationEvent(
Thread.currentThread().getName() + " | Զ¼ ..."));
}
н
SimpleAsyncTaskExecutor-2 | main | Զ¼ ...
SimpleAsyncTaskExecutor-3 | main | Զ¼ ...
SimpleAsyncTaskExecutor-4 | main | Զ¼ ...
...
SimpleAsyncTaskExecutor-99 | main | Զ¼ ...
SimpleAsyncTaskExecutor-100 | main | Զ¼ ...
SimpleAsyncTaskExecutor-101 | main | Զ¼ ...
Կÿһ¼ᴴһִ߳У̱߳˱ԴƵشһ˷ѣ߳أ̳߳ء
ǿ SimpleApplicationEventMulticaster#setTaskExecutor IJ java.util.concurrent.Executorͱüˣֱʹ jdk ṩ̳߳أ
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster applicationEventMulticaster
= new SimpleApplicationEventMulticaster();
// ʹjdkṩ̳߳
applicationEventMulticaster.setTaskExecutor(Executors.newFixedThreadPool(4));
return applicationEventMulticaster;
}
ʹõ jdK ṩ newFixedThreadPool 4 ̣߳У£
pool-1-thread-2 | main | Զ¼ ...
pool-1-thread-3 | main | Զ¼ ...
pool-1-thread-4 | main | Զ¼ ...
pool-1-thread-4 | main | Զ¼ ...
pool-1-thread-1 | main | Զ¼ ...
pool-1-thread-3 | main | Զ¼ ...
pool-1-thread-3 | main | Զ¼ ...
pool-1-thread-2 | main | Զ¼ ...
pool-1-thread-1 | main | Զ¼ ...
pool-1-thread-3 | main | Զ¼ ...
...
Կʼֻ 4 ߳ڹ㲥¼
Щ淶Уǽֱֹʹ jdk ṩ̵߳ijأǸᳫԶ̳߳أ㣬ڱIJ̳߳ؼģ˾ͼʹ jdk ṩ߳ʾ¡
ʵϣǰṩʾ demo Զ¼Ͳظˡ
ķ spring ¼ƣ¼Ĵ¼㲥ҴԴijʼ¼ķ̡
ԭӣhttps://my.oschina.net/funcy/blog/4713339 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע