zoukankan      html  css  js  c++  java
  • ssh下:系统初始化实现ServletContextListener接口时,获取spring中数据层对象无效的问题

    想要实现的功能:SSH环境下,数据层都交由Spring管理;在服务启动时,将数据库中的一些数据加载到ServletContext中缓存起来。

    系统初始化类需要实现两个接口:

    ServletContextListener,系统初始化时调用contextInitialized方法缓存数据;

    ApplicationContextAware,获取Spring的ApplicationContext对象,以获取spring容器管理的service对象。

    系统初始化类如下:

    复制代码
     1 package com.lizhou.action;
     2 
     3 import java.util.List;
     4 
     5 import javax.servlet.ServletContext;
     6 import javax.servlet.ServletContextEvent;
     7 import javax.servlet.ServletContextListener;
     8 
     9 import org.springframework.beans.BeansException;
    10 import org.springframework.context.ApplicationContext;
    11 import org.springframework.context.ApplicationContextAware;
    12 import org.springframework.stereotype.Component;
    13 
    14 import com.lizhou.entity.ProductBigType;
    15 import com.lizhou.service.inter.ProductBigTypeServiceInter;
    16 
    17 /**
    18  * 初始化:实现application缓存数据功能
    19  * 在服务启动时,将数据库中的数据加载进内存
    20  * @author bojiangzhou
    21  *
    22  */
    23 @Component //这里要该注解,不然无法注入ApplicationContext对象
    24 public class InitAction implements ServletContextListener, ApplicationContextAware {
    25     
    26     private ApplicationContext ac;
    27     
    28     @Override
    29     public void contextInitialized(ServletContextEvent event) {
    30         //这里输出当前调用该方法的对象
    31         System.out.println("contextInitialized: "+this);
    32         
    33         //获取application
    34         ServletContext application = event.getServletContext();
    35         //获取服务层
    36         ProductBigTypeServiceInter bigTypeService = (ProductBigTypeServiceInter) this.ac.getBean("bigTypeService");
    37         //获取商品大类集合
    38         List<ProductBigType> bigTypeList = bigTypeService.findAllBigTypeList();
    39         //保存到application缓存中
    40         application.setAttribute("bigTypeList", bigTypeList);
    41     }
    42     
    43     @Override
    44     public void setApplicationContext(ApplicationContext ac) throws BeansException {
    45         //这里输出当前调用该方法的对象
    46         System.out.println("setApplicationContext: "+this);
    47         this.ac = ac;
    48     }
    49     
    50     @Override
    51     public void contextDestroyed(ServletContextEvent event) {
    52     }
    53 
    54 }
    复制代码

    下面是web.xml里spring和系统初始化的配置:spring是在系统初始化类前加载的

    复制代码
     1 <!-- 添加对spring的支持 -->
     2   <context-param>
     3       <param-name>contextConfigLocation</param-name>
     4       <param-value>classpath:applicationContext.xml</param-value>
     5   </context-param>
     6   
     7   <!-- 定义spring的监听器,加载spring -->
     8   <listener>
     9       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    10   </listener>
    11   
    12   <!-- 添加自己的初始化action -->
    13   <listener>
    14       <listener-class>com.lizhou.action.InitAction</listener-class>
    15   </listener>
    复制代码

    服务启动时,控制台输出如下信息:

    首先,从输出的信息来看,ApplicationContext对象已经注入进来了;

    但是,第36行,也就是通过ApplicationContext来获取服务层对象时报错空指针异常了,说明ApplicationContext为空;

    造成这个异常的原因很明显:从输出的两个对象来看,调用setApplicationContext方法和contextInitialized方法不是同一个对象,所以在调用contextInitialized方法时,ApplicationContext还是为Null;

    因为调用setApplicationContext方法的对象是由Spring初始化的,而调用contextInitialized方法的对象是由tomcat在加载web.xml时通过反射创建的。

    所以两个对象不一致。

    这里我想到一种解决办法是:将ApplicationContext设置为静态的(static),这样就只有一个ApplicationContext对象了。

     1 private static ApplicationContext ac; //设置为静态 

    这样就不会报空指针异常了。一切就OK了!

    想了想,好像不能将这个初始化类交给Spring来管理,它配置在web.xml中,系统启动时就会触发ServletContextEvent事件,然后调用contextInitialized方法来做初始化工作,它是由tomcat来完成的。即使交由Spring来管理,也没有效果。

    如果有其它的办法请分享给我,谢谢!!

  • 相关阅读:
    剑指 Offer 06. 从尾到头打印链表
    剑指 Offer 05. 替换空格
    剑指 Offer 04. 二维数组中的查找
    14. 不修改数组找出重复的数字
    剑指 Offer 03. 数组中重复的数字
    231. 2 的幂
    1394. 完美牛棚
    10. 正则表达式匹配
    3726. 调整数组
    474. 一和零
  • 原文地址:https://www.cnblogs.com/wangchaoyuana/p/7523296.html
Copyright © 2011-2022 走看看