Spring重复扫描导致事务失败的解决方案及深入分析

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介:

Spring重复扫描导致事务失败的解决方案及深入分析

问题及日志

使用Spring和mybatis,然后配置事务,出现SqlSession was not registered for synchronization because synchronization is not active,事务没有启用成功。

[org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
[org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1a714e6e] was not registered for synchronization because synchronization is not active
[org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
[org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [jdbc: mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java]* will not be managed by Spring*
[com.haoyifen.mySSMTemplate.dao.UserMapper.selectByPrimaryKey] - ==> Preparing: select ID, USER_ID, USER_NAME, SEX, ADDRESS, PHONE_NUMBER, MAIL_BOX from user where ID = ?
[com.haoyifen.mySSMTemplate.dao.UserMapper.selectByPrimaryKey] - ==> Parameters: 1(Integer)
[com.haoyifen.mySSMTemplate.dao.UserMapper.selectByPrimaryKey] - <== Total: 1
[org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1a714e6e]

IntelliJ IDEA的编辑器显示我的拦截路径是正确的。为UserService类创建事务配置。
这里写图片描述

问题分析及解决方案

后来深入分析才发现,原来是扫描配置错误。
我把Spring的ApplicationContext和DispatcherServlet(WebApplicationContext)配置使用两个文件分离开的,分别为spring.xml和spring-mvc.xml。在spring.xml中配置了事务。在两个文件中都启用了扫描设置,用于扫描@Service,@Component和@Controller

spring.xml
<!-- 自动扫描 -->
<context:component-scan base-package="com.haoyifen.mySSMTemplate"></context:component-scan>
spring-mvc.xml
<context:component-scan base-package="com.haoyifen.mySSMTemplate"></context:component-scan>

以上的配置使得spring-mvc重复扫描了userService类,而spring如果要使事务生效,就需要cglib为userService生成代理子类,在spring.xml中已经生成了代理类,而在spring-mvc.xml中,又重新扫描了一遍,使得原先cglib生成的代理子类失效,从而事务拦截也失效。所以我们应该设置spring-mvc.xml,使其不扫描@Service和@Component,spring.xml不扫描@Controller。配置如下:

spring.xml
<!-- 自动扫描 ,忽略@Controller注解的类-->
<context:component-scan base-package="com.haoyifen.mySSMTemplate">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
</context:component-scan>
spring-mvc.xml
<!--自动扫描该包,使spring-mvc只扫描controller包中的类(其中只有@Controller控制器),不会重复扫描到@Service或者@Component-->
<context:component-scan base-package="com.haoyifen.mySSMTemplate.controller">
</context:component-scan>

验证

修改后,再查看日志,就发现已经可以正确启用事务了。
[org.springframework.jdbc.datasource.DataSourceTransactionManager] - Acquired Connection [jdbc:mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java] for JDBC transaction
[org.springframework.jdbc.datasource.DataSourceTransactionManager] - Switching JDBC Connection [jdbc:mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java]* to manual commit*
[org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
[org.mybatis.spring.SqlSessionUtils] -* Registering transaction synchronization for SqlSession* [org.apache.ibatis.session.defaults.DefaultSqlSession@1031238e]
[org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [jdbc:mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java]* will be managed by Spring*
….
[org.mybatis.spring.SqlSessionUtils] -* Transaction synchronization closing SqlSession* [org.apache.ibatis.session.defaults.DefaultSqlSession@1031238e]
[org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction commit
[org.springframework.jdbc.datasource.DataSourceTransactionManager] - Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java]
[org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [jdbc:mysql://localhost:3306/iot, UserName=root@localhost, MySQL Connector Java] after transaction
[org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource

深入日志分析

我们可以查看日志,来分析一下userService的创建过程。在修改xml文件之前:

Application初始化

创建Application时创建了一次userService,并使用cglib代理子类,生成了事务类:
[org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [spring.xml]
…..
开始创建userService类
[org.springframework.beans.factory.support.DefaultListableBeanFactory] -* Creating shared instance of singleton bean ‘userService’*
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Creating instance of bean ‘userService’
……
缓存userService用于其他bean的注入
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Eagerly caching bean ‘userService’ to allow for resolving potential circular references
……
注入userMapper
[org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - Autowiring by type from bean name ‘userService’ to bean named ‘userMapper’
……
生成cglib代理类
[org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator] - Creating implicit proxy for bean ‘userService’ with 0 common interceptors and 2 specific interceptors
[org.springframework.aop.framework.CglibAopProxy] - Creating CGLIB proxy: target source is SingletonTargetSource for target object [com.haoyifen.mySSMTemplate.service.UserService@2c06eb2b]
…..
完成创建,此时的userService已经是被cglib代理过的子类的实例
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Finished creating instance of bean ‘userService’

创建WebApplication子容器

接下来创建WebApplication子容器时,又创建了一次userService,并且没有使用cglib进行代理,所以事务失效。
创建WebApplication
[org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [spring-mvc.xml]
开始创建userService类
[org.springframework.beans.factory.support.DefaultListableBeanFactory] -* Creating shared instance of singleton bean ‘userService’*
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Creating instance of bean ‘userService’
[org.springframework.beans.factory.annotation.InjectionMetadata] - Registered injected element on class [com.haoyifen.mySSMTemplate.service.UserService]: AutowiredFieldElement for private com.haoyifen.mySSMTemplate.dao.UserMapper com.haoyifen.mySSMTemplate.service.UserService.userMapper
缓存userService用于其他bean的注入
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Eagerly caching bean ‘userService’ to allow for resolving potential circular references
[org.springframework.beans.factory.annotation.InjectionMetadata] - Processing injected element of bean ‘userService’: AutowiredFieldElement for private com.haoyifen.mySSMTemplate.dao.UserMapper com.haoyifen.mySSMTemplate.service.UserService.userMapper
[org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean ‘userMapper’
注入userMapper
[org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - Autowiring by type from bean name ‘userService’ to bean named ‘userMapper’
完成创建,本来由cglib代理的子类实例被替换成原生的userService实例,自然也就没有了事务功能
[org.springframework.beans.factory.support.DefaultListableBeanFactory] -* Finished creating instance of bean ‘userService’*

我们按照上面的方法将spring-mvc.xml文件更改后,在创建WebApplication时,就不会再重新创建userService了。

原文地址http://www.bieryun.com/1819.html

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
5月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
|
10月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
261 0
|
8月前
|
人工智能 Java 数据库连接
Spring事务失效场景
本文深入探讨了Spring框架中事务管理可能失效的几种常见场景及解决方案,包括事务方法访问级别不当、方法内部自调用、错误的异常处理、事务管理器或数据源配置错误、数据库不支持事务以及不合理的事务传播行为或隔离级别。通过合理配置和正确使用`@Transactional`注解,开发者可以有效避免这些问题,确保应用的数据一致性和完整性。
603 10
|
7月前
|
Java 关系型数据库 MySQL
【Spring】【事务】初学者直呼学会了的Spring事务入门
本文深入解析了Spring事务的核心概念与使用方法。Spring事务是一种数据库事务管理机制,通过确保操作的原子性、一致性、隔离性和持久性(ACID),维护数据完整性。文章详细讲解了声明式事务(@Transactional注解)和编程式事务(TransactionTemplate、PlatformTransactionManager)的区别与用法,并探讨了事务传播行为(如REQUIRED、REQUIRES_NEW等)及隔离级别(如READ_COMMITTED、REPEATABLE_READ)。
571 1
|
8月前
|
druid Java 关系型数据库
Spring Boot与Druid升级解决方案
好的,我需要帮助用户解决他们遇到的数据库连接问题,并升级项目的依赖。首先,用户提供的错误信息是关于Spring Boot应用在初始化数据源时抛出的异常,具体是Druid连接池验证连接失败。同时,用户希望升级项目的依赖版本。
797 10
|
7月前
|
负载均衡 Java API
基于 Spring Cloud 的微服务架构分析
Spring Cloud 是一个基于 Spring Boot 的微服务框架,提供全套分布式系统解决方案。它整合了 Netflix、Zookeeper 等成熟技术,通过简化配置和开发流程,支持服务发现(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、API网关(Zuul)、配置管理(Config)等功能。此外,Spring Cloud 还兼容 Nacos、Consul、Etcd 等注册中心,满足不同场景需求。其核心组件如 Feign 和 Stream,进一步增强了服务调用与消息处理能力,为开发者提供了一站式微服务开发工具包。
698 0
|
9月前
|
监控 Java 关系型数据库
Spring Boot整合MySQL主从集群同步延迟解决方案
本文针对电商系统在Spring Boot+MyBatis架构下的典型问题(如大促时订单状态延迟、库存超卖误判及用户信息更新延迟)提出解决方案。核心内容包括动态数据源路由(强制读主库)、大事务拆分优化以及延迟感知补偿机制,配合MySQL参数调优和监控集成,有效将主从延迟控制在1秒内。实际测试表明,在10万QPS场景下,订单查询延迟显著降低,超卖误判率下降98%。
421 5
|
9月前
|
SQL 前端开发 Java
深入分析 Spring Boot 项目开发中的常见问题与解决方案
本文深入分析了Spring Boot项目开发中的常见问题与解决方案,涵盖视图路径冲突(Circular View Path)、ECharts图表数据异常及SQL唯一约束冲突等典型场景。通过实际案例剖析问题成因,并提供具体解决方法,如优化视图解析器配置、改进数据查询逻辑以及合理使用外键约束。同时复习了Spring MVC视图解析原理与数据库完整性知识,强调细节处理和数据验证的重要性,为开发者提供实用参考。
403 0
|
9月前
|
安全 前端开发 Java
Spring Boot 项目中触发 Circular View Path 错误的原理与解决方案
在Spring Boot开发中,**Circular View Path**错误常因视图解析与Controller路径重名引发。当视图名称(如`login`)与请求路径相同,Spring MVC无法区分,导致无限循环调用。解决方法包括:1) 明确指定视图路径,避免重名;2) 将视图文件移至子目录;3) 确保Spring Security配置与Controller路径一致。通过合理设定视图和路径,可有效避免该问题,确保系统稳定运行。
636 0

热门文章

最新文章