<tx:annoation-driven/>, web.xml的Spring配置文件位置,Spring父子容器, Spring部分源代码分析,<mvc:annotation-driven/>


	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	bean>
	
	<tx:annotation-driven transaction-manager="transactionManager"/>

在配置文件中,默认情况下,会自动使用名称为transactionManager的事务管理器。
所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用
@Transactional可以加在Controller层,但是前提是位置必须放置正确:
在spring-framework-reference.pdf文档中有这样一段话:
only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.
这句话的意思是,只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解,如果你把它放在Dispatcher的应用上下文中(意思就是说如果你用的是servlet的方式加载spring-mvc.xml文件,并且将写在spring-mvc.xml文件中),它只检查控制器上的@Transactional注解,而不是你services上的@Transactional注解。

web.xml的Spring配置文件位置:

<context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>
    
    classpath:applicationContext.xml
        param-value>
  context-param>
<servlet-name>springmvcservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
      <param-name>contextConfigLocationparam-name>
      
      <param-value>classpath:springmvc.xmlparam-value>
    init-param>
  servlet>

另外一种方式是可以将spring的所有配置文件都放在context-param(上下文参数)中进行加载。

<context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>
            classpath:applicationContext.xml,
            classpath:spring-servlet.xml
        param-value>
context-param>

Spring父子容器:
为什么上面另外一种方式可以将spring的所有配置文件都放在context-param(上下文参数)中,引出了一个父子容器的概念,而典型的父子容器就是spring和springmvc同时使用的时候。分别ContextLoaderListener 创建的 容器是父容器,DispatcherServlet 创建的容器是子容器。

而父容器和子容器的区别。比如父容器有a.b.c三个bean对象,子容器有d.e.f三个bean对象,子容器就可以通过getBean方法调用父容器的a.b.c bean对象,而父容器不能通过getBean拿到子容器的d.e.f三个bean对象。但是这里有一个例外property-placeholder,容器中读取的配置文件就是私有的,互相不能访问。其中也要弄清楚的是父子容器并不是一种包含关系,而是平行关系,但是在子容器中有一个parent,指向父容器,也就是说子容器在通过getBean访问父容器中的bean对象时是通过parent访问。

这种做法的实际意思就是在一个JVM,只有一个树状结构的容器树。可以通过子容器访问父容器资源。就比如在实际开发中使用ssm框架,spring可以管理service,mapper,springmvc管理controller,mybatis编写mapper,controller就需要调用service,service调用mapper,因为springmvc容器是spring的子容器,可以通过父容器找到service和mapper,但是在service中却是找不到controller的。保证一种资源的局部性。

这也就是为什么如果将事务配置在子容器,即Dispatcher的应用上下文中,会导致父容器的service事务不起作用,因为父容器是访问不了子容器资源的,而如果将配置在父容器,不仅servicer能进行加事务注解,controller也可以,因为子容器能访问到父容器资源。

spring-servlet.xml如果配置在,即被配置在servlet的初始化过程中,所以如果不初始化servlet,那么spring-servlet.xml是不会被发现的。如果我们将定时器的注解加载过程放在spring-servlet.xml中,如果不进行页面的刷新,是不会经过DispatcherServlet这个跳转器的,所以也就不会加载spring-servlet.xml文件,所以定时任务可能就不会被触发。如果经过了这个DispatcherServlet这个跳转器,即被初始化。所以定时任务才会被执行。这是servlet的基本知识,浏览器需要访问时,servlet才会进行真正的实例化。

更多请详看:
https://blog.csdn.net/weixin_46228112/article/details/124602459
https://blog.csdn.net/qq_39326498/article/details/126663514

Spring部分源代码分析:

<tx:annoation-driven/>, web.xml的Spring配置文件位置,Spring父子容器, Spring部分源代码分析,<mvc:annotation-driven/>_第1张图片
在这里插入图片描述
<tx:annoation-driven/>, web.xml的Spring配置文件位置,Spring父子容器, Spring部分源代码分析,<mvc:annotation-driven/>_第2张图片

配置注解映射器和适配器

在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。
在这里插入图片描述
使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
mvc:annotation-driven默认加载很多的参数绑定方法,比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发时使用

你可能感兴趣的:(IT-JAVA,java)