目录
1、观察者模式
2、Spring中的观察者
2.1、事件(ApplicationEvent)
2.2、事件发布(ApplicationContext)
2.3、事件监听(ApplicationListener)
2.4、事件管理(ApplicationEventMulticaster)
3、demo
3.1、事件任务类
3.2、事件
3.3、事件监听器
3.3.1、继承ApplicationListener接口
3.3.2、@EventListener注解
3.4、事件发布
3.5、启动类
3.6、注意事项
4、原理简介
4.1、广播器
4.2、注册广播器和监听器
4.2.1、初始化事件广播器(initApplicationEventMulticaster)
4.2.2、注册监听器(registerListeners)
4.3、事件广播
4.3.1、publistEvent
4.3.2、multicastEvent
包含观察者和目标(被观察者)两种对象。
目标和观察者之间存在一对多的关系,通过建立目标与观察者之间的联系,当目标的某个状态发生变化时,所有与之关联的观察者都会得到通知并执行各自的任务。
也叫作发布-订阅模式:
优点:降低了目标与观察者之间的耦合关系。
缺点:目标与观察者之间没有完全解耦,还可能出现循环引用;当观察者对象很多时,通知的发布可能会很耗时。
事件本身,ApplicationEvent是所有事件的弗雷,可以用来传递数据。
Spring内置事件如下:
通过ApplicationEventPublisher中的publishEvent发布事件。
观察者,监听事件。事件发布后,会通知观察者执行监听器中的业务逻辑。
/**
* 用户
*/
@Data
@Builder
public class User {
private String name;
private int age;
}
/**
* 用戶注册事件
*/
@Getter
public class UserRegisterEvent extends ApplicationEvent{
private User user;
public UserRegisterEvent(User user) {
super("user-register-event");
this.user = user;
}
}
/**
* 继承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() + "]<18,授予未成年权限");
}}
@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() + "]注册完成");
}
}
@SpringBootApplication
@EnableAsync
@EnableTransactionManagement
public class BootstrapApplication {
public static void main(String[] args) {
SpringApplication.run(BootstrapApplication.class, args);
}
}
@EnableTransactionManagement开启事务支持,@TransactionalEventListener标识事务监听器。
发布事件的操作必须在事务(@Transactional)内进行,否则监听器不会生效,除非将fallbackExecution标志设置为true(@TransactionalEventListener(fallbackExecution = true))
可以配置在事务的哪个阶段来监听事务(默认在事务提交后监听),@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)。
@EnableAsync开启异步支持,@Async标识监听器异步处理。
开启异步执行后,方法的异常不会抛出,只能在方法内部处理。
@Order控制多个监听器的执行顺序,值越小,监听器越先执行。
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);
}
}
}
通过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);
}
}
}
以上内容为个人学习理解,如有问题,欢迎在评论区指出。
部分内容截取自网络,如有侵权,联系作者删除。