SimpleApplicationEventMulticaster学习

简介

SimpleApplicationEventMulticaster 是 Spring 框架中负责事件广播的一个类。它实现了 ApplicationEventMulticaster 接口,该接口定义了发布(广播)应用事件的方法。在 Spring 应用中,当某个事件发生时(比如,某个 bean 的状态发生了改变),可以使用 ApplicationEventMulticaster 来通知所有对该事件感兴趣的监听器。

SimpleApplicationEventMulticaster 是一个简单的实现,它维护了一个事件监听器的列表,并在事件发生时遍历这个列表,调用每个监听器的相应方法来处理事件。

SimpleApplicationEventMulticaster 的主要特点包括:

  • 注册监听器:通过 addApplicationListener 方法,可以向广播器注册事件监听器。监听器必须实现 ApplicationListener 接口,并指定它们感兴趣的事件类型。
  • 广播事件:使用 multicastEvent 方法来广播事件。当这个方法被调用时,它会遍历所有注册的监听器,并调用那些能够处理该事件的监听器的 onApplicationEvent 方法。
  • 默认事件类型:SimpleApplicationEventMulticaster 默认处理所有实现了 ApplicationEvent 接口的事件。
  • 任务执行器:SimpleApplicationEventMulticaster 还可以配置一个 TaskExecutor,用于异步地广播事件。如果未设置 TaskExecutor,事件将同步广播。
  • 错误处理:如果事件处理过程中发生异常,SimpleApplicationEventMulticaster 会记录一个错误消息,但不会抛出异常或中断事件广播。

在 Spring 容器中,SimpleApplicationEventMulticaster 通常被自动配置为单例 bean,并且可以通过 @Autowired 注解注入到其他组件中,以便发布事件。同时,Spring 容器也会自动注册一些内置的事件监听器,用于处理如上下文刷新、上下文关闭等内置事件。

源码

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	@Nullable
	private Executor taskExecutor;

	@Nullable
	private ErrorHandler errorHandler;

	@Nullable
	private volatile Log lazyLogger;


	/**
	 * Create a new SimpleApplicationEventMulticaster.
	 */
	public SimpleApplicationEventMulticaster() {
	}

	/**
	 * Create a new SimpleApplicationEventMulticaster for the given BeanFactory.
	 */
	public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
		setBeanFactory(beanFactory);
	}

	public void setTaskExecutor(@Nullable Executor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	/**
	 * Return the current task executor for this multicaster.
	 */
	@Nullable
	protected Executor getTaskExecutor() {
		return this.taskExecutor;
	}

	public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
		this.errorHandler = errorHandler;
	}

	/**
	 * Return the current error handler for this multicaster.
	 * @since 4.1
	 */
	@Nullable
	protected ErrorHandler getErrorHandler() {
		return this.errorHandler;
	}

	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		//存在executor则异步执行
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {//否则同步执行
				invokeListener(listener, event);
			}
		}
	}

	private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
		return ResolvableType.forInstance(event);
	}

	/**
	 * Invoke the given listener with the given event.
	 * @param listener the ApplicationListener to invoke
	 * @param event the current event to propagate
	 * @since 4.1
	 */
	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);
		}
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	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()) ||
					(event instanceof PayloadApplicationEvent &&
							matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception.
				Log loggerToUse = this.lazyLogger;
				if (loggerToUse == null) {
					loggerToUse = LogFactory.getLog(getClass());
					this.lazyLogger = loggerToUse;
				}
				if (loggerToUse.isTraceEnabled()) {
					loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

}

示例

// 自定义事件  
public class CustomEvent extends ApplicationEvent {  
    private String message;  
  
    public CustomEvent(Object source, String message) {  
        super(source);  
        this.message = message;  
    }  
  
    public String getMessage() {  
        return message;  
    }  
}  
  
// 自定义事件监听器  
public class CustomEventListener implements ApplicationListener<CustomEvent> {  
    @Override  
    public void onApplicationEvent(CustomEvent event) {  
        System.out.println("Received custom event - " + event.getMessage());  
    }  
}  
  
// 在某个组件中发布事件  
@Service  
public class EventPublishingService {  
  
    private final ApplicationEventMulticaster applicationEventMulticaster;  
  
    @Autowired  
    public EventPublishingService(ApplicationEventMulticaster applicationEventMulticaster) {  
        this.applicationEventMulticaster = applicationEventMulticaster;  
    }  
  
    public void publishEvent(String message) {  
        CustomEvent customEvent = new CustomEvent(this, message);  
        applicationEventMulticaster.multicastEvent(customEvent);  
    }  
}

在这个示例中,CustomEvent 是一个自定义事件,CustomEventListener 是一个监听这个事件的监听器。EventPublishingService 是一个服务类,它使用注入的 ApplicationEventMulticaster 来发布 CustomEvent 事件。当 publishEvent 方法被调用时,所有注册的 CustomEventListener 将会收到并处理这个事件。

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
de.schlichtherle.license.LicenseContentException: exc.licenseHasExpired at de.schlichtherle.license.LicenseManager.validate(LicenseManager.java:629) at com.keyunzhihui.auth.license.CustomLicenseManager.validate(CustomLicenseManager.java:101) at com.keyunzhihui.auth.license.CustomLicenseManager.install(CustomLicenseManager.java:83) at de.schlichtherle.license.LicenseManager.install(LicenseManager.java:406) at de.schlichtherle.license.LicenseManager.install(LicenseManager.java:382) at com.keyunzhihui.auth.license.LicenseVerify.install(LicenseVerify.java:44) at com.keyunzhihui.auth.license.LicenseVerify.install(LicenseVerify.java:33) at com.keyunzhihui.auth.listener.LicenseRunListener.onApplicationStartEvent(LicenseRunListener.java:59) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344) at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229) at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:105) at org.springframework.boot.SpringApplicationRunListeners.lambda$started$5(SpringApplicationRunListeners.java:75) at java.util.ArrayList.forEach(ArrayList.java:1259) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:117) at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:111) at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:75) at org.springframework.boot.SpringApplication.run(SpringApplication.java:345) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1318) at com.kyzh.business.doorlock.DoorLockServiceApplication.main(DoorLockServiceApplication.java:42)
07-08

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值