listener中获取spring中管理的bean

Posted 一首简单的歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了listener中获取spring中管理的bean相关的知识,希望对你有一定的参考价值。

看第一个例子:

自定义一个listener:

package com.test.common.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.annotation.Autowired;

import com.test.moudules.test.service.MyService;

public class CustomListener implements ServletContextListener {
    
    @Autowired
    MyService myService;

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("*****started*******");
        myService.test();
    }

}

在web.xml中进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>testWeb</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
   <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     <listener>
        <listener-class>com.test.common.listener.CustomListener</listener-class>
    </listener>
<!-- springmvc 前端控制器 -->
    <servlet>
        <servlet-name>dispatcherSerlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherSerlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

 

MyService(纳入spring管理的普通bean):

package com.test.moudules.test.service;

import org.springframework.stereotype.Component;

@Component
public class MyService {

    public void test() {
        System.out.println("this is test method");
    }
}

启动web应用结果:

java.lang.NullPointerException
    at com.test.common.listener.CustomListener.contextInitialized(CustomListener.java:22)

分析原因:

listener(以及filter)是由servlet容器(比如tomcat)来进行管理的,而像MyService这些bean是由spring容器管理的,所以在CustomListener中是识别不了自动注入的注解(@Autowired),也无法获取到spring容器中的MyService这些bean的,所以报空指针异常。

看第二个例子:

package com.test.common.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.web.context.support.WebApplicationContextUtils;

import com.test.moudules.test.service.MyService;

public class CustomListener implements ServletContextListener {

    MyService myService;

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

//servlet容器启动时执行的方法
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("*****started*******");
        myService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext())
                .getBean(MyService.class);
        myService.test();
    }

}

 

启动web应用结果:

*****started*******
this is test method

分析原因:看结果是执行成功了拿到了MyService的bean,并执行了方法。如何实现呢?我们最终的目标是要拿到spring管理的bean(像MyServlce这些类的实现),可以通过

web.xml中配置的DispatcherServlet,DispatcherServlet加载时会启动一个spring容器(作为子容器),而像管理MyService这些bean的spring容器是父容器,通过

WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext())可以在子容器中拿到父容器的applicationContext,进而拿到相关的bean。

注意:

配置顺序必须如下:

 <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     <listener>
        <listener-class>com.test.common.listener.CustomListener</listener-class>
    </listener>

即让父spring容器先启动起来,再启动自定义的listener若顺序返了肯定也拿不到相应的bean,因为父spring容器还未启动。

 

 

以上是关于listener中获取spring中管理的bean的主要内容,如果未能解决你的问题,请参考以下文章

如何在线程中获取spring 管理的bean

Spring中如何在非Spring管理的Bean中获取到Spring管理的Bean并操作

ApplicationContextAware 接口作用

静态文件获取spring管理的bean对象

ApplicationContextAware接口的作用

spring中Bean的生命周期