??xml version="1.0" encoding="utf-8" standalone="yes"?>
ApplicationContext是Spring的核心,Context我们通常解释Z下文环境Q我想用“容器”
来表q它更容易理解一些,ApplicationContext则是“应用的容?#8221;?PQSpring把Bean攑֜
q个容器中,在需要的时候,用getBeanҎ取出Q虽然我没有看过q一部分的源代码Q但?/p>
惛_应该是一个类似Map的结构?
在Web应用中,我们会用到WebApplicationContextQWebApplicationContextl承?/p>
ApplicationContextQ先让我们看看在Web应用中,怎么初始化WebApplicationContextQ在
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>
-->
可以看出Q有两种ҎQ一个是用ContextLoaderListenerq个ListernerQ另一个是
ContextLoaderServletq个ServletQ这两个Ҏ都是在web应用启动的时候来初始?/p>
WebApplicationContextQ我个h认ؓListerner要比Servlet更好一些,因ؓListerner监听?/p>
用的启动和结束,而Servlet得启动要E微延迟一些,如果在这时要做一些业务的操作Q启?/p>
的前后顺序是有媄响的?
那么在ContextLoaderListener和ContextLoaderServlet中到底做了什么呢Q?
以ContextLoaderListenerZQ我们可以看?
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
protected ContextLoader createContextLoader() {
return new ContextLoader();
}
ContextLoader是一个工LQ用来初始化WebApplicationContextQ其主要Ҏ是
initWebApplicationContextQ我们l追tinitWebApplicationContextq个ҎQ具体代?/p>
我不贴出Q大家可以看Spring中的源码Q,我们发现Q原来ContextLoader是把
WebApplicationContextQXmlWebApplicationContext是默认实现类Q放在了ServletContext
中,ServletContext也是一?#8220;容器”Q也是一个类似Map的结构,而WebApplicationContext
在ServletContext中的KEY是
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTEQ我们如果要使用
WebApplicationContext则需要从ServletContext取出QSpring提供了一?/p>
WebApplicationContextUtilsc,可以方便的取出WebApplicationContextQ只要把
ServletContext传入可以了?
上面我们介绍了WebApplicationContext在Servlet容器中初始化的原理,一般的Web应用可
以轻杄使用了,但是Q随着Struts的广泛应用,把Struts和Spring整个hQ是一个需要面
对的问题QSpring本n也提供了Struts的相关类Q主要用的?/p>
org.springframework.web.struts.ActionSupportQ我们只要把自己的Actionl承?/p>
ActionSupportQ就是可以调用ActionSupport中getWebApplicationContext()的方法取?/p>
WebApplicationContextQ但q样一来在Action中,需要取得业务逻辑的地斚w要getBeanQ看
上去不够z,所以Spring又提供了另一个方法,?/p>
org.springframework.web.struts.ContextLoaderPlugInQ这是一个Struts的PlugQ在Struts
启动时加载,对于ActionQ可以像理Bean一h理Q在struts-config.xml中Action的配
|变成类g面的样子
<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.DelegatingActionProxyQ之后我们需要徏
立action-servlet.xmlq样的文Ӟaction-servlet.xmlW合Spring的spring-beans.dtd标准
Q在里面定义cM下面?
<bean name="/aAction" class="com.web.action.Aaction" singleton="false">
<property name="businessService">
<ref bean="businessService"/>
</property>
</bean>
com.web.action.Aaction是Action的实现类QbusinessService是需要的业务逻辑QSpring?/p>
把businessService注入到Action中,在Action中只要写businessService的get和setҎ可
以了Q还有一点,action的bean是singleton="false"Q即每次新徏一个实例,q也解决?/p>
Struts中Action的线E同步问题,具体q程是当用户?#8220;/aAction”的HTTPhQ当然应该是
“/aAction.do”Q,Struts会找到这个Action的对应类
org.springframework.web.struts.DelegatingActionProxyQDelegatingActionProxy是个?/p>
理类Q它会去找action-servlet.xml文g?#8220;/aAction”对应的真正实现类Q然后把它实例化
Q同时把需要的业务对象注入Q然后执行Action的executeҎ?
使用了ContextLoaderPlugInQ在struts-config.xml中变成类D样配|?
<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?
说到q里不知道大家会不会有这L问题Q如果用ContextLoaderPlugInQ如果我们有些程
序是qStruts的Action环境Q我们怎么处理Q比如我们要自定义标记库Q在标记库中Q我?/p>
需要调用Spring理的业务层逻辑对象Q这时候我们就很麻烦,因ؓ只有在action中动态注?/p>
业务逻辑Q其他我们似乎不能取得Spring的WebApplicationContext?
别急,我们q是来看一下ContextLoaderPlugIn的源码(源码不再贴出Q,我们可以发现Q原
来ContextLoaderPlugIn仍然是把WebApplicationContext攑֜ServletContext中,只是q个
KEY不太一样了Q这个KEYgؓ
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX+ModuleConfig.getPrefix()Q具体请查看?/p>
代码Q,q下好了Q我们知道了WebApplicationContext攑֜哪里Q只要我们在Web应用中能?/p>
取到ServletContext也就能取到WebApplicationContext?)
Spring是一个很强大的框Ӟ希望大家在用过E中不断的深入,了解其更多的Ҏ,我在q?/p>
里抛砖引玉,有什么不对的地方Q请大家指出?/p>
所以可以直接在ServletContext取出WebApplicationContext 对象Q?/p>
WebApplicationContext webApplicationContext = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
事实上WebApplicationContextUtils.getWebApplicationContextҎ是使用上面的代码实现的Q徏议用上面上面的静态方?nbsp;