SpringBoot 创建和使用“事件”
一、spring boot 的事件由 ApplicationEvent 类及其子类表示。您可以创建自己的事件,只需扩展 ApplicationEvent 类并定义自己的构造函数即可。
public class DomainEvent extends ApplicationEvent {
private final DomainListener domainListener;
public DomainEvent(DomainListener domainListener) {
super(domainListener);
this.domainListener = domainListener;
}
public DomainListener getDomainListener() {
return domainListener;
}
}
//事件中使用到的类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DomainListener {
private String name;
}
二、事件的监听
事件的监听有两种实现方法
(1)实现接口ApplicationListener
@Component
@Slf4j
public class ListenerService implements ApplicationListener<DomainEvent> {
@Override
public void onApplicationEvent(DomainEvent event) {
log.info("监听到事件:" + event.getDomainListener().getName());
}
}
(2)使用 @EventListener 注解,一般推荐使用这个注解
@Component
@Slf4j
public class EventCompoment {
@Async
@SneakyThrows
@EventListener(DomainEvent.class)
public void handleEvent(DomainEvent event) {
Thread.sleep(5000);
log.info("handleEvent监听到事件:"+ event.getDomainListener().getName());
// int i = 1 / 0;
}
}
三、事件的发布(推送)
需要引入spring boot 自带的 ApplicationEventPublisher
@Service
@RequiredArgsConstructor
@Slf4j
public class EventService {
public final ApplicationEventPublisher publisher;
public void test() {
DomainListener domainListener = new DomainListener();
domainListener.setName("test");
publisher.publishEvent(new DomainEvent(domainListener));
log.info("发布事件结束!");
}
}
⚠️:一些注意事项
如果我们不进行特殊处理,事件都是同步的,可能会影响我们主程序的效率,所以一般有需要的情况下
我们会使用异步处理这个事件
/** @Async 开启异步的方法上:**/
@Async
@SneakyThrows
@EventListener(DomainEvent.class)
public void handleEvent(DomainEvent event) {}
@SneakyThrows ::
在 Java 中,异常分为受检查异常(checked exception)和未受检查异常(unchecked exception)两种。
受检查异常是指在编译时就必须处理的异常,如果不处理则会导致编译错误。这种异常通常是由于外部因素(如 I/O 错误、网络连接问题等)导致的,而开发人员需要在代码中显式地处理这些异常。例如,IOException、SQLException 等都是受检查异常。
未受检查异常是指在编译时不需要处理的异常,这种异常通常是由于程序内部逻辑错误或者其他不可预知的因素导致的。在程序运行时,如果出现未受检查异常,则程序会抛出该异常并终止运行。例如,NullPointerException、ArrayIndexOutOfBoundsException 等都是未受检查异常。
当程序中出现受检查异常时,开发人员必须在代码中显式地处理这些异常,否则程序无法通过编译。而当程序中出现未受检查异常时,开发人员可以选择在代码中显式地处理这些异常,也可以让程序在运行时抛出异常并终止运行。
@SneakyThrows 注解可以将受检查异常转换为未受检查异常并抛出,从而避免了在代码中显式地处理这些异常的繁琐过程。但是,使用 @SneakyThrows 注解也可能会隐藏代码中的潜在问题,因此需要谨慎使用。
@EnableAsync ::在主类添加这个注解,允许开启异步
⚠️:在spring boot应用程序中使用事件,会重新开始一个上下文,事件中的上下文,和原有上下文不相通
⚠️:在 Spring Boot 应用中,事件监听器中的上下文和系统原有的上下文是不同的。这是因为在事件监听器中,Spring Boot 使用了一个新的上下文来处理事件。这个上下文是在事件被发布时创建的,它与系统原有的上下文是相互独立的。
可以通过注入一个 ApplicationContext 对象来获取系统原有的上下文,并使用该对象来获取需要的 bean。
@Component
public class MyEventListener {
@Autowired
private ApplicationContext applicationContext;
@EventListener
public void handleMyEvent(MyEvent event) {
// 在事件监听器中访问系统原有的上下文中的 bean
MyService myService = applicationContext.getBean(MyService.class);
myService.doSomething();
}
}