@Transactional 注解的行为规则
类级别的 @Transactional
注解:
- 仅影响该类中定义的方法。
- 不会自动应用到父类的方法。
- 如果子类重写了父类的方法,子类的方法会继承事务配置。
方法级别的 @Transactional
注解:
- 仅影响被注解的方法。
- 不会自动应用到父类的同名方法。
- 如果子类重写了父类的方法并添加了
@Transactional
注解,子类的方法会开启事务。
下面通过具体的代码示例来详细说明这些行为。
示例代码
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ParentService {
// 方法级别的 @Transactional 注解
@Transactional
public void parentMethod() {
System.out.println("父方法被调用,事务中执行。");
}
public void nonTransactionalParentMethod() {
System.out.println("非事务的父方法被调用。");
}
}
@Service
public class ChildService extends ParentService {
// 子类重写父类的方法,继承了事务配置
@Override
public void parentMethod() {
System.out.println("子方法被调用,继承父类的事务配置,事务中执行。");
}
// 子类重写父类的方法,并添加了新的事务配置
@Override
@Transactional
public void nonTransactionalParentMethod() {
System.out.println("子方法被调用,新的事务配置,事务中执行。");
}
// 子类新增的方法,带有事务配置
@Transactional
public void childMethod() {
System.out.println("子方法被调用,事务中执行。");
}
// 子类新增的方法,没有事务配置
public void nonTransactionalChildMethod() {
System.out.println("非事务的子方法被调用。");
}
}
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
// 类级别的 @Transactional 注解
@Transactional
public class ParentService {
// 该方法会继承类级别的事务配置,在事务中执行
public void parentMethod() {
System.out.println("父方法被调用,事务中执行。");
}
// 该方法也会继承类级别的事务配置,在事务中执行
public void anotherParentMethod() {
System.out.println("另一个父方法被调用,事务中执行。");
}
// 即使没有显式添加 @Transactional 注解,也会继承类级别的事务配置
public void nonTransactionalParentMethod() {
System.out.println("非事务的父方法被调用,但由于类级别的注解,仍然在事务中执行。");
}
}
@Service
public class ChildService extends ParentService {
// 子类重写父类的方法,继承了事务配置
@Override
public void parentMethod() {
System.out.println("子方法被调用,继承父类的事务配置,事务中执行。");
}
// 子类重写父类的方法,并添加了新的事务配置
@Override
@Transactional
public void nonTransactionalParentMethod() {
System.out.println("子方法被调用,新的事务配置,事务中执行。");
}
// 子类新增的方法,带有事务配置
@Transactional
public void childMethod() {
System.out.println("子方法被调用,事务中执行。");
}
// 子类新增的方法,没有事务配置
public void nonTransactionalChildMethod() {
System.out.println("非事务的子方法被调用。");
}
}
代理机制注意事项
- Spring 的
@Transactional
注解是基于代理实现的。只有通过代理对象调用的方法才会触发事务管理。例如,通过ChildService
的代理对象调用parentMethod
、anotherParentMethod
、nonTransactionalParentMethod
、childMethod
和nonTransactionalChildMethod
方法时,事务配置才会生效。 - 直接在类内部调用其他方法(如
this.method()
)不会触发事务。