监听器是典型的观察者设计模式的实现,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被销毁时调用
import cn.gamer.mapper.UserMapper; import cn.gamer.model.User; import cn.gamer.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 gamer * @date 2019/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("gamer"); System.out.println(JsonUtils.toJson(user2)); } @Override public void contextDestroyed(ServletContextEvent event) { System.out.println("*************ServletContextListener stop************"); } }
如果是普通Spring应用,则还需要配置web.xml,比如:
<listener> <listener-class>cn.gamer.listener.TestListener</listener-class> </listener>
ApplicationListener
依赖于Spring框架,在Spring启动时调用。在普通Spring应用中一般监听ContextRefreshedEvent事件。而在Spring Boot中可以监听多种事件,比如:
- ApplicationStartedEvent:spring boot启动监听类
- ApplicationEnvironmentPreparedEvent:环境事先准备
- ApplicationPreparedEvent:上下文context准备时触发
- ApplicationReadyEvent:上下文已经准备完毕的时候触发
- ApplicationFailedEvent:该事件为spring boot启动失败时的操作
package cn.gamer.listener; import cn.gamer.mapper.UserMapper; import cn.gamer.model.User; import cn.gamer.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 gamer * @date 2019/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("gamer"); System.out.println(JsonUtils.toJson(user2)); } }
import cn.gamer.mapper.UserMapper; import cn.gamer.model.User; import cn.gamer.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 gamer * @date 2019/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("gamer"); System.out.println(JsonUtils.toJson(user2)); } }
需要注意的是,在普通Spring环境中,基于ApplicationListener的监听器的onApplicationEvent方法可能会被执行多次,所以需要添加以下判断:
@Override public void onApplicationEvent(ContextRefreshedEvent event) { //root application context 没有parent if(event.getApplicationContext().getParent() == null){ //ignore } }