文档章节

Spring在Listener中注入bean的问题

蜡笔小小小新
 蜡笔小小小新
发布于 2016/10/04 19:33
字数 559
阅读 129
收藏 2

下面是我第一次这么干的时候:

package com.lin.warehouse.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;

import com.lin.warehouse.service.IWarehouseService;
import com.lin.warehouse.service.impl.WarehouseServiceImpl;

@WebListener
public class TestListener implements HttpSessionListener {
	
	@Autowired
	private IWarehouseService warehouseService;

    public void sessionCreated(HttpSessionEvent event)  { 
    	
    	System.out.println("----------------------------------------------------->"+warehouseService.getClass().toString());
    }

    public void sessionDestroyed(HttpSessionEvent event)  { 
    }
	
}

在一个Listsner中把接口的实例注入进来,但这样得不到接口的实例,接口引用是空指针。为什么会这样呢?因为Listsner是由Tomcat管理的,Tomcat无法把SpringIOC容器的Bean诸如到Listsner,而注入Bean的工作是由Spring负责的。那么解决这个问题呢?

Spring容器实现了一个监听ServletContext启动事件的监听器,这个监听器把一个IOC容器在ServletContext启动时放进ServletContext容器当做应用的Bean容器。现在只需要在Listsner中得到这个IOC容器就可以了,看看org.springframework.web.context.ContextLoaderListener的源代码。

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
			throw new IllegalStateException(
					"Cannot initialize context because there is already a root application context present - " +
					"check whether you have multiple ContextLoader* definitions in your web.xml!");
		}

		Log logger = LogFactory.getLog(ContextLoader.class);
		servletContext.log("Initializing Spring root WebApplicationContext");
		if (logger.isInfoEnabled()) {
			logger.info("Root WebApplicationContext: initialization started");
		}
		long startTime = System.currentTimeMillis();

		try {
			// Store context in local instance variable, to guarantee that
			// it is available on ServletContext shutdown.
			if (this.context == null) {
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {
					// The context has not yet been refreshed -> provide services such as
					// setting the parent context, setting the application context id, etc
					if (cwac.getParent() == null) {
						// The context instance was injected without an explicit parent ->
						// determine parent for root web application context, if any.
						ApplicationContext parent = loadParentContext(servletContext);
						cwac.setParent(parent);
					}
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

			ClassLoader ccl = Thread.currentThread().getContextClassLoader();
			if (ccl == ContextLoader.class.getClassLoader()) {
				currentContext = this.context;
			}
			else if (ccl != null) {
				currentContextPerThread.put(ccl, this.context);
			}

			if (logger.isDebugEnabled()) {
				logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
						WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
			}
			if (logger.isInfoEnabled()) {
				long elapsedTime = System.currentTimeMillis() - startTime;
				logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
			}

			return this.context;
		}
		catch (RuntimeException ex) {
			logger.error("Context initialization failed", ex);
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
			throw ex;
		}
		catch (Error err) {
			logger.error("Context initialization failed", err);
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
			throw err;
		}
	}

上面是初始化ServletContext的方法,把IOC容器放进ServletContext容器的是这句,

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

它的KEY是 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,那就在Listsner中通getAttribute(“”,);方法得到IOC容器

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;

import com.lin.warehouse.service.IWarehouseService;
import com.lin.warehouse.service.impl.WarehouseServiceImpl;

@WebListener
public class TestListener implements HttpSessionListener {
	
	//@Autowired
	private IWarehouseService warehouseService;

    public void sessionCreated(HttpSessionEvent event)  { 
    	
    	ApplicationContext applicationContext = (WebApplicationContext)event.getSession().getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    	
    	warehouseService = applicationContext.getBean("warehouseService",WarehouseServiceImpl.class );
    }

    public void sessionDestroyed(HttpSessionEvent event)  { 
    }
	
}

 

© 著作权归作者所有

共有 人打赏支持
蜡笔小小小新
粉丝 32
博文 114
码字总数 75210
作品 0
深圳
后端工程师
spring定时器用Annotation实现

1.ApplicationContext.xml配置 a)、需要在xmlns里面加入: xmlns:task="http://www.springframework.org/schema/task" b)、在xsi:schemaLocation中加入 http://www.springframework.org/sch......

锁力
2011/12/30
0
1
Spring面试问答Top 25

本人收集了一些在大家在面试时被经常问及的关于Spring的主要问题,这些问题有可能在你下次面试时就会被问到。对于本文中未提及的Spring其他模块,我会单独分享面试的问题和答案。 欢迎大家向...

赵小宾
2015/05/04
0
1
Spring中ApplicationContextAware使用说明

Spring 中提供一些Aware相关接口,像是BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,实作这些 Aware接口的Bean在被初始之后,可以取得一些相...

Josean_Luo
2014/06/07
0
0
struts2学习笔记之spring整合

一、整合步骤: 1 配置classpath,将struts-spring-plugin.jar和spring.jar添加进去 如果少了spring.jar将报错,提示找不到相关类定义。 2 在web.xml中配置spring contextConfigLocationcla...

美码师
2011/10/15
0
0
spring全套,出现bean问题

springmvc datajpa,出现问题 现象: 1.在listener中通过webapplicationcontext获取service层的bean出错(用类型找不到,用名称则类型不对,是个proxy),但是获取dao层的bean就正常。contr...

noday
2015/08/09
149
5

没有更多内容

加载失败,请刷新页面

加载更多

下一页

kernel version does not match DSO version

错误信息: kernel version 384.11 does not match DSO version 384.130.0 原因是: cuda driver版本太低,不匹配DSO 简单有效的修复方法,升级nvidia driver, 步骤如下: 1. google seach ...

刘小米
今天
0
0
maven坐标和依赖

一、maven坐标详解 <groupId>com.fgt.club</groupId><artifactId>club-common-service-facade</artifactId><version>3.0.0</version><packaging>jar</packaging> maven的坐标元素说......

老韭菜
今天
1
0
springmvc-servlet.xml配置表功能解释

问:<?xml version="1.0" encoding="UTF-8" ?> 答: xml version="1.0"表示是此xml文件的版本是1.0 encoding="UTF-8"表示此文件的编码方式是UTF-8 问:<!DOCTYPE beans PUBLIC "-//SPRING//......

隐士族隐逸
今天
1
0
基于TP5的微信的公众号获取登录用户信息

之前讲过微信的公众号自动登录的菜单配置,这次记录一下在TP5项目中获取自动登录的用户信息并存到数据库的操作 基本的流程为:微信设置自动登录的菜单—>访问的URL指定的函数里获取用户信息—...

月夜中徘徊
今天
0
0
youTrack

package jetbrains.teamsys.license.runtime; 计算lis package jetbrains.ring.license.reader; 验证lis 安装后先不要生成lis,要把相关文件进行替换 ring-license-checker-1.0.41.jar char......

max佩恩
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部