Spring 事物机制总结

本文介绍了Spring框架中的两种事务处理机制:声明式事务和编程式事务。详细讲解了声明式事务的五种配置方式,并对比了编程式事务的不同实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring两种事物处理机制,一是声明式事物,二是编程式事物

声明式事物

1)Spring的声明式事务管理在底层是建立在AOP的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),便可以将事务规则应用到业务逻辑中。因为事务管理本身就是一个典型的横切逻辑,正是AOP的用武之地。Spring开发团队也意识到了这一点,为声明式事务提供了简单而强大的支持。Spring强大的声明式事务管理功能,这主要得益于Spring依赖注入容器和Spring AOP的支持。依赖注入容器为声明式事务管理提供了基础设施,使得Bean对于Spring框架而言是可管理的;而Spring AOP则是声明式事务管理的直接实现者。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

2)5种配置方式
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
关系图如下:

http://images.blogjava.net/blogjava_net/robbie/WindowsLiveWriter/Spring_9C9C/Spring%E4%BA%8B%E5%8A%A1%E9%85%8D%E7%BD%AE%20(2).jpg

<bean id="sessionFactory"
	class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
	<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean>

<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

注意:sessionFactorty和transactionManager是下面5中配置方式的基本配置,


第一种方式:每个Bean都有一个代理

<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.test.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
	<!-- 配置事务管理器 -->
	<property name="transactionManager" ref="transactionManager" />
	<property name="target" ref="userDaoTarget" />
	<property name="proxyInterfaces" value="com.test.spring.dao.GeneratorDao" />
	<!-- 配置事务属性 -->
	<property name="transactionAttributes">
		<props>
			<prop key="*">PROPAGATION_REQUIRED</prop>
		</props>
	</property>
</bean>
第二种方式:所有Bean共享一个代理基类

<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true">
	<!-- 配置事务管理器 -->
	<property name="transactionManager" ref="transactionManager" />
	<!-- 配置事务属性 -->
	<property name="transactionAttributes">
		<props>
			<prop key="*">PROPAGATION_REQUIRED</prop>
		</props>
	</property>
</bean>

<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.test.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" parent="transactionBase">
	<property name="target" ref="userDaoTarget" />
</bean>
第三种方式:使用拦截器

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
	<property name="transactionManager" ref="transactionManager" />
	<!-- 配置事务属性 -->
	<property name="transactionAttributes">
		<props>
			<prop key="*">PROPAGATION_REQUIRED</prop>
		</props>
	</property>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<property name="beanNames">
		<list>
			<value>*Dao</value>
		</list>
	</property>
	<property name="interceptorNames">
		<list>
			<value>transactionInterceptor</value>
		</list>
	</property>
</bean>

<!-- 配置DAO -->
<bean id="userDao" class="com.test.spring.dao.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>
第四种方式:使用tx标签配置的拦截器    

<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="*" propagation="REQUIRED" />
	</tx:attributes>
</tx:advice>

<aop:config>
	<aop:pointcut id="interceptorPointCuts"
		expression="execution(* com.test.spring.dao.*.*(..))" />
	<aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
</aop:config>    
第五种方式:全注解

public class test {
	@Transactional
	public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

		public List<User> listUsers() {
			return null
		}
	}
}

编程式事务

Spring的编程式事务即在代码中使用编程的方式进行事务处理,可以做到比声明式事务更细粒度。有两种方式一是使用TransactionManager,另外就是TransactionTemplate。

1)TransactionManager使用方式

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
	private HibernateTransactionManager transactionManager;
	private DefaultTransactionDefinition def;

	public HibernateTransactionManager getTransactionManager() {
		return transactionManager;
	}

	public void setTransactionManager(HibernateTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	public void createTransactionDefinition() {
		def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
	}

	public void saveOrUpdate(User user) {
		TransactionStatus status = transactionManager.getTransaction(def);
		try {
			this.getHibernateTemplate().saveOrUpdate(user);
		} catch (DataAccessException ex) {
			transactionManager.rollback(status);
			throw ex;
		}
		transactionManager.commit(status);
	}
}

2)TransactionTemplate方式

ResultDto ret = null;
ret = (ResultDto) this.transactionTemplate.execute(new TransactionCallback() {
	@Override
	public Object doInTransaction(TransactionStatus status) {
		ResultDto ret = null;
		try {
			drillTaskDao.deleteByKey(taskid);
		} catch (Exception e) {
			logger.error("delDrillTask:" + e.getMessage(), e);
			ret = ResultBuilder.buildResult(ResultBuilder.FAIL_CODE, null, ErrorCode.COM_DBDELETEERROR);
			return ret;
		}
		finally {
			status.setRollbackOnly();
		}
		 
		ret = cleartaskrelativedata(taskid, appid, true);
		return ret;
	}
});
return ret;



<think>我们正在讨论Spring事务注解(@Transactional)的工作原理。根据引用内容,Spring事务分为声明式和编程式,而注解属于声明式事务管理。其核心原理是AOP(面向切面编程)和代理机制。 ### 1. 核心机制:AOP代理 当你在方法或类上添加`@Transactional`注解时,Spring会在运行时为该Bean创建代理对象。这个代理对象会拦截所有带有`@Transactional`注解的方法调用,并在方法执行前后加入事务管理逻辑(开启事务、提交事务、回滚事务)[^2][^3]。 ### 2. 事务管理器的角色 Spring本身并不直接管理事务,而是通过`PlatformTransactionManager`接口委托给具体的事务管理器实现(如JDBC的`DataSourceTransactionManager`、JPA的`JpaTransactionManager`、JTA的`JtaTransactionManager`等)。在Spring Boot中,`@EnableTransactionManagement`会自动根据项目依赖配置事务管理器[^4]。 ### 3. 事务拦截流程 当一个被`@Transactional`注解的方法被调用时: 1. **代理拦截**:代理对象拦截方法调用。 2. **获取事务**:事务管理器根据事务属性(如传播行为、隔离级别等)获取或创建一个事务(可能是一个新事务,也可能是加入现有事务)。 3. **执行业务逻辑**:在事务上下文中执行原始方法。 4. **处理异常**:如果方法抛出异常,事务管理器会根据回滚规则(默认只回滚`RuntimeException`和`Error`)决定是否回滚事务。若未抛出异常或抛出的异常类型不需要回滚,则提交事务[^3]。 ### 4. 关键配置属性 `@Transactional`注解支持以下属性配置: - `propagation`:事务传播行为(例如:REQUIRED、REQUIRES_NEW)。 - `isolation`:事务隔离级别(例如:READ_COMMITTED)。 - `timeout`:事务超时时间。 - `readOnly`:是否只读事务(优化性能)。 - `rollbackFor`/`noRollbackFor`:指定回滚/不回滚的异常类型[^3]。 ### 5. 注意事项 - **方法可见性**:`@Transactional`注解只能应用于`public`方法。如果应用于`protected`、`private`或包可见方法,事务不会生效(因为代理无法拦截非public方法)[^3]。 - **自调用问题**:在同一个类中,一个非事务方法调用另一个`@Transactional`方法时,事务不会生效(因为自调用不会经过代理对象)。需要通过AspectJ或注入自身代理解决[^2]。 ### 示例代码 ```java @Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void createUser(User user) { userRepository.save(user); // 此操作在事务中执行 if (someCondition) { throw new RuntimeException("回滚事务"); // 触发回滚 } } } ``` ### 总结 Spring事务注解通过**AOP代理**和**事务管理器**协作实现。代理负责拦截方法调用并管理事务边界,事务管理器负责底层事务操作(如JDBC连接的事务控制)。理解代理机制和事务属性配置是掌握Spring事务的关键[^2][^3][^4]。 --- **相关问题** 1. **Spring事务的传播行为有哪些?如何选择?** (解释`REQUIRED`、`REQUIRES_NEW`等传播行为的区别和适用场景) 2. **如何解决Spring事务自调用失效的问题?** (探讨AspectJ、代理注入等解决方案) 3. **Spring Boot中如何配置多数据源的事务管理?** (涉及`@Primary`、`@Qualifier`注解和`ChainedTransactionManager`的使用) 4. **Spring事务回滚规则有哪些?如何自定义回滚异常类型?** (分析`rollbackFor`/`noRollbackFor`属性的用法) 5. **声明式事务和编程式事务应该如何选择?** (对比两种事务管理的优缺点及适用场景)</think>Spring事务注解(`@Transactional`)的工作原理基于**AOP代理机制**和**事务管理器协作**实现,其核心实现流程如下: ### 一、核心实现机制 1. **代理对象创建** Spring容器在初始化Bean时,检测到`@Transactional`注解后,会通过AOP(面向切面编程)创建该Bean的**代理对象**(JDK动态代理或CGLIB代理)。 ```java // 原始Bean public class UserService { @Transactional public void updateUser(User user) { ... } } // Spring创建的代理对象(伪代码) public class UserServiceProxy extends UserService { private TransactionManager txManager; public void updateUser(User user) { // 1. 开启事务 // 2. 调用原始方法super.updateUser() // 3. 提交/回滚事务 } } ``` 2. **事务拦截器工作流程** 代理对象通过`TransactionInterceptor`拦截目标方法,按顺序执行: ```mermaid graph TD A[方法调用] --> B{是否有@Transactional} B -->|是| C[获取事务管理器] C --> D[开启事务<br>PlatformTransactionManager.getTransaction] D --> E[执行业务逻辑] E --> F{是否抛出异常?} F -->|是| G[回滚事务<br>txManager.rollback] F -->|否| H[提交事务<br>txManager.commit] ``` ### 二、关键组件协作 1. **事务管理器(PlatformTransactionManager)** Spring Boot根据依赖自动配置: - JDBC → `DataSourceTransactionManager` - JPA → `JpaTransactionManager` - 分布式事务 → `JtaTransactionManager`[^4] 2. **事务属性解析** 注解属性被解析为`TransactionAttribute`对象: | 属性 | 默认值 | 作用 | |---|---|---| | `propagation` | REQUIRED | 事务传播行为 | | `isolation` | DEFAULT | 事务隔离级别 | | `rollbackFor` | RuntimeException | 触发回滚的异常类型 | | `timeout` | -1 | 事务超时时间(秒) | | `readOnly` | false | 是否只读事务 | ### 三、事务执行细节 1. **事务传播机制** 当方法嵌套调用时,根据传播行为处理事务: ```java @Transactional(propagation = Propagation.REQUIRED) // 默认 public void methodA() { methodB(); // 加入当前事务 } @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB() { // 挂起当前事务,开启新事务 } ``` 2. **回滚规则** - 默认只回滚**非检查型异常**(RuntimeException和Error) - 可通过`rollbackFor`自定义: ```java @Transactional(rollbackFor = {SQLException.class, IOException.class}) ``` 3. **事务同步机制** 通过`TransactionSynchronizationManager`绑定资源(如数据库连接)到当前线程,确保同一事务内使用相同连接。 ### 四、重要约束条件 1. **方法可见性要求** 注解必须应用于**public方法**(非public方法事务失效)[^3] ```java // 有效 @Transactional public void validMethod() {...} // 无效(不会报错但事务不生效) @Transactional private void invalidMethod() {...} ``` 2. **自调用问题** 同类中非事务方法调用事务方法会绕过代理: ```java public void outerMethod() { innerMethod(); // 事务失效! } @Transactional public void innerMethod() {...} ``` 解决方案:通过AOP上下文获取代理对象调用。 ### 五、Spring Boot自动配置 通过`@EnableTransactionManagement`开启注解驱动: 1. 自动注册`ProxyTransactionManagementConfiguration` 2. 扫描`@Transactional`注解 3. 根据数据源类型自动配置事务管理器[^4] --- **相关问题** 1. **Spring事务的传播行为有哪些具体区别?如何选择?** (深入解析`REQUIRED`、`REQUIRES_NEW`、`NESTED`等传播行为的应用场景) 2. **事务失效的常见场景有哪些?如何排查?** (分析自调用、异常捕获、方法可见性等典型陷阱的解决方案) 3. **如何在分布式系统中实现跨服务事务?** (对比JTA、Seata、Saga等分布式事务方案的整合) 4. **事务隔离级别数据库锁机制有何关联?** (探讨读提交、可重复读等隔离级别在MySQL/Oracle中的具体实现差异) 5. **如何监控和优化Spring事务性能?** (介绍事务超时配置、只读事务提升性能、事务日志分析等实践)
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值