Spring之事件监听与发布

igxiaoshan Lv5

ApplicationListener—事件监听

属于Spring框架对Java中实现的监听者模式的一种框架实现

ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。

如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。

其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。

同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。

内置事件

序号 Spring 内置事件 & 描述
1 ContextRefreshedEvent
ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
2 ContextStartedEvent
当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
3 ContextStoppedEvent
当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
4 ContextClosedEvent
当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
5 RequestHandledEvent
这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public class UserEvent extends ApplicationEvent {
private String address;

private String text;

public UserEvent(Object source) {
super(source);
}

public UserEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
   //......address和text的setter、getter
}
1
2
3
4
5
6
7
8
9
@Component
public class UserListener implements ApplicationListener<UserEvent> {
@Override
public void onApplicationEvent(UserEvent event) {
System.out.println("---> userEvent 监听 address " + event.getAddress());
System.out.println("---> userEvent 监听 test " + event.getText());
System.out.println("---> userEvent 监听 source " + event.getSource());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootTest
public class EventTest {

@Autowired
private WebApplicationContext webApplicationContext;

@Test
public void listenerTest(){
UserEvent event = new UserEvent("hello", "abc@qq.com", "this is a test");
webApplicationContext.publishEvent(event);
}
}

容器监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Slf4j
@Component
public class ApplicationEventListener implements ApplicationListener<ApplicationEvent> {

@Override
public void onApplicationEvent(ApplicationEvent event) {
// 在这里可以监听到Spring Boot的生命周期
if (event instanceof ApplicationEnvironmentPreparedEvent) {
// 初始化环境变量
log.debug("初始化环境变量");
} else if (event instanceof ApplicationPreparedEvent) {
// 初始化完成
log.debug("初始化环境变量完成");
} else if (event instanceof ContextRefreshedEvent) {
// 应用刷新,当ApplicationContext初始化或者刷新时触发该事件。
log.debug("应用刷新");
} else if (event instanceof ApplicationReadyEvent) {
// 应用已启动完成
log.debug("应用已启动完成");
} else if (event instanceof ContextStartedEvent) {
// 应用启动,Spring2.5新增的事件,当容器调用ConfigurableApplicationContext的 Start()方法开始/重新开始容器时触发该事件。
log.debug("应用启动");
} else if (event instanceof ContextStoppedEvent) {
// 应用停止,Spring2.5新增的事件,当容器调用ConfigurableApplicationContext 的Stop()方法停止容器时触发该事件。
log.debug("应用停止");
} else if (event instanceof ContextClosedEvent) {
// 应用关闭,当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有 单例Bean都被销毁。
log.debug("应用关闭");
} else {
}
}
}

ApplicationEventPublisherAware—事件发布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

@Service
public class UserRegisterService implements ApplicationEventPublisherAware {

private ApplicationEventPublisher applicationEventPublisher;

public boolean register(User user) {

//用户注册
System.out.println("[service]用户[" + user + "]注册成功!");

//消息发布
applicationEventPublisher.publishEvent(new UserEvent(this, user));
return true;
}

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
1
2
3
4
5
6
7
8
9
10
11

@Component
public class EventListener implements ApplicationListener<UserRegisterEvent> {

@Override
public void onApplicationEvent(UserRegisterEvent event) {

System.out.println("---> userEvent 监听 address " + event.getAddress());
System.out.println("---> userEvent 监听 test " + event.getText());
}
}