Spring中ApplicationContext加载机制

转:http://blog.csdn.net/edisondu1983/article/details/3954417  有删改。

 

 

 

Spring中ApplicationContext加载机制。 
          加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet。 
         这两者在功能上完全等同,只是一个是基于Servlet2.3版本中新引入的Listener接口实现,而另一个基于Servlet接口实现。开发中可根据目标Web容器的实际情况进行选择。

配置非常简单,在web.xml中增加 : 
<listener> 
  <listener-class> 
       org.springframework.web.context.ContextLoaderListener 
  </listener-class> 
</listener> 
或: 
<servlet> 
    <servlet-name>context</servlet-name> 
    <servlet-class> 
       org.springframework.web.context.ContextLoaderServlet 
    </servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
  
          通过以上配置,Web容器会自动加载/WEB-INF/applicationContext.xml初始化 
ApplicationContext实例,如果需要指定配置文件位置,可通过context-param加以指定: 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/myApplicationContext.xml</param-value> 
</context-param>

        配置完成之后,即可通过 
 WebApplicationContextUtils.getWebApplicationContext方法在Web应用中获取ApplicationContext引用。

如:ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(); 
    LoginAction action=(LoginAction)ctx.getBean("action");

 

=============================

 

Spring中WebApplicationContext的研究 

ApplicationContext是Spring的核心,Context我们通常解释为上下文环境,我想用“容器”来表述它更容易理解一些,ApplicationContext则是“应用的容器”,Spring把Bean放在这个容器中,在需要的时候,用getBean方法取出 ,虽然我没有看过这一部分的源代码,但我想它应该是一个类似Map的结构。 
在Web应用中,我们会用到WebApplicationContext,WebApplicationContext继承自ApplicationContext,先让我们看看在Web应用中,怎么初始化WebApplicationContext,在web.xml中定义: 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/applicationContext.xml</param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

<!-- OR USE THE CONTEXTLOADERSERVLET INSTEAD OF THE LISTENER 
<servlet> 
    <servlet-name>context</servlet-name> 
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> 
    <!-- 自动启动 -->

<load-on-startup>1</load-on-startup> 
</servlet> 
--> 

可以看出,有两种方法,一个是用ContextLoaderListener这个Listerner,另一个是ContextLoaderServlet这个Servlet,这两个方法都是在web应用启动的时候来初始化WebApplicationContext ,我个人认为Listerner要比Servlet更好一些,因为Listerner监听应用的启动和结束,而Servlet得启动要稍微延迟一些,如果在这时要做一些业务的操作,启动的前后顺序是有影响的。 

那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢? 
以ContextLoaderListener为例,我们可以看到 
public void contextInitialized(ServletContextEvent event) { 
  this.contextLoader = createContextLoader(); 
  this.contextLoader.initWebApplicationContext(event.getServletContext()); 

protected ContextLoader createContextLoader() { 
  return new ContextLoader(); 

ContextLoader是一个工具类,用来初始化WebApplicationContext,其主要方法就是initWebApplicationContext,我们继续追踪initWebApplicationContext这个方法(具体代码我不贴出,大家可以看Spring中的源码),我们发现,原来ContextLoader是把WebApplicationContext(XmlWebApplicationContext是默认实现类)放在了ServletContext中ServletContext也是一个“容器”,也是一个类似Map的结构,而WebApplicationContext在ServletContext中的KEY就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,我们如果要使用WebApplicationContext则需要从ServletContext取出,Spring提供了一个WebApplicationContextUtils类,可以方便的取出WebApplicationContext,只要把ServletContext传入就可以了。 

上面我们介绍了WebApplicationContext在Servlet容器中初始化的原理,一般的Web应用就可以轻松的使用了,但是,随着Struts的广泛应用,把Struts和Spring整个起来,是一个需要面对的问题 ,Spring本身也提供了Struts的相关类,主要使用的有org.springframework.web.struts.ActionSupport,我们只要把自己的Action继承自ActionSupport,就是可以调用ActionSupport中getWebApplicationContext()的方法取出WebApplicationContext ,但这样一来在Action中,需要取得业务逻辑的地方都要getBean,看上去不够简洁,

所以Spring又提供了另一个方法用org.springframework.web.struts.ContextLoaderPlugIn,这是一个Struts的Plug,在Struts启动时加载 ,对于Action,可以像管理Bean一样来管理,在struts-config.xml中Action的配置变成类似下面的样子 
<action attribute="aForm" name="aForm" path="/aAction" scope="request"  type="org.springframework.web.struts.DelegatingActionProxy"> 
  <forward name="forward" path="forward.jsp" /> 
</action> 
注意type变成了org.springframework.web.struts.DelegatingActionProxy,之后我们需要建立action-servlet.xml这样的文件,action-servlet.xml符合Spring的spring-beans.dtd标准,在里面定义类似下面的 
<bean name="/aAction" class="com.web.action.Aaction" singleton="false"> 
  <property name="businessService"> 
    <ref bean="businessService"/> 
  </property> 
</bean> 

com.web.action.Aaction是Action的实现类,businessService是需要的业务逻辑,Spring会把businessService注入到Action中,在Action中只要写businessService的get和set方法就可以了,还有一点,action的bean是singleton="false",即每次新建一个实例,这也解决了Struts中Action的线程同步问题,具体过程是当用户做“/aAction”的HTTP请求(当然应该是“/aAction.do”),Struts会找到这个Action的对应类org.springframework.web.struts.DelegatingActionProxy,DelegatingActionProxy是个代理类,它会去找action-servlet.xml文件中“/aAction”对应的真正实现类,然后把它实例化,同时把需要的业务对象注入,然后执行Action的execute方法。 

使用了ContextLoaderPlugIn,在struts-config.xml中变成类似这样配置 
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> 
  <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml" /> 
</plug-in> 
而在web.xml中不再需要ContextLoaderListener或是ContextLoaderServlet。 

说到这里不知道大家会不会有这样的问题,如果使用ContextLoaderPlugIn,如果我们有些程序是脱离Struts的Action环境,我们怎么处理,比如我们要自定义标记库,在标记库中,我们需要调用Spring管理的业务层逻辑对象,这时候我们就很麻烦,因为只有在action中动态注入业务逻辑,其他我们似乎不能取得Spring的WebApplicationContext。 

别急,我们还是来看一下ContextLoaderPlugIn的源码(源码不再贴出),我们可以发现,原来ContextLoaderPlugIn仍然是把WebApplicationContext放在ServletContext中,只是这个KEY不太一样了,这个KEY值为ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX+ModuleConfig.getPrefix()(具体请查看源代码),这下好了,我们知道了WebApplicationContext放在哪里,只要我们在Web应用中能够取到ServletContext也就能取到WebApplicationContext了:)

 

--------------------------

加载spring配置文件还是放到src下比较好。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext-hibernate.xml,
classpath:applicationContext-dao.xml,
classpath:applicationContext-service.xml,
classpath:applicationContext-struts.xml
</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

--------------------------Sping in Action 7.2.5--------------------------------------

7.2.5Rounding out the Spring application context
As I mentioned earlier, DispatcherServlet loads its Spring application context from
a single XML file whose name is based on its <servlet-name>. But what about the
other beans we’ve declared in previous chapters, such as the SpitterService bean? If
DispatcherServlet is going to load its beans from a file named spitter-servlet.xml,
then won’t we need to declare those other beans in spitter-servlet.xml?
In the earlier chapters we’ve split our Spring configuration across multiple XML
files: one for the service layer, one for the persistence layer, and another for the data
source configuration. Although not strictly required, it’s a good idea to organize our

Spring configuration across multiple files. With that in mind, it makes sense to put all
of the web layer configuration in spitter-servlet.xml, the file loaded by Dispatcher-
Servlet. But we still need a way to load the other configuration files.
That’s where ContextLoaderListener comes into play. ContextLoaderListener is
a servlet listener that loads additional configuration into a Spring application context
alongside the application context created by DispatcherServlet. To use Context-
LoaderListener, add the following <listener> declaration to the web.xml file:
<listener>
       <listener-class>
           org.springframework.web.context.ContextLoaderListener
       </listener-class>
</listener>

We also need to tell ContextLoaderListener which Spring configuration file(s) it
should load. If not specified otherwise, the context loader will look for a Spring con-
figuration file at /WEB-INF/applicationContext.xml. But this single file doesn’t lend
itself to breaking up the application context into several pieces. So we’ll need to over-
ride this default.
To specify one or more Spring configuration files for ContextLoaderListener to
load, set the contextConfigLocation parameter in the servlet context:
<context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>
             /WEB-INF/spitter-security.xml
            classpath:service-context.xml
            classpath:persistence-context.xml
            classpath:dataSource-context.xml
       </param-value>
</context-param>

The contextConfigLocation parameter is specified as a list of paths. Unless specified
otherwise, the paths are relative to the application root. But since our Spring configuration is split across multiple XML files that are scattered across several JAR files in the
web application, we’ve prefixed some of them with classpath: to load them as
resources from the application classpath and others with a path local to the web
application.
You’ll recognize that we’ve included the Spring configuration files that we created
in previous chapters. You may also notice a few extra configuration files that we’ve not
covered yet. Don’t worry...we’ll get to those in later chapters.
Now we have our first controller written and ready to serve requests for the Spitter
application’s home page. If all we needed is a home page, we’d be done. But there’s
more to Spitter than just the home page, so let’s continue building out the applica-
tion. The next thing we’ll try is to write a controller that can handle input.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值