`

web项目如何获取容器中的bean对象?

 
阅读更多
from:http://blog.163.com/sir_876/blog/static/11705223201111544523333/
spring通过在web.xml 中配置ContextLoaderListener 来加载context配置文件,在DispatcherServlet中也可以来加载spring context配置文件,那么这两个有什么区别呢。

ContextLoaderListener中加载的context成功后,spring 将 applicationContext存放在ServletContext中key值为"org.springframework.web.context.WebApplicationContext.ROOT"的attribute 中。 (servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context));可以通过 WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 或WebApplicationContextUtils.getWebApplicationContext(servletContext)方法来获取对应的applicationContext。

DispatcherServlet加载的context成功后,如果 publishContext属性的值设置为true的话(缺省为true) 会将applicationContext存放在 org.springframework.web.servlet.FrameworkServlet.CONTEXT. + (servletName)的attribute中。

例如 web.xml中配置如下
Xml代码 
    <servlet> 
        <servlet-name>mvcServlet</servlet-name> 
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
        <init-param> 
            <param-name>contextConfigLocation</param-name> 
            <param-value>classpath*:/spring/config/applicationContextMVC.xml</param-value> 
        </init-param> 
        <load-on-startup>1</load-on-startup> 
    </servlet>

则对应的applicationContext的attribute key值为org.springframework.web.servlet.FrameworkServlet.CONTEXT.mvcServlet。

  在每次request请求时,DispatcherServlet会将此applicationContext存放在request中attribute 值为 org.springframework.web.servlet.DispatcherServlet.CONTEXT中 (request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());)。可以通过 RequestContextUtils.getWebApplicationContext 或 WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname) 方法 来获取对应的applicationContext。

  从上面的分析可以看出,DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,由于保存在servletContext中的key值与通过ContextLoaderListener加载进来的applicationContext使用的 key值不相同,因此如果只使用DispatcherServlet加载context的话,如果程序中有地方使用 WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的exception。

那我们怎么取了?
ApplicationContext ac = (WebApplicationContext) this.getServeltContext().getAttribute("org.springframework.web.servelt.FrameworkServlet.CONTEXT.这里填写web.xml配置的servlet的名称");

http://pbcljf.blog.163.com/blog/static/340340192010513537424/
方法一:在初始化时保存ApplicationContext对象
代码:
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
ac.getBean("beanId");
说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。

方法二:通过Spring提供的工具类获取ApplicationContext对象
代码:
import org.springframework.web.context.support.WebApplicationContextUtils;
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc);
ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
ac1.getBean("beanId");
ac2.getBean("beanId");
说明:
这种方式适合于采用Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象,然后在通过它获取需要的类实例。

上面两个工具方式的区别是,前者在获取失败时抛出异常,后者返回null。

其中 servletContext sc 可以具体 换成 servlet.getServletContext()或者 this.getServletContext() 或者 request.getSession().getServletContext(); 另外,由于spring是注入的对象放在ServletContext中的,所以可以直接在ServletContext取出 WebApplicationContext 对象: WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

方法三:继承自抽象类ApplicationObjectSupport
说明:抽象类ApplicationObjectSupport提供getApplicationContext()方法,可以方便的获取到ApplicationContext。
Spring初始化时,会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入。

方法四:继承自抽象类WebApplicationObjectSupport
说明:类似上面方法,调用getWebApplicationContext()获取WebApplicationContext

方法五:实现接口ApplicationContextAware
说明:实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。
Spring初始化时,会通过该方法将ApplicationContext对象注入。


在web应用中一般用ContextLoaderListener加载webapplication,如果需要在action之外或者control类之外获取webapplication思路之一是,单独写个类放在static变量中,
类似于:
public class AppContext {

  private static AppContext instance;

  private AbstractApplicationContext appContext;

  public synchronized static AppContext getInstance() {
    if (instance == null) {
      instance = new AppContext();
    }
    return instance;
  }

  private AppContext() {
    this.appContext = new ClassPathXmlApplicationContext(
        "/applicationContext.xml");
  }

  public AbstractApplicationContext getAppContext() {
    return appContext;
  }
}

不过这样,还是加载了2次applicationcontext,servlet一次,路径加载一次;觉得不如直接用路径加载,舍掉servlet加载
在网上也找了些其他说法:实现ApplicationContextAware,,, 接口,或者servletcontextAware接口,还要写配置文件。有的竟然要把配置文件里的listener,换成自己的类,这样纯粹多此一举。不过有的应用不是替换,是在补一个listener,
我在一版的jpetstore(具体那一版不知道)里发现了这个:
[web.xml]里
     
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
   
    <listener>
        <listener-class>com.ibatis.jpetstore.util.SpringInit</listener-class>
    </listener>
其中SpringInit实现接口ServletContextListener :

package com.ibatis.jpetstore.util;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;


public class SpringInit implements ServletContextListener {
   

    private static WebApplicationContext springContext;
   
    public SpringInit() {
        super();
    }
   
    public void contextInitialized(ServletContextEvent event) {
        springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
    }
   

    public void contextDestroyed(ServletContextEvent event) {
    }
   
    public static ApplicationContext getApplicationContext() {
        return springContext;
    }

   
}

在其中的一个bean的构造里SpringInit获取applicationcontext,代码:
  public OrderBean() {
    this(
            (AccountService) SpringInit.getApplicationContext().getBean("accountService"),
            (OrderService) SpringInit.getApplicationContext().getBean("orderService") );
  }

恩,这种在action,servlet之外的bean里获取applicationcontext的方法值得参考,应该有用

分享到:
评论

相关推荐

    基于java的企业级应用开发:Bean的实例化.ppt

    Bean的实例化 在面向对象的程序中,想要使用某个对象,就需要先实例化这个对象。同样,在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式,分别为构造器实例化、静态工厂方式实例化和实例...

    Spring面试题含答案.pdf

    58. 什么是目标对象? 59. 什么是代理? 60. 有几种不同类型的自动代理? 61. 什么是织入。什么是织入应用的不同点? 62. 解释基于 XML Schema 方式的切面实现 63. 解释基于注解的切面实现 64. 什么是 Spring 的 ...

    07-IoC配置-scope属性

    scope属性 名称: scope类型:属性 ...request、session、application、websocket:设定创建出的对象放置在web容器对应的位置 三、bean的生命周期控制 用于控制方法的执行时机 名称: init-method, destroy-metho

    redant:基于Netty一个基于Netty的轻量级Web容器的轻型分布式Web容器

    RedAnt是一个基于Netty的轻量级Web容器 特性: IOC容器:通过@Bean注解可以管理所有对象,通过@Autowired注解进行对象注入 自定义路由:通过@Controller @Mapping @Param注解可以自定义路由 自动参数转换:通过...

    Spring技术内幕:深入解析Spring架构与设计原理 1/2

     ioc容器如何掌控以pojo为基础的bean对象?它的轻量级开发设计思想是如何实现的?  spring产品级的ioc容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成bean的解析和载入?又如何实现bean的生命...

    Spring入门.docx

    实例化完成的Bean对象存放在singletonObjects当中。 FileSystemXmlApplicationContext是加载磁盘里具体位置的xml文件。不同环境下会出现不同的容器,比如导入spring-web包时,会有web环境下的容器。 (4)基于xml

    Spring技术内幕:深入解析Spring架构与设计原理

     ioc容器如何掌控以pojo为基础的bean对象?它的轻量级开发设计思想是如何实现的?  spring产品级的ioc容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成bean的解析和载入?又如何实现bean的生命...

    超级有影响力霸气的Java面试题大全文档

    当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例...

    Spring技术内幕:深入解析Spring架构与设计原理 2/2

     ioc容器如何掌控以pojo为基础的bean对象?它的轻量级开发设计思想是如何实现的?  spring产品级的ioc容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成bean的解析和载入?又如何实现bean的生命...

    Spring.html

    ClassPathXmlApplicationContext:使用这个工厂创建对象,他会根据scope智能判断是否懒加载,如果是单例则创建容器时就会创建里面bean的实例,如果是多例在获取使用时才会创建bean实例 ...

    java面试宝典

    121、jsp有哪些内置对象?作用分别是什么? 31 122、jsp有哪些动作?作用分别是什么? 31 123、JSP中动态INCLUDE与静态INCLUDE的区别? 31 124、两种跳转方式分别是什么?有什么区别? 31 125、如何执行一个线程安全的JSP?...

    Spring技术内幕:深入解析Spring架构与设计原理(第2部分)

     IoC容器如何掌控以POJO为基础的Bean对象?它的轻量级开发设计思想是如何实现的?  Spring产品级的IoC容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成Bean的解析和载入?又如何实现Bean的生命...

    SPRING3技术内幕

     IoC容器如何掌控以POJO为基础的Bean对象?它的轻量级开发设计思想是如何实现的?  Spring产品级的IoC容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成Bean的解析和载入?又如何实现Bean的生命...

    千方百计笔试题大全

    121、jsp有哪些内置对象?作用分别是什么? 31 122、jsp有哪些动作?作用分别是什么? 31 123、JSP中动态INCLUDE与静态INCLUDE的区别? 31 124、两种跳转方式分别是什么?有什么区别? 31 125、如何执行一个线程安全的JSP?...

    jsp系列教程1-2

    ① 9个内建对象中exception需要在指令配置元素中配置...web容器将访问的jsp文件转换成java文件(9个内建对象可在此种找到)--&gt;再将java文件转换为class文件显示在浏览器中。 视屏2 给bean对象复制使用下面语句: ...

    jsp系列教程1-3

    ① 9个内建对象中exception需要在指令配置元素中配置...web容器将访问的jsp文件转换成java文件(9个内建对象可在此种找到)--&gt;再将java文件转换为class文件显示在浏览器中。 视屏2 给bean对象复制使用下面语句: ...

    JSP系列视屏教程

    ① 9个内建对象中exception需要在指令配置元素中配置...web容器将访问的jsp文件转换成java文件(9个内建对象可在此种找到)--&gt;再将java文件转换为class文件显示在浏览器中。 视屏2 给bean对象复制使用下面语句: ...

    J2EE中文版指南 CHM格式 带全文检索

    指定Web客户端的企业Bean引用 32 六.设置企业Bean的JNDI名 32 七.部署J2EE应用程序 33 八.运行J2EE应用程序客户端 34 九.运行Web客户端 34 十.修改J2EE应用程序 35 修改类文件 35 添加文件 36 修改部署设置 36 ...

    Spring技术内幕:深入解析Spring架构与设计原理(第1部分)

     IoC容器如何掌控以POJO为基础的Bean对象?它的轻量级开发设计思想是如何实现的?  Spring产品级的IoC容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成Bean的解析和载入?又如何实现Bean的生命...

Global site tag (gtag.js) - Google Analytics