2.4、事件管理(ApplicationEventMulticaster)
4.2.1、初始化事件广播器(initApplicationEventMulticaster)
4.2.2、注册监听器(registerListeners)
包含观察者和目标(被观察者)两种对象。
目标和观察者之间存在一对多的关系,通过建立目标与观察者之间的联系,当目标的某个状态发生变化时,所有与之关联的观察者都会得到通知并执行各自的任务。
也叫作发布-订阅模式:
- 订阅:观察者向目标对象注册自己,告诉目标对象自己在观察它。
- 发布:当目标对象的状态发生改变时,向它所有的观察者发送通知,观察者收到通知后执行各自的操作。
优点:降低了目标与观察者之间的耦合关系。
缺点:目标与观察者之间没有完全解耦,还可能出现循环引用;当观察者对象很多时,通知的发布可能会很耗时。
2.1、事件(ApplicationEvent)
事件本身,ApplicationEvent是所有事件的弗雷,可以用来传递数据。 Spring内置事件如下:
- ContextRefreshedEvent: ApplicationContext初始化或刷新,或者说在容器实例化(refresh())时发布事件;
- ContextStartedEvent:Spring容器启动时,即调用ConfigurableApplicationContext接口的start()时发布事件;
- ContextStoppedEvent:Spring容器停止时,即调用ConfigurableApplicationContext接口的stop()时发布事件,关闭的容器可以通过start()重启;
- ContextClosedEvent:Spring容器关闭时,即调用ConfigurableApplicationContext接口的close()时发布事件,所有的Bean已被销毁,无法重启容器;
- RequestHandledEvent:当一个请求被处理完成时发布事件。
2.2、事件发布(ApplicationContext)
通过ApplicationEventPublisher中的publishEvent发布事件。
2.3、事件监听(ApplicationListener)
观察者,监听事件。事件发布后,会通知观察者执行监听器中的业务逻辑。
2.4、事件管理(ApplicationEventMulticaster)
- 用于事件监听器的注册和事件的广播。
- 注册:将监听器与事件关联。
- 广播:事件发布后,通知与事件关联的所有监听器。
3.1、事件任务类
/**
* 用户
*/
@Data
@Builder
public class User {
private String name;
private int age;
}
3.2、事件
/**
* 用戶注册事件
*/
@Getter
public class UserRegisterEvent extends ApplicationEvent{
private User user;
public UserRegisterEvent(User user) {
super("user-register-event");
this.user = user;
}
}
3.3、事件监听器
/**
* 继承ApplicationListener接口监听事件
* 监听器:当有用户注册事件发生时,记录日志
*/
@Component
@Slf4j
public class RecordUserRegisterListener implements ApplicationListener { @Async
@SneakyThrows
@Override
public void onApplicationEvent(UserRegisterEvent event) {
User user = event.getUser();
Thread.sleep(3000L);
log.info("用户[" + user.getName() + "]注册成功,记录日志");
}
}
/**
* @EventListener注解监听事件
*/
@Component
@Slf4j
public class GlobalEventListener {
@EventListener(classes = UserRegisterEvent.class, condition = "#event.user.age >= 18")
public void onUserGrant1(UserRegisterEvent event) {
User user = event.getUser();
log.info("用户[" + user.getName() + "]注册成功,年龄[" + user.getAge() + "]>=18,授予成人权限");
}
@EventListener(classes = UserRegisterEvent.class, condition = "#event.user.age < 18")
public void onUserGrant2(UserRegisterEvent event) {
User user = event.getUser();
log.info("用户[" + user.getName() + "]注册成功,年龄[" + user.getAge() + "]
3.4、事件发布
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private ApplicationEventPublisher publisher;
@GetMapping("/register")
public void register(String name, int age) {
User user = User.builder().name(name).age(age).build();
// 事件发布
publisher.publishEvent(new UserRegisterEvent(user));
log.info("用户[" + user.getName() + "]注册完成");
}
}
3.5、启动类
@SpringBootApplication
@EnableAsync
@EnableTransactionManagement
public class BootstrapApplication {
public static void main(String[] args) {
SpringApplication.run(BootstrapApplication.class, args);
}
}
3.6、注意事项
- *事务监听器
@EnableTransactionManagement开启事务支持,@TransactionalEventListener标识事务监听器。 发布事件的操作必须在事务(@Transactional)内进行,否则监听器不会生效,除非将fallbackExecution标志设置为true(@TransactionalEventListener(fallbackExecution = true)) 可以配置在事务的哪个阶段来监听事务(默认在事务提交后监听),@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)。
- *异步支持
@EnableAsync开启异步支持,@Async标识监听器异步处理。 开启异步执行后,方法的异常不会抛出,只能在方法内部处理。
- *监听器顺序
@Order控制多个监听器的执行顺序,值越小,监听器越先执行。
4.1、广播器
- ApplicationEventMulticaster接口:提供了添加/移除监听器以及广播事件给监听器的行为。
- AbstractApplicationEventMulticaster抽象类:提供了基础的监听器注册/移除以及查找能力。
- SimpleApplicationEventMulticaster类:提供了事件广播功能。
4.2、注册广播器和监听器
Spring容器初始化时,在refresh()方法中,会进行广播器和监听器的注册。
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
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 {
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
simpleApplicationEventMulticaster.setApplicationStartup(getApplicationStartup());
this.applicationEventMulticaster = simpleApplicationEventMulticaster;
// 将事件广播器作为单例bean注册到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() + "]");
}
}
}
protected void registerListeners() {
// 获取监听器然后注册到广播器中
for (ApplicationListener listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 获取bean Name数组String[] listenerBeanNames 然后注册到广播器中
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set earlyEventsToProcess = this.earlyApplicationEvents;
// 处理以前的事件,先将 earlyApplicationEvents 赋予null,然后判断 earlyEventsToProcess 如果不为空就广播出去
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
4.3、事件广播
通过ApplicationEventPublisher的publishEvent方法将事件广播出去。
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();
}
}
//如果早期事件不为null,则将事件放入早期事件集合中--说明广播器还没有实例化好
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 获取广播器进行事件广播
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
//将事件也交给父类处理
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 解析事件类型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 尝试获取任务执行器
Executor executor = getTaskExecutor();
// 获取合适的ApplicationListener,循环调用监听器的onApplicationEvent方法
for (ApplicationListener listener : getApplicationListeners(event, type)) {
// 判断executor 是否不为null
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
// 判断applicationStartup
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.onApplicationEvent,内部通过反射调用监听器方法
invokeListener(listener, event);
}
}
}
以上内容为个人学习理解,如有问题,欢迎在评论区指出。 部分内容截取自网络,如有侵权,联系作者删除。