5

我对 Spring 3.2.3 @Transactional 注释有疑问。我的服务类如下所示:

@Service @Transactional
class InventoryDisclosureBO {

@Autowired InventoryDisclosureDAO inventoryDisclosureDAO;

private static final Logger log = LoggerFactory.getLogger( InventoryDisclosureBO.class);

public void processDisclosureData(InventoryDisclosureStatus data){
  validate(data);
  persist(data);
}

@Transactional(propagation = REQUIRES_NEW)
void persist(InventoryDisclosureStatus data) {
  inventoryDisclosureDAO.setAllInvalid( data.getUnit());
  inventoryDisclosureDAO.insert( data );
}

void validate(InventoryDisclosureStatus data) {
 ...
}
}

如果我调用 persist() 方法,一切都会完美地工作。但是,如果我在类级别注释掉 @Transactional - 事务不会开始。有人能告诉我为什么 Spring 只能在甲醇级别忽略 @Transactional 吗?

4

2 回答 2

7

您不能从 processDisclosureData() 调用 persist(),因为它属于同一类,并且它将绕过 Spring 为 InventoryDisclosureBO 创建的事务代理。您应该从其他 bean 调用它以使 @Transactional 注释工作。当 Spring 向其他 bean 注入对 InventoryDisclosureBO bean 的引用时,它实际上注入了对包含事务逻辑的 InventoryDisclosureBOProxy 的引用,例如

    class Bean2 {

      @Autowire
      private InventoryDisclosureBO idbo;   <-- Spring will inject a proxy here

      public void persist(InventoryDisclosureStatus data) {
           idbo.persist(data);     <-- now it will work via proxy
      }
...
于 2013-09-03T10:43:58.937 回答
3

这与 spring 如何生成事务代理有关。

在类级别有@Transactional 的情况下,InventoryDisclosureBO.processDisclosureData()实际上,当您调用时,您正在调用一个启动事务的Spring 代理,然后调用真正的实现。

如果你在 persis() 中只有@Transaction,那么当你调用时 spring 不会启动事务InventoryDisclosureBO.processDisclosureData(),然后它就无法检测到你已经调用了 InventoryDisclosureBO.persist()

所以 Spring 基本上忽略了 on 上的注解persist,因为它不能添加事务代理。

根据经验,@Transactional 注释应该在公共方法上,并且希望在调用层次结构中相当高(否则每个持久化最终都会创建一个新事务)

您可能会找到有关此其他 SO 问题的更多信息:私有方法上的方法拦截器(任何非公共方法的行为方式相同)

于 2013-09-03T10:48:21.630 回答