Spring源码之事件管理与发布
作者:互联网
在AbstractApplicationContext.refresh() 方法中,初始化了一个事件管理类(或事件管理器)。
// Initialize event multicaster for this context.
// TODO 初始化事件管理类,在单例池中创建了一个SimpleApplicationEventMulticaster类
initApplicationEventMulticaster();
进入 initApplicationEventMulticaster() 方法:
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);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 在这new了一个SimpleApplicationEventMulticaster事件管理类
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
this.applicationEventMulticaster = simpleApplicationEventMulticaster;
// 把这个事件管理类注册到beanFactory中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
回到refresh() 方法,这里有一个registerListeners() 方法:
// Check for listener beans and register them.
// 往事件管理类中注册事件类,核心代码在这里
registerListeners();
进入 registerListeners() 方法:
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 从beanFactory中拿到一个ApplicationListener的实例
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
// 把这个BeanName加入到事件观察者(监听)容器applicationListenerBeans中,
// 当事件发布时通知这些观察者
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
事件发布真正调用的方法是 AbstractApplicationContext.publishEvent() 方法,
该方法是ApplicationEventPublisher接口的方法,AbstractApplicationContext进行了重写:
@Override
public void publishEvent(ApplicationEvent event) {
// 事件发布
publishEvent(event, null);
}
进入publishEvent() 方法:
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// TODO 拿到事件管理类,里面管理了多个观察者
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
进入multicastEvent() 方法:
所属类:org.springframework.context.event.SimpleApplicationEventMulticaster
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 if (this.applicationStartup != null) {
StartupStep invocationStep = this.applicationStartup.start("spring.event.invoke-listener");
invokeListener(listener, event);
invocationStep.tag("event", event::toString);
if (eventType != null) {
invocationStep.tag("eventType", eventType::toString);
}
invocationStep.tag("listener", listener::toString);
invocationStep.end();
}
else {
// 调用Listener,通知监听者
invokeListener(listener, event);
}
}
}
进入invokeListener() 方法:
所属类:org.springframework.context.event.SimpleApplicationEventMulticaster
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
// 着重看这里
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
进入doInvokeListener() 方法:
所属类:org.springframework.context.event.SimpleApplicationEventMulticaster
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 去调用所有事件管理者的onApplicationEvent()方法,
// 自定义监听者实现了ApplicationListener接口,会重写onApplicationEvent()方法
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
应用举例:
1.自定义事件类,须继承ApplicationEvent:
/**
* @ClassName: OrderCreateEvent
* @Description: 订单创建活动事件
* @Author: Kaisheng Du
* @Date: 2021/9/22 13:52
* @Version: 1.0
*/
public class OrderCreateEvent extends ApplicationEvent {
private String name;
//消息参数
private List<String> contentList;
public OrderCreateEvent(Object source, String name, List<String> contentList) {
super(source);
this.name = name;
this.contentList = contentList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getContentList() {
return contentList;
}
public void setContentList(List<String> contentList) {
this.contentList = contentList;
}
}
2. 自定义事件监听类(可以定义多个):
/**
* @ClassName: SmsListener
* @Description: 短信监听器
* @Author: Kaisheng Du
* @Date: 2021/9/22 13:55
* @Version: 1.0
*/
@Component
public class SmsListener implements ApplicationListener<OrderCreateEvent> {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//发送短信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by sms");
}
}
/**
* @ClassName: SmsListener
* @Description: 微信监听器
* @Author: Kaisheng Du
* @Date: 2021/9/22 13:55
* @Version: 1.0
*/
@Component
public class WechatListener implements ApplicationListener<OrderCreateEvent> {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//发送微信
System.out.println(event.getContentList().get(0) + ",您的订单:" + event.getContentList().get(1) + "创建成功! ----by wechat");
}
}
3.事件发布
public interface OrderService {
void saveOrder();
}
/**
* @ClassName: OrderServiceImpl
* @Description: 保存订单后发送通知
* @Author: Kaisheng Du
* @Date: 2021/9/22 13:50
* @Version: 1.0
*/
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private ApplicationContext applicationContext;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void saveOrder() {
// 1.创建订单
System.out.println("订单创建成功");
// 2.发布事件
ArrayList<String> contentList = new ArrayList<>();
contentList.add("kieasar");
contentList.add("123456789");
OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this, "订单创建", contentList);
// ApplicationContext是我们的事件容器上层,我们发布事件,也可以通过此容器完成发布
applicationContext.publishEvent(orderCreateEvent);
// 也可以通过下面方法进行事件发布
// applicationEventPublisher.publishEvent(orderCreateEvent);
}
class Person{
}
}
案例测试:
@Test
public void testEvent() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
OrderService orderService = (OrderService) applicationContext.getBean("orderServiceImpl");
// 调用保存订单方法
orderService.saveOrder();
}
标签:contentList,Spring,void,event,listener,源码,事件,null,public 来源: https://blog.csdn.net/qq_40213907/article/details/120670274