????Spring是基于事件驅(qū)動(dòng)模型的碎浇,事件驅(qū)動(dòng)模型也就是我們常說(shuō)的觀察者腾它,或者發(fā)布-訂閱模型。理解觀察者模式更有助于理解 Spring 事件機(jī)制碗誉,話不多說(shuō)召嘶,我們先來(lái)看一下 Spring 的事件角色的類(lèi)圖
????從此類(lèi)圖中我們可以得到以下信息:
????1.事件源:如果我們需要實(shí)現(xiàn)事件傳播的話,我們首先需要實(shí)現(xiàn)自己的事件類(lèi)去實(shí)現(xiàn) ApplicationEvent 接口哮缺。
????2.監(jiān)聽(tīng)者:需要定義自己的事件監(jiān)聽(tīng)器類(lèi)去實(shí)現(xiàn) ApplicationListener<E extends ApplicationEvent> 接口苍蔬。
????3.事件發(fā)布:需要有一個(gè)對(duì)象去發(fā)布該事件,從類(lèi)圖中我們可以了解到蝴蜓,應(yīng)用上下文 ApplicationContext 就是一個(gè)天生的事件發(fā)布源。我們通常可以 事件ApplicationEventPublisherAware接口來(lái)注入上下文中的 ApplicationEventPublisher茎匠,既可以通過(guò)它發(fā)布事件
????需要知道的是格仲,在spring源碼中 AbstractApplicationContext 持有了 ApplicationEventMulticaster引用,且通過(guò)他進(jìn)行事件的發(fā)布诵冒,默認(rèn)實(shí)現(xiàn)為 SimpleApplicationEventMulticaster凯肋。那么了解了這些,我們可以來(lái)簡(jiǎn)單實(shí)現(xiàn)一下我們的spring自定義事件:
1.定義一個(gè)類(lèi)汽馋,及源事件:
public class Order {
private String orderNo;
private String orderStatus;
private String goods;
private Date createTime;
//省略 get/set
}
//源事件
public class OrderCreateEvent extends ApplicationEvent {
private final Order order;
public OrderCreateEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() {
return order;
}
}
2.定義事件監(jiān)聽(tīng)器:
@Component
public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent> {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
System.out.printf(this.getClass().getName() + " -- ApplicationListener 接口實(shí)現(xiàn)侮东,訂單號(hào)[%s]:,商品[%s]\n",
event.getOrder().getOrderNo(), event.getOrder().getGoods());
}
}
3.定義事件發(fā)服務(wù):
@Service
public class OrderService implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
/**
* 訂單保存
*/
public void save(){
Order order = new Order();
order.setOrderNo("1");
order.setGoods("手機(jī)");
System.out.println("訂單保存成功:" + order.toString());
//發(fā)布事件
applicationEventPublisher.publishEvent(new OrderCreateEvent(this,order));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
4.編寫(xiě)測(cè)試類(lèi):
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringStudyApp.class)
public class SpringStudyTest {
@Autowired
OrderService orderService;
@Test
public void contextLoads() {
orderService.save();
}
}
????簡(jiǎn)單的幾步就實(shí)現(xiàn)了自定義的spring事件。
基于注解的事件監(jiān)聽(tīng)@EventListener:
@Component
public class OrderCreateEventListenerAnnotation {
@EventListener
public void createOrderEvent(OrderCreateEvent event) {
System.out.println(this.getClass().getName() + "--訂單創(chuàng)建事件豹芯,@EventListener注解實(shí)現(xiàn)悄雅,orderNo:" + event.getOrder().getOrderNo());
}
}
異步事件:
上面的監(jiān)聽(tīng)事件都是同步觸發(fā)的,如果想異步只需要兩步:
- 啟動(dòng)類(lèi)上添加 @EnableAsync注解铁蹈,開(kāi)啟異步支持宽闲。
- 監(jiān)聽(tīng)方法上添加 @Async注解
事件傳播機(jī)制:
當(dāng)我們監(jiān)聽(tīng)一個(gè)事件處理完成時(shí),還需要發(fā)布另一個(gè)事件握牧,一般我們想到的是調(diào)用ApplicationEventPublisher#publishEvent發(fā)布事件方法容诬,但Spring提供了另一種更加靈活的新的事件繼續(xù)傳播機(jī)制,監(jiān)聽(tīng)方法返回一個(gè)事件沿腰,也就是方法的返回值就是一個(gè)事件對(duì)象
@Component
public class OrderListener {
@EventListener
public void orderListener(Order order){
System.out.println(this.getClass().getName() + " -- 監(jiān)聽(tīng)一個(gè)訂單");
}
//事件傳播機(jī)制
// 當(dāng)我們監(jiān)聽(tīng)一個(gè)事件處理完成時(shí)览徒,還需要發(fā)布另一個(gè)事件,一般我們想到的是調(diào)用ApplicationEventPublisher#publishEvent發(fā)布事件方法颂龙,
// 但Spring提供了另一種更加靈活的新的事件繼續(xù)傳播機(jī)制习蓬,監(jiān)聽(tīng)方法返回一個(gè)事件,也就是方法的返回值就是一個(gè)事件對(duì)象厘托。
@EventListener
public OrderCreateEvent orderReturnEvent(Order order){
System.out.println(this.getClass().getName() + " -- 監(jiān)聽(tīng)一個(gè)訂單,返回一個(gè)新的事件 OrderCreateEvent");
return new OrderCreateEvent(this,order);
}
}
????這樣子我們后續(xù)通過(guò) applicationEventPublisher.publishEvent(order); 發(fā)布一個(gè) Order 類(lèi)型的參數(shù)的事件友雳,他會(huì)被上面的 orderReturnEvent 方法監(jiān)聽(tīng)到,然后最后返回一個(gè) OrderCreateEvent 事件對(duì)象铅匹,繼而觸發(fā)該事件的監(jiān)聽(tīng)押赊。
????基于事件驅(qū)動(dòng)模型可以很方便的實(shí)現(xiàn)解耦,提高代碼的可讀性和可維護(hù)性包斑,那么 Spring中是怎么進(jìn)行初始化及使用的呢流礁?我們來(lái)一探究竟。
Spring 事件源碼分析:
????我們知道 Spring 容器的初始化都會(huì)走到 AbstractApplicationContext 的 refresh() 方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// 關(guān)鍵來(lái)了罗丰,為此上下文初始化事件多播程序
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 調(diào)用子類(lèi)特殊的某些特殊的方法刷新容器
// Initialize other special beans in specific context subclasses.
onRefresh();
// 檢查偵聽(tīng)器bean并注冊(cè)它們神帅。
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
}
}
????直接來(lái)看 initApplicationEventMulticaster() 方法:
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
protected void initApplicationEventMulticaster() {
// 獲取上面初始化的 DefaultListableBeanFactory 容器
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 如果容器里找到了這個(gè)類(lèi),那么直接賦值給成員變量
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {// 初始化一個(gè) SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
????其實(shí)這個(gè)方法主要的作用是保證容器中又一個(gè)被實(shí)例化的ApplicationEventMulticaster 類(lèi)型的Bean萌抵。緊接著等待子類(lèi)特殊的刷新方法結(jié)束基本上整個(gè)容器也就初始化完成了找御。然后調(diào)用 registerListeners():
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
//注冊(cè)監(jiān)聽(tīng)器
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
// 遍歷上面這個(gè)集合元镀,將提前儲(chǔ)備好的監(jiān)聽(tīng)器添加到監(jiān)聽(tīng)器容器中
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 獲得容器中類(lèi)型是 ApplicationListener 的 beanName集合
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 發(fā)布這個(gè) earlyApplicationEvents 容器中的事件
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
// 委派上面初始化的 SimpleApplicationEventMulticaster 進(jìn)行廣播發(fā)布
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
????緊接著來(lái)看 multicastEvent(ApplicationEvent event):
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 再去通過(guò)event去獲得一個(gè)ResolvableType
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 通過(guò)事件及類(lèi)型進(jìn)行獲取事件監(jiān)聽(tīng)器進(jìn)行遍歷
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
// 當(dāng) executor 不為空,這里走的是異步事件
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
// 同步事件
else {
invokeListener(listener, event);
}
}
}
????從這里去調(diào)用 listener 的 onApplicationEvent 方法:
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
//.....省略部分代碼
}
????像容器初始化完成霎桅,AbstractApplicationContext的 finishRefresh() 方法中
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// 發(fā)布容器刷新完成事件
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
????這里所調(diào)用的 publishEvent(new ContextRefreshedEvent(this)) 最終還是走 multicastEvent(ApplicationEvent event) 方法的栖疑。這就是Spring事件的基本處理流程。