Spring中的ApplicationListener和ServletContextListener的区别

监听器是典型的观察者设计模式的实现,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
    }
}

 

posted @ 2020-10-10 13:38  47号Gamer丶  阅读(947)  评论(0编辑  收藏  举报