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的主要内容,如果未能解决你的问题,请参考以下文章