zoukankan      html  css  js  c++  java
  • 自定义Listener(监听器)中使用Spring容器管理的bean

    本文转载至:http://blog.lifw.org/post/46428852

    感谢博主,受益了!

    原文如下:

    1.在java web项目中我们通常会有这样的需求:当项目启动时执行一些初始化操作,例如从数据库加载全局配置文件等,通常情况下我们会用javaee规范中的Listener去实现,例如

    public class ConfigListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent sce) {
              //执行初始化操作
        }
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    }

    2.这样当servlet容器初始化完成后便会调用contextInitialized方法。但是通常我们在执行初始化的过程中会调用service和dao层提供的方法,而现在web项目通常会采用spring框架来管理和装配bean,我们想当然会像下面这么写,假设执行初始化的过程中需要调用ConfigService的initConfig方法,而ConfigService由spring容器管理(标有@Service注解)

    public class ConfigListener implements ServletContextListener {
     
        @Autowired
        private ConfigService configService;
         
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            configService.initConfig();
        }
     
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    }

    3.然而以上代码会在项目启动时抛出空指针异常!ConfigService实例并没有成功注入。这是为什么呢?要理解这个问题,首先要区分Listener的生命周期和spring管理的bean的生命周期。

    (1)Listener的生命周期是由servlet容器(例如tomcat)管理的,项目启动时上例中的ConfigListener是由servlet容器实例化并调用其contextInitialized方法,而servlet容器并不认得@Autowired注解,因此导致ConfigService实例注入失败。

    (2)而spring容器中的bean的生命周期是由spring容器管理的。

    4.那么该如何在spring容器外面获取到spring容器bean实例的引用呢?这就需要用到spring为我们提供的WebApplicationContextUtils工具类,该工具类的作用是获取到spring容器的引用,进而获取到我们需要的bean实例。代码如下

    public class ConfigListener implements ServletContextListener {
         
        @Override
        public void contextInitialized(ServletContextEvent sce) {  
            ConfigService configService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ConfigService.class);
            configService.initConfig();
        }
     
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
        }
    }

    注意:以上代码有一个前提,那就是servlet容器在实例化ConfigListener并调用其方法之前,要确保spring容器已经初始化完毕!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,因此只需在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener,配置如下

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>
     
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     
    <listener>
        <listener-class>example.ConfigListener</listener-class>
    </listener>
  • 相关阅读:
    cube.js 基于http 通道的数据实时更新bug 解决
    cube.js 基于http 通道的数据实时更新
    cube.js websocket 实时数据更新说明
    phpspy 进行php 项目性能分析
    使用groovy 下载maven依赖包
    java 几个不错的代码生成工具
    语言性能分析工具总结
    使用rbspy 分析ruby应该性能
    dremio v18.0 软件包可以使用了
    nginx rewrite查询字符串重写问题
  • 原文地址:https://www.cnblogs.com/gugunan/p/8378682.html
Copyright © 2011-2022 走看看