博客背景
在一次开发过程中,提出来这样一个需求:需要定时任务执行一个操作,正常配置了spring的定时任务以后,发现第一次执行也需要等项目跑起来以后的相应的间隔时间才会执行,这样是不符合应用场景的,真正需求是需要在项目刚刚启动的时候就执行一次定时任务,然后在接下来,按照spring定时任务的间隔进行执行,那么这样怎么处理呢?第一反应肯定就是监听器,去监听web容器以及spring的基础配置加载完成,然后触发一个事件。
正文
spring事件机制
- ApplicationListener 就是我们的 Observer,需要到容器中注册。他要关心他所关心的 ApplicationEvent 。一般有如下代码:if (event instanceof BlackListEvent) {}
- ApplicationEventMulticaster是我们的SUBJECT一个代理。他会管理我们的ApplicationListener 。
- ApplicationEvent 是事件,它就是媒介,充当介质的作用。
除了我们可以自己实现spring容器的事件外,Spring也提供了几个内置事件:
1. ContextRefreshedEvent:ApplicationContext容器初始化或者刷新时触发该事件。
2. ContextStartedEvent:当使用ConfigurableApplicationContext接口的start()方法启动ApplicationContext容器时触发该事件。
3. ContextClosedEvent:当使用ConfigurableApplicationContext接口的close()方法关闭ApplicationContext容器时触发该事件。
4. ContextStopedEvent: 当使用ConfigurableApplicationContext接口的stop()方法停止ApplicationContext容器时触发该事件。
在spring中,容器管理所有的 bean。是ApplicationEvent 驱动的,一个ApplicationEvent publish了,观察这个事件的监听者就会送到通知。
本文着重介绍 ContextRefreshedEvent
ApplicationContext容器初始化或者刷新时触发该事件
自定义的监听器
package com.mu.common.listener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import com.mu.common.access_token.AccessToken;
@Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private AccessToken token;
@Override
public void onApplicationEvent(ContextRefreshedEvent ev) {
// 防止重复执行。
if (ev.getApplicationContext().getParent() == null) {
token.test();
}
}
}
配置方式:
在web.xml中添加如下:
<!-- 自定义的监听器 -->
<listener>
<listener-class>com.mu.common.listener.MyListener</listener-class>
</listener>
至于其他的监听器,实现方式都一样,具体的实现内容按照各自的需求去实现就好了。