spring注解与springMVC注解扫描的问题

  在将spring与springMVC结合使用时,当我们使用注解的时候,一般都是在spring配置文件中配置注解扫描dao层、service层的包,在springMVC配置文件中配置注解扫描controller,自己在练习spring+SpringMVC+mybatis的项目时对这种做法一知半解,所以在练习项目的时候在实践中对自己的一些想法进行了验证。

  • 一般的配置

    •   spring配置文件中

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:aop="http://www.springframework.org/schema/aop"
              xmlns:tx="http://www.springframework.org/schema/tx"
               xmlns:context="http://www.springframework.org/schema/context"
              xsi:schemaLocation="
                  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
           <!-- 启用注解  -->
          <context:annotation-config />
      
          <!-- 设置使用注解的类所在的包 -->
          <context:component-scan base-package="dao,service.*"></context:component-scan>
      
          <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              <property name="locations">
                  <list>
                      <value>classpath:config/jdbc.properties</value>
                  </list>
              </property>
          </bean>
          <!-- c3p0连接池配置 -->
           <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                 <!-- 四大参数的name不能换,和连接池的构造函数有关-->
                <property name="driverClass" value="${jdbc.driverClassName}"/>
                <property name="jdbcUrl" value="${jdbc.url}" />
                <property name="user" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />  
      
                 <!--连接池中保留的最大连接数。默认值: 15 -->
                <property name="maxPoolSize" value="20"/>
                <!-- 连接池中保留的最小连接数,默认为:3-->
                <property name="minPoolSize" value="2"/>
                <!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->
                <property name="initialPoolSize" value="2"/>  
      
                <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
                <property name="maxIdleTime" value="60"/>  
      
                <!-- 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 -->
                <property name="checkoutTimeout" value="3000"/>  
      
                <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
                <property name="acquireIncrement" value="2"/>  
      
               <!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次-->
                <property name="acquireRetryAttempts" value="0"/>  
      
                <!--重新尝试的时间间隔,默认为:1000毫秒-->
                <property name="acquireRetryDelay" value="1000" />  
      
                <!--关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 -->
                <property name="autoCommitOnClose" value="false"/>  
      
                <!--c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0-->
                <property name="maxStatements" value="100"/>
                <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 -->
                <property name="maxStatementsPerConnection" value="0"/>
           </bean>
           <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
            <!-- 配置mybatis配置文件 -->
            <property name="configLocation">
               <value>classpath:config/sqlMapConfig.xml</value>
            </property>
             <!-- 实体类映射文件路径,可以在这里直接配置,也可以在configLocation配置的文件中配置 ibatis2不支持 -->
             <!-- <property name="mapperLocations" value="classpath:config/sqlmap/*.xml" />  -->
          </bean>
          <!-- Dao -->
          <bean id="ibatisDao" class="dao.IbatisDao">
               <property name="dataSource" ref="dataSource"></property>
               <!-- 这里的dao继承SqlMapClientDaoSupport,所以要显示的配置注入 sqlMapClient-->
                <property name="sqlMapClient">
                  <ref bean="sqlMapClient"/>
               </property>
          </bean>
          <!-- 开启事务注解 -->
          <tx:annotation-driven transaction-manager="transactionManager"/>
          <!-- 定义事务管理器(声明式的事务) -->
          <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean>
      
      </beans>

      这里我们配置了事务管理器和基本的dao。service层采用的是注解注入

    •  springMVC配置文件中:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
              xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
      <!--     启用spring mvc 注解 -->
          <context:annotation-config />
      
          <!-- 设置使用注解的类所在的包 -->
         <context:component-scan base-package="controller"></context:component-scan>   
      
          <!-- 完成请求和注解POJO的映射  3.1后已经过时 与DefaultAnnotationHandlerMapping配套使用
          <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />-->
          <!-- 新的注解映射-->
          <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
      
           <!-- 使用新的注解映射必须指定 RequestMappingHandlerMapping去替代过时的DefaultAnnotationHandlerMapping-->
           <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
           <!-- 使用ajax向前台返回json需要在注解映射中添加转换器 -->
           <!-- 依赖包为jackson-core 、 jackson-annotation、 jackson-databind -->
           <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
                    <property name="messageConverters">
                        <list>
                            <ref bean="jsonHttpMessageConverter"/>
                        </list>
                    </property>
          </bean>
      <bean id="jsonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" /><!--   用于jackson2 -->
           <!--  class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> -->
      
          <!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/page/" p:suffix=".jsp" />
      </beans>

      springMVC配置文件中配置了指定的HandlerAdapter和HandlerMapping以及Resolver。
      在这种配置下,项目能正常运行,配置了@Transactional的service中的事务也能被我们的事务管理器管理。

  • 只在spring配置文件中启用注解扫描(关闭springmvc扫描),扫描dao、service、controller。
      这种情况下,项目启动正常,但是无法处理我们的请求,鉴于springmvc容器是spring容器的子容器,我猜想由于controller中的所有请求处理方法我都是采用@requestMapping来进行配置的,requestMapping都是由我们的springMVC配置文件中配置的HandlerAdapter和HandlerMapping以及Resolver的Bean来进行处理(即使我们不在这里面配置,spingmvc也有默认的),但是父容器又不能访问子容器的bean,所以即使扫描了controller包也无法将controller的处理方法与我们的请求正确mapping,所以这里如果仅仅在spring中扫描所有包,项目是无法实现正常运转的。
  • 只在spring配置文件中启用注解扫描,扫描dao、service、controller,并且在spring配置文件中配置springmvc的HandlerAdapter和HandlerMapping以及Resolver。
      这种情况项目与我们一般配置的效果一样,这种情况就相当于我们在spring中也完成了spingmvc的配置,将原本应该在springmvc容器中的bean直接在spring中配置,虽然效果是一样的,但是不建议这种做。这种配置的结果也代表我们上一种情况出现的原因的猜想是对的,spring父容器无法访问springmvc中的bean,无法将扫描到的controller与请求url正确适配。
  • 在springMVC配置文件中启用注解扫描(关闭spring扫描),扫描dao、service、controller。
      这种情况下项目能正常跳转,但是我们通过@Transactional配置的service事务失效,这里是因为spring容器配置了事务管理器后,装配的service都是经过cglib代理过的实例,具有事务功能,而springmvc容器装配的service是没有进行代理处理的,所以是没有事务功能的,这一点可以参见这篇博客http://blog.csdn.net/haoyifen/article/details/51172647。这里我试着在springMVC配置文件中也配置了一个事务管理器过后,发现一切正常了,由springmvc装配的service同样也具备事务功能,这里就很奇怪,为什么父容器配置的事务管理器子容器无法使用呢?父容器中的bean子容器都是可以访问的,为什么没有使用呢?
    到这里差不多可以回答开始的问题了,为什么要在spring中扫描dao、service,因为通过spring容器扫描dao以及service可以进行事务的增强,如果你仅仅在一个子容器中进行事务的增强那么其他的serviceBean是不会被事务增强的(比如第四种情况中,如果我们在spring容器中手动配置一个bean,那么这个bean不是由springmvc装配的,而我们的事务管理器在springmvc中,这个bean就不具备事务的功能)。而controller之所以要在springmvc中配置,因为spring容器无法访问到springmvc容器的bean(HandlerAdapter和HandlerMapping以及Resolver等),无法完成请求与hander的正确适配,如果要强行实现,在spring中配置HandlerAdapter和HandlerMapping以及Resolver则显得太过牵强。在书上看到的一种说法是这样也体现了分层的概念,dao、service等web层都需要使用的bean应该直接在spring容器中装配,而controller这种则放在专门处理请求跳转的springmvc容器中,相对于将所有bean配置在spring容器中,也体现了权限控制的思想吧。
时间: 2024-08-02 07:20:23

spring注解与springMVC注解扫描的问题的相关文章

Spring学习笔记-springMVC基于注解的控制器(Demo)

springmvc的整体运行流程图: 基于@Controller和@RequestMapping是springmvc示例代码 在web.xml中配置springmvc核心分发器DispatcherServlet .... <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </

Spring学习笔记-springMVC基于注解的控制器(基本概念)

在spring2.5以前的版本中,实现一个mvc的Controller的唯一方法就是实现Controller接口,一个控制器只能响应一个客户端请求,在2.5以后的版本中,spring引入了注解,利用注解简化配置文件,利用注解实现bean的声明和依赖注入(DI),注解也同样被引入到spring的web模块springMVC中. 使用基于注解的控制器有两个优点 第一:一个控制器可以处理多个动作,而不是像以前那样一个控制器只能处理一个请求 第二:省略的在配置文件中对bean的声明和依赖注入,显著提高开

Spring基于注解及SpringMVC

1.使用注解 (1)组件扫描 指定一个包路径,Spring会自动扫描该包 及其子包所有组件类,当发现组件类定义前有 特定的注解标记时,就将该组件纳入到Spring 容器.等价于原有XML配置中的<bean>定义功能. 组件扫描可以替代大量XML配置的<bean>定义. (2)如何使用 step1,在配置文件当中,添加 <context:component-scan base-package=""/> 让容器扫描指定的包及其子包下面的类. step2,

Spring Boot2.0之注解方式启动Springmvc

回顾下springmvc原理图: DispatcherServlet是Spring MVC的核心,每当应用接受一个HTTP请求,由DispatcherServlet负责将请求分发给应用的其他组件. 在旧版本中,DispatcherServlet之类的servlet一般在web.xml文件中配置,该文件一般会打包进最后的war包种:但是Spring 3引入了注解,我将要介绍,如何基于注解配置Spring MVC. 1.Spring mvc无配置文件夹,采用注解方式启动. 把配置的内容 转换为 Ja

Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)

转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇) 本文主要内容: (1)SpringMVC校验 (2)数据回显 (3)异常处理器 (4)图片上传 (5)Json数据交互 (6)支持RESTful 1.SpringMVC校验 1.1校验理解 项目中,通常使用较多的是前端的校验,比如页面中js校验.对于安全要求较高的

结合项目(Spring+(基于注解的)SpringMVC和Mybatis+uploadify文件上传)--poi解析Excel文件

poi解析Excel文件 1.上传文件至服务器 2.解析Excel文件并返回数据集合 3.将数据保存到服务器 框架======Spring+(基于注解的)SpringMVC和Mybatis===== 第一步: 前台: jsp文件采用的是uploadify <div id="fileQueue"></div> <input type="file" id="brandFile"> js: <script ty

Java 系列之spring学习--springmvc注解方式(五)

一.springmvc注解方式 注解方式使用的更多,更加灵活.在上一篇的博客的基础上修改springmvc-servlet.xml配置文件. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchem

谈谈Spring的IoC之注解扫描

问题 ??IoC是Inversion of Control的缩写,翻译过来即"控制反转".IoC可以说是Spring的灵魂,想要读懂Spring,必先读懂IoC.不过有时候硬着头皮直接看源码,就像雾里看花,并不能一窥真谛.想要理解Spring的IoC,不如反过来思考一下,如果我们自己去实现IoC,需要考虑什么?遵循依赖大于配置的原则,我们这里只讨论注解式的控制反转容器,XML配置的方式暂不考虑.由此我想到下面几个问题: 注解扫描 实例化 循环依赖 泛型注入 本文的重点,就是围绕这几个问

SpringMVC注解启用

本文是我在学习网络视频SpringMVC的过程中写下的.感谢发布视频的各位前辈 下面讲解SpringMVC注解启用的几个关键步骤: 首先需要加载配置文件(如果使用本人的代码请自己定义路径) <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://