• 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
        }
    }
  • 相关阅读:
    Java GC机制详解
    程序员面试的时候如何谈薪酬待遇?
    每个程序员都会遇到的面试问题:谈谈进程和线程的区别
    面试问题:你了解Java内存结构么(Java7、8、9内存结构的区别)
    UVa 208
    山科 STUST OJ Problem B: 编写函数:String to Double (II) (Append Code)
    山科SDUST OJ Problem J :连分数
    辗转相除法
    [比赛总结]ACM div3 G 比赛总结
    SDUST OJ Problem G 动态的字符串排序
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13792121.html
Copyright © 2020-2023  润新知