为什么我的controller注解配置扫描器写到applicationContext.xml中不起作用,写到spring-mvc.xml中就可以?

博客分类:
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath*:META-INF/spring/applicationContext*.xml&/param-value&
&/context-param&
&!-- Creates the Spring Container shared by all Servlets and Filters --&
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
&!-- Handles Spring requests --&
&servlet-name&servlet&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&/WEB-INF/spring/webmvc-config.xml&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&servlet&/servlet-name&
&url-pattern&/&/url-pattern&
&/servlet-mapping&
1、在主容器中(applicationContext.xml),将Controller的注解排除掉 &context:component-scan base-package="com"&
&context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /& &/context:component-scan& 而在springMVC配置文件中将Service注解给去掉 &context:component-scan base-package="com"&
&context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /&
&context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /&
&/context:component-scan& 因为spring的context是父子容器,所以会产生冲突,由ServletContextListener产生的是父容 器,springMVC产生的是子容器,子容器Controller进行扫描装配时装配了@Service注解的实例,而该实例理应由父容器进行初始化以 保证事务的增强处理,所以此时得到的将是原样的Service(没有经过事务加强处理,故而没有事务处理能力。 还有一种方式是将service层改用xml配置,其实这样做也是变相的让springmvc无法扫描service,而只能依赖父窗口也就是ServletContextListener来进行初始化,这样同样被赋予了事务性。
2、自己单独做了个小网站 但是发现action事务不起作用了 但是如果用service层就没问题 找了很多办法没解决 最后自己解决了其实就是一个加载顺序的问题首先使用了spring MVC的项目是不需要配置action bean
而是通过spring mvc的配置文件进行扫描注解加载的spring事务配置文件还有上下文都是通过org.springframework.web.context.ContextLoaderListener加载的,而spring MVC的action是通过org.springframework.web.servlet.DispatcherServlet加载的 这样就有个优先级的问题了
web是先启动ContextLoaderListener后启动DispatcherServlet在ContextLoaderListener加载的时候action并没在容器中,所以现在使用AOP添加事务或者扫描注解都是无用的。那么解决办法就是在DispatcherServlet 加载spring-MVC配置文件后再进行一次AOP事务扫描和注解事务扫描就OK了&tx:annotation-driven transaction-manager="transactionManager"/&&aop:config&
&aop:advisor advice-ref="transactionAdvice" pointcut="execution(* com.yang.web.*.action.*.*(..))"/&
&/aop:config& 至于为什么要在Action中加事务 spring in action 一书中也说过 service dao action 是很经典的组合但不是必须的,对于一个简单的增删改查系统,没必要分那么多层,比如一个简单保存功能 无非就new 一个实体 映射参数 使用了spring jdbcTemplate 保存就一行代码 就一个这么简单的功能有必要 一个service接口 一个service实现类 一行代码调用一个dao接口一个dao实现类
要多建四个类 还要在spring上下文中配置
对于一个简单的系统而言这就是为自己找不自在
明明盖的是民房 硬要打摩天大楼的地基
浏览: 4013742 次
来自: 一片神奇的土地
可以用,感谢!
[color=red][/color]dfsdsd[color ...
dd发的发给好友
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'若要对@Controller注解标注的bean进行自动扫描,必须将&context:component-scan base-package="包路径.controller"/&放置在dispatcherservlet的配置文件中,若配置在ContextLoaderListener的配置文件applicationContext.xml中则不起作用
&!-- 上下文配置文件 --&
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath:config/spring/spring-*.xml&/param-value&
&/context-param&
&!-- 监听器 --&
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
&在SpringMVC中@Controller注解的bean必须由DispatcherServlet初始化的children webApplicationContext来管理,
&servlet-name&console&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath:config/spring/dispatcher-servlet.xml&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
在DispatcherServlet初始化的context中会扫描当前容器所有的bean实例,根据类级别以及方法级别的映射信息注解组装成对应的HandleMappering信息,但是ContextLoaderListener是不具备这个功能的。
contextLoaderListener对@Service是可以扫描的,可以理解为,由DispatcherServlet加载相当于在ContextLoaderListener加载的基础上增加了controller的处理,所以DispatcherServlet加载的controller和bean都好用,ContextLoaderListener加载的bean好用而controller不好用
web层controlller配置文件最好独立于其他业务bean配置文件,所以一般将对@Controller的自动扫描配置在DispatcherServlet的配置文件中,而将对@Service和@Repository的扫描配置在ContextLoaderListener的配置文件中
阅读(...) 评论()博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
Sprin学习笔记(马士兵spring视频笔记).doc 17页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
你可能关注的文档:
··········
··········
面向接口(抽象)编程的概念与好处
IOC/DI的概念与好处
inversion of control
dependency injection
AOP的概念与好处
Spring简介
Spring应用IOC/DI(重要)
annotation
Spring应用AOP(重要)
annotation
Struts2.1.6 + Spring2.5.6 + Hibernate3.3.2整合(重要)
opensessionInviewfilter(记住,解决什么问题,怎么解决)
Spring JDBC
面向接口编程(面向抽象编程)
场景:用户添加
Spring_0100_AbstractOrientedProgramming
不是AOP:Aspect Oriented Programming
好处:灵活
什么是IOC(DI),有什么好处
把自己new的东西改为由容器提供
初始化具体值
好处:灵活装配
Spring简介
项目名称:Spring_0200_IOC_Introduction
spring.jar , jarkata-commons/commons-loggin.jar
实例化具体bean
管理transaction
Spring IOC配置与应用
FAQ:不给提示:
window – preferences – myeclipse – xml – xml catalog
User Specified Entries – add
Location: D:\share\0900_Spring\soft\spring-framework-2.5.6\dist\resources\spring-beans-2.5.xsd
file:///D:/share/0900_Spring/soft/spring-framework-2.5.6/dist/resources/spring-beans-2.5.xsd
Key Type: Schema Location
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
2. 注入类型
Spring_0300_IOC_Injection_Type
setter(重要)
构造方法(可以忘记)
接口注入(可以忘记)
id vs. name
Spring_0400_IOC_Id_Name
Id\name都行
name可以用特殊字符
&bean name=&u& class=&com.bjsxt.dao.impl.UserDAOImpl&&
&bean id=&userService& class=&com.bjsxt.service.UserService&&
&property name=&userDAO& ref=&u& /&
&constructor-arg&
&ref bean=&u&/&
&/constructor-arg&
简单属性的注入
Spring_0500_IOC_SimpleProperty
&property name=… value=….&
&bean 中的scope属性&bean 的生命范围&
Request\Session\GlobalSession只有Spring和Web Framework结合时才会起作用,比如Spring和Struts结合时才配,但是很少配、、、、
Spring_0600_IOC_Bean_Scope
singleton 单例(默认为Singleton)
在每个Sprign IOC容器中一个Bean定义对应一个对象实例
proptotype 每次创建新的对象
Spring_0700_IOC_Collections
很少用,不重要!参考程序
Spring_0800_IOC_AutoWire
&bean name=&userDAO1& class=&com.bjsxt.dao.impl.UserDAOImpl&&
正在加载中,请稍后...
217页246页134页74页25页42页163页96页28页50页spring ApplicationContext配置文件的加载过程 |
spring ApplicationContext配置文件的加载过程
12月 2, 2014 |
我们在基于spring + spring mvc架构的项目的web.xml中看到如下的经典配置:(定义了两个配置xml文件,将servlet相关的对象定义在一个xml中;其他的定义在另一xml中,比如dao层对象,service对象等)
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&WEB-INF/classes/applicationContext.xml&/param-value&
&/context-param&
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
&servlet-name&mvc&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&WEB-INF/mvc-applicationContext.xml&/param-value&
&/init-param&
&/servlet&
&servlet-mapping&
&servlet-name&mvc&/servlet-name&
&url-pattern&/&/url-pattern&
&/servlet-mapping&
12345678910111213141516171819
&context-param&&param-name&contextConfigLocation&/param-name&&param-value&WEB-INF/classes/applicationContext.xml&/param-value&&/context-param&&listener&&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&&/listener&&servlet&&servlet-name&mvc&/servlet-name&&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&&init-param&&param-name&contextConfigLocation&/param-name&&param-value&WEB-INF/mvc-applicationContext.xml&/param-value&&/init-param&&/servlet&&servlet-mapping&&servlet-name&mvc&/servlet-name&&url-pattern&/&/url-pattern&&/servlet-mapping&
在这段代码中,有pplicationContext.xml 和mvc-applicationContext.xml两个配置文件, 前者通过&context-param&配置,后者作为DispatcherServlet的参数,那么这两个配置文件是加载的,它们是构成一个ApplicationContext,还是构成多个呢,如果是构成两个ApplicationContext,那么这两个ApplicationContext是如何协调工作的?这就是本博文将要回答的问题。
其实所有的问题就藏在ContextLoaderListener 和 DispatcherServlet的源码当中!!!
ContextLoaderListener位于spring-web-3.1.1.RELEASE.jar中,
ServletContextListener实现了ServletContextListener接口,系统启动时会回调contextInitialized()方法。
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader =
this.contextLoader.initWebApplicationContext(event.getServletContext());
public void contextInitialized(ServletContextEvent event) {this.contextLoader = createContextLoader();if (this.contextLoader == null) {this.contextLoader = this;}this.contextLoader.initWebApplicationContext(event.getServletContext());}
将加载的任务委托给了ContextLoader.initWebApplicationContext()方法,该方法的主要代码如下:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
if (this.context instanceof ConfigurableWebApplicationContext) {
configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
return this.
1234567891011121314151617181920
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {// Store context in local instance variable, to guarantee that// it is available on ServletContext shutdown.if (this.context == null) {this.context = createWebApplicationContext(servletContext);}if (this.context instanceof ConfigurableWebApplicationContext) {configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);}servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);&ClassLoader ccl = Thread.currentThread().getContextClassLoader();if (ccl == ContextLoader.class.getClassLoader()) {currentContext = this.context;}else if (ccl != null) {currentContextPerThread.put(ccl, this.context);}return this.context;}
在这个方法中,利用context-param中指定的配置文件初始化ApplicationContext,然后以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key,注册为servletContext的一个属性。
DispatcherServlet位于spring-webmvc-3.1.1.RELEASE.jar中
DispatcherServlet的继承关系为:
DispatcherServlet
|--FrameworkServlet
|--HttpServletBean
initServletBean将初始化的任务委托给initWebApplicationContext()
protected final void FrameworkServlet::initServletBean() throws ServletException {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
protected final void FrameworkServlet::initServletBean() throws ServletException {this.webApplicationContext = initWebApplicationContext();initFrameworkServlet();}
在initFrameworkServlet()中包含如下代码
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());
这个函数的作用就是从ServletContext中获取以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key的ApplicationContext对象,如果返回的值不为空,将其作为新创建的ApplicationContext的parent。具体的逻辑在createWebApplicationContext(ApplicationContext parent)中
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class&?& contextClass = getContextClass();
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException(
"Fatal initialization error in servlet with name '" + getServletName() +
"': custom WebApplicationContext class [" + contextClass.getName() +
"] is not of type ConfigurableWebApplicationContext");
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
wac.setConfigLocation(getContextConfigLocation());
configureAndRefreshWebApplicationContext(wac);
123456789101112131415
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {Class&?& contextClass = getContextClass();if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +"': custom WebApplicationContext class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setParent(parent);wac.setConfigLocation(getContextConfigLocation());configureAndRefreshWebApplicationContext(wac);return wac;}
在这个方法中,创建了一个ApplicationContext对象wac,将其parent设置为传入的ApplicationContext,也就是使用&context-param&中指定的配置文件初始化的ApplicationContext。然后使用DispatcherServlet自身的ApplicationContext初始化wac。
我们的示例中,spring初始化了两个ApplicationContext,&context-param&中指定的配置文件(applicationContext.xml)初始化的ApplicationContext是DispatcherServlet中指定的配置文件(mvc-applicationContext.xml)初始化的ApplicationContext的父Context。
Posted in:}

我要回帖

更多关于 controlleradvice注解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信