使用spring的@Transactional对一个也使用aop的方法:在建议之后

时间:2011-06-14 13:35:55

标签: java spring annotations aop transactional

我试图看看是否已经有类似的问题,但是找不到它,就在这里。

我们有一个遗留代码,其中单个BO使用反射对许多DAO进行方法调用。 为简单起见,我修改了代码。

@Transactional
class EndpointData1DAO implements DAO{
  void inserData() {
   // insert data 1
  }
}

@Transactional
class EndpointData2DAO implements DAO{
  void inserData() {
    // insert data 2
  }
}

class MachoBO {
 void handleEverything(String daoName) {
   DAO dao = getDAOUsingReflection(daoName);
   dao.insertData();
 }
}

问题是,需求已更改,因此在EndpointData1DAO上调用insertData()时,还必须调用EndpointData2DAO的insertData。

我可以简单地将EndpointData2DAO添加为EndpointData1DAO的成员,但这会严重违反SRP并使其变得难看。

所以我编写了一个注释@ExecuteAfter(clazz = EndpointData2DAO.class,method =“insertData”),它获取EndpointData2DAO的一个实例并调用insertData(), 在执行它注释的类的方法之后,通过使用aop:after,以便给出

@Transactional
@ExecuteAfter(clazz=EndpointData2DAO.class, method="insertData") 
class EndpointData1DAO implements DAO{
  void inserData() {
   System.out.println("insert1");
  }
}

@Transactional
class EndpointData2DAO implements DAO{
  void inserData() {
   System.out.println("insert2");
  }
}

class MachoBO {
 void handleEverything(String daoName) {
   DAO dao = getDAOUsingReflection(daoName);
   dao.insertData();
 }

1 2 将在调用machoBO.handleEverthing(“Data1”);

时打印出来

现在我的问题是, 将EndpointData1DAO和EndpointData2DAO的insertData()置于同一物理事务中? 换句话说,EndpointData2DAO的insertData()中的运行时异常是否会回滚EndpointData1DAO'insertData()所插入的数据?

提前多了〜!!

1 个答案:

答案 0 :(得分:0)

我通过实际运行测试找到了答案。

通过执行以下代码,我能够找到当前正在运行的事务的名称。

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        Class tsmClass = contextClassLoader.loadClass("org.springframework.transaction.support.TransactionSynchronizationManager");
        String transactionName = (String) tsmClass.getMethod("getCurrentTransactionName", null).invoke(null, null);
        System.out.println(transactionName);

并想出我放的时候 在MachoBO上的@Transactional如下,

@Transactional
class MachoBO {
 void handleEverything(String daoName) {
   DAO dao = getDAOUsingReflection(daoName);
   dao.insertData();
 }

因为@Transactional有一个“方法范围”, 调用machoBO.handleEverthing("Data1");时 两个DAO的inserData()在事务名称“MachoBO.handleEverthing”下执行。

但是,当MachoBO未使用@Transactional注释时, 两个DAO的inserData()不共享相同的方法范围,&因此, 在单独的事务下执行,即“EndpointData1DAO.inserData”和“EndpointData2DAO.insertData”。

应该注意的是(虽然很明显)在DAO使用@Transactional注释并且传播设置为REQUIRES_NEW的情况下,DAO的insertData()在单独的事务中运行。