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

    正好以前项目中碰到这个问题,现在网上偶然又看到这个问题的博文,那就转一下吧。

    原文:http://blog.lifw.org/post/46428852 感谢作者

    另外补充下:在web Server容器中,无论是Servlet,Filter,还是Listener都不是Spring容器管理的,因此我们都无法在这些类中直接使用Spring注解的方式来注入我们需要的对象,当然除了下面我们详细说的方法外,还有的比如说为了在Servlet中使用Spring容器的对象,那么可以参考如下两篇文章:

    Servlet自动注入Spring容器中的Bean解决方法

    在servlet中注入spring的bean,servlet容器和spring容器

    额外文章就参考这么多

    以下是原文:

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

    1 public class ConfigListener implements ServletContextListener {
    2     @Override
    3     public void contextInitialized(ServletContextEvent sce) {
    4           //执行初始化操作
    5     }
    6     @Override
    7     public void contextDestroyed(ServletContextEvent sce) {
    8     }
    9 }

    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>
  • 相关阅读:
    古谚、评论与论断、名篇与名言
    重读《西游记》
    重读《西游记》
    命名之法 —— 时间、季节、地点
    命名之法 —— 时间、季节、地点
    文言的理解 —— 古时的称谓、别称、别名
    文言的理解 —— 古时的称谓、别称、别名
    Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration
    瀑布 敏捷 文档
    POJ 1325 ZOJ 1364 最小覆盖点集
  • 原文地址:https://www.cnblogs.com/fjdingsd/p/5731982.html
Copyright © 2011-2022 走看看