监听器是典型的观察者设计模式的实现,Servlet和Spring中我们熟知的listeners包括:HttpSessionListener、ServletContextListener、ApplicationListener。
- HttpSessionListener:是对javax.servlet.http.HttpSession(session)的监听;
- ServletContextListener:是对javax.servlet.ServletContext(application)的监听;
- ApplicationListener:是对Spring的ApplicationContext的监听。
其中,基于ServletContextListener的监听器要比基于ApplicationListener的监听器先执行。因为前者是Tomcat/Jetty容器启动后就执行,后者需要Spring应用初始化完成后才执行。
ServletContextListener
依赖于sevlet容器,需要配置web.xml(Spring Boot只需要配置@WebListener即可,并且使用@WebListener后,可以注入bean)
- public void contextInitialized(ServletContextEvent event):在ServletContext被创建时调用
- public void contextDestroyed(ServletContextEvent event):在ServletContext被销毁时调用
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 34 35 36 37 38 39 40 41 | package cn.zifangsky.listener; import cn.zifangsky.mapper.UserMapper; import cn.zifangsky.model.User; import cn.zifangsky.utils.JsonUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; /** * 基于ServletContextListener的Listener * * @author zifangsky * @date 2018/8/13 * @since 1.0.0 */ @WebListener public class TestListener implements ServletContextListener { @Autowired private UserMapper userMapper; @Override public void contextInitialized(ServletContextEvent event) { WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()); // context.getAutowireCapableBeanFactory().autowireBean(this); System.out.println("*************ServletContextListener start************"); User user2 = userMapper.selectByUsername("zifangsky"); System.out.println(JsonUtils.toJson(user2)); } @Override public void contextDestroyed(ServletContextEvent event) { System.out.println("*************ServletContextListener stop************"); } } |
如果是普通Spring应用,则还需要配置web.xml,比如:
1 2 3 | <listener> <listener-class>cn.zifangsky.listener.TestListener</listener-class> </listener> |
ApplicationListener
依赖于Spring框架,在Spring启动时调用。在普通Spring应用中一般监听ContextRefreshedEvent事件。而在Spring Boot中可以监听多种事件,比如:
- ApplicationStartedEvent:spring boot启动监听类
- ApplicationEnvironmentPreparedEvent:环境事先准备
- ApplicationPreparedEvent:上下文context准备时触发
- ApplicationReadyEvent:上下文已经准备完毕的时候触发
- ApplicationFailedEvent:该事件为spring boot启动失败时的操作
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 | package cn.zifangsky.listener; import cn.zifangsky.mapper.UserMapper; import cn.zifangsky.model.User; import cn.zifangsky.utils.JsonUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; /** * 基于ApplicationListener的Listener * 用于容器初始化完成之后,执行需要处理的一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等 * @author zifangsky * @date 2018/8/13 * @since 1.0.0 */ @Component public class TestListener2 implements ApplicationListener<ContextRefreshedEvent> { @Autowired private UserMapper userMapper; @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("*************ApplicationListener<ContextRefreshedEvent> start************"); User user2 = userMapper.selectByUsername("zifangsky"); System.out.println(JsonUtils.toJson(user2)); } } |
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 | package cn.zifangsky.listener; import cn.zifangsky.mapper.UserMapper; import cn.zifangsky.model.User; import cn.zifangsky.utils.JsonUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; /** * 基于ApplicationListener的Listener * 用于容器初始化完成之后,执行需要处理的一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等 * @author zifangsky * @date 2018/8/13 * @since 1.0.0 */ @Component public class TestListener3 implements ApplicationListener<ApplicationReadyEvent> { @Autowired private UserMapper userMapper; @Override public void onApplicationEvent(ApplicationReadyEvent event) { System.out.println("*************ApplicationListener<ApplicationReadyEvent> start************"); User user2 = userMapper.selectByUsername("zifangsky"); System.out.println(JsonUtils.toJson(user2)); } } |
需要注意的是,在普通Spring环境中,基于ApplicationListener的监听器的onApplicationEvent方法可能会被执行多次,所以需要添加以下判断:
1 2 3 4 5 6 7 | @Override public void onApplicationEvent(ContextRefreshedEvent event) { //root application context 没有parent if(event.getApplicationContext().getParent() == null){ //ignore } } |
参考: