spring和springmvc父子容器的关系

4 篇文章 0 订阅
本片文章受一下四篇文章影响,形成一篇综合性的自己的理解:
http://blog.csdn.net/caomiao2006/article/details/51290494
http://www.cnblogs.com/zyzcj/p/5286190.html#3693938
http://blog.csdn.net/wabiaozia/article/details/51627500    
http://blog.csdn.net/wyc199273/article/details/62227013      
----------------------------------------------------------------------------------     
一、引入:  
例如我有一个web工程:
其中web.xml包含如下两个配置:
1)
        <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring/applicationContext.xml</param-value>
	</context-param>
	<!--Spring的ApplicationContext 载入 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
2)
<!-- 配置SpringMVC -->
	<servlet>
		<servlet-name>springmvc-web</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 指定SpringMVC配置文件 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring/springmvc-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>springmvc-web</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>

1) 在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文(或者称之为父容器,根容器,spring容器)即 WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。 这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。spring容器中就包含有<context-param>指定的applicationContext.xml配置文件中定义的bean。

2) contextLoaderListener监听器初始化完毕后,开始 初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。 DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文(子上下文,子容器,springmvc容器),读取<init-param>中指定的mvc配置文件,子容器中生成并持有相应的bean。 同时这个子上下文,也继承根上下文。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间。
--------------------------------------------------------------------------------------------------------------
二、特性:
子上下文可以访问父上下文中的bean,但是父上下文不可以访问子上下文中的bean。

父上下文使用与否

方案一,传统型:

父上下文容器中保存数据源datasource、服务层service、DAO层、事务的Bean(transaction)。

子上下文容器中保存Mvc相关的Action、controller的Bean.

事务控制在服务层。

由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。


方案二,激进型:

不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。事情就简单了,什么麻烦事儿也没有了。

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

三、沿着一个思路分析两个案例:

3.1)
如果我在applicationContext.xml配置注解扫描:
1
<context:component-scan base-package=“com.test" />
 
根据Spring提供的参考手册,该配置的功能是扫描默认包下的所有的@Component注解,并且自动注册到容器中,同时也扫描@Controller,@Service,@Respository这三个注解,他们是继承自@Component。

然后再springmvc-config.xml中配置支持@RequestMapping映射的注解扫描
<context:annotation-config/> 
//这就是springmvc要以注解方式进行HandlerMapping(是SpringMVC中用来处理Request请求URL到具体Controller的)的必要配置
 
启动项目发现,springMVC失效,无法进行跳转,开启log的DEBUG级别进行调试,发现springMVC容器中的请求好像没有映射到具体controller中;
 原因:spring容器中扫描controller生成bean,但是并没有配置支持@RequestMapping映射的注解扫描<context:annotation-config/>所以spring容器中生成的bean并没有HandlerMapping请求映射功能。

想要解决这个问题,就只有按照如上所说的传统方式。子上下文容器中保存Mvc相关的Action、controller的Bean.
将<context:component-scan base-package=“com.test.controller" />扫描配置到springmvc-config.xml中,将指定包下的bean扫描到子容器中。重启后,验证成功,springMVC跳转有效。
-------------------------------------
 3.2)
我们applicationContext中配置PropertyPlaceholderConfigurer的相关配置:
<bean id="common.propertyConfigurer"  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound" value="true" /><!--忽略未找到文件 -->
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="fileEncoding" value="UTF-8" />
    <property name="locations">
        <list>
            <value>classpath*:conf/default-*.properties</value>
            <value>classpath*:conf/*.properties</value>
        </list>
    </property>
</bean>

这个配置的作用就是
例如:你在spring中引入了aaaaa.properties文件,aaaaa.properties文件中有一个属性a=http:8080。
就可以在java类中通过
  1. @value("{a}") 
  2. private String a; 
来注入properties文件中的a对应的属性。
但是运行会发现,我们在controller中注入不了这个值,而在service中能够用这种形式注入这个值。
查看另一个博文的说明(原因如下):
我们的项目里在applicationContext.xml和springmvc-config.xml中都扫描了controller. 但是只在applicationContext.xml中配置了PropertyPlaceholderConfigurer的相关配置。
因为<mvc:annotation-driven/>配置是在springmvc-config.xml里面的.导致请求到controller走的是springmv容器里的controller. 而springmvc容器中没有相关配置PropertyPlaceholderConfigurer.导致controller中的@Value没有注入,从而造成问题。
但是不是说父容器中的bean,对于子容器也是可以用的吗?怎么这个在父容器中配置的就不行了呢?

我的推论是,@注解方式只对配置了支持注解的容器有效。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值