从事Java开发这些年,Spring框架的事务管理机制一直是面试必问和实际开发中最常打交道的部分。但很多人可能和我当初一样,虽然会用@Transactional注解,却对底层实现一知半解。今天我们就深入Spring IOC容器,看看声明式事务究竟是如何被加载和处理的。
Spring提供了编程式事务和声明式事务两种管理方式。声明式事务通过AOP实现,其核心在于将事务管理代码从业务逻辑中解耦。当我们使用@Transactional注解时,实际上是在告诉Spring:"这段方法需要事务支持,具体怎么实现你帮我搞定"。
这个注解是声明式事务的启动开关。在Spring Boot中,它通常由@SpringBootApplication间接引入。其核心作用是向容器注册两个关键Bean:
java复制@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
}
这个类决定了使用哪种方式实现事务管理(基于代理或AspectJ)。默认情况下,Spring会选择基于JDK动态代理或CGLIB的方式:
java复制protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
这个配置类定义了三个核心Bean:
java复制@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
// 创建增强器并设置属性源和拦截器
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}
@Bean
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
这个拦截器是整个声明式事务的核心执行者,其invoke方法主要逻辑:
java复制public Object invoke(MethodInvocation invocation) throws Throwable {
// 获取目标类
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// 执行带事务逻辑的方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
这个类负责解析@Transactional注解,将其转换为Spring内部的事务属性表示。关键方法是:
java复制protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 解析传播行为
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
// 解析隔离级别
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
// 解析超时时间
int timeout = attributes.getNumber("timeout");
if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) {
rbta.setTimeout(timeout);
}
// 解析是否只读
rbta.setReadOnly(attributes.getBoolean("readOnly"));
// 解析回滚规则
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
// 其他规则解析...
rbta.setRollbackRules(rollbackRules);
return rbta;
}
Spring处理@Transactional注解时有以下优先级规则:
这个增强器将事务拦截器和事务属性源组合在一起,它实现了PointcutAdvisor接口,主要功能:
java复制public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
public Pointcut getPointcut() {
return this.pointcut;
}
}
AutoProxyRegistrar向容器注册了InfrastructureAdvisorAutoProxyCreator,这个Bean后处理器负责:
以DataSourceTransactionManager为例,其核心方法:
java复制protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 获取数据库连接
con = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(con), true);
// 设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// 设置只读标志
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
con.setAutoCommit(false);
}
// 其他初始化操作...
} catch (Throwable ex) {
// 异常处理
}
}
TransactionInterceptor最终会调用TransactionManager的commit或rollback方法:
java复制protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
// 其他处理...
}
}
当应用需要操作多个数据源时,可以通过@Qualifier指定使用哪个事务管理器:
java复制@Service
public class OrderService {
@Transactional("orderTransactionManager")
public void createOrder(Order order) {
// 使用订单数据源的事务
}
@Transactional("userTransactionManager")
public void updateUser(User user) {
// 使用用户数据源的事务
}
}
通过实现TransactionAttributeSource接口,可以支持自定义的事务属性定义方式:
java复制public class CustomTransactionAttributeSource implements TransactionAttributeSource {
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
// 实现自定义的解析逻辑
return ...;
}
}
Spring提供了事务事件监听机制,可以监听事务的各个阶段:
java复制@Component
public class MyTransactionEventListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(TransactionCompletedEvent event) {
// 事务提交后的处理
}
}
事务边界要清晰:一个事务应该对应一个完整的业务操作,而不是简单的每个方法都加事务
注意事务中的远程调用:在事务中包含HTTP/RPC调用可能导致事务时间过长
合理处理事务中的异常:有些业务异常可能需要捕获而不回滚事务
测试事务行为:编写单元测试验证事务的传播行为和回滚逻辑
监控事务性能:通过Spring Actuator或自定义监控统计事务执行时间和成功率
提示:在复杂的业务场景中,可以考虑使用TransactionTemplate进行编程式事务管理,它提供了更灵活的控制方式,特别是在需要根据运行时条件决定是否提交事务的情况下特别有用。
理解Spring事务的实现原理不仅可以帮助我们更好地使用它,还能在出现问题时快速定位原因。建议大家在掌握基本原理后,可以进一步研究不同传播行为的具体实现,这对处理复杂业务场景中的事务问题非常有帮助。