#java #spring #annotations #aop #transactional
#ява #spring #аннотации #аоп #транзакционный #java #aop
Вопрос:
я пытался посмотреть, есть ли уже подобный вопрос, но не смог его найти, так что, вот он.
у нас есть устаревший код, в котором один 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();
}
}
проблема в том, что требование изменилось, поэтому, когда insertData () вызывается в EndpointData1DAO, также должны вызываться insertData EndpointData2DAO.
я мог бы просто добавить 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»);
теперь мой вопрос в том, будет ли insertData() EndpointData1DAO и EndpointData2DAO находиться в одной физической транзакции? другими словами, будет ли исключение во время выполнения в программе EndpointData2DAO insertData() откатывать данные, вставленные EndpointData1DAO’ insertData()?
заранее большое спасибо~!!
Ответ №1:
Я нашел ответ, фактически запустив тест.
Выполнив следующий код, я смог узнать имя текущей транзакции.
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);
и понял, что, когда я вставил
@Transactional для MachoBO, как показано ниже,
@Transactional
class MachoBO {
void handleEverything(String daoName) {
DAO dao = getDAOUsingReflection(daoName);
dao.insertData();
}
поскольку @Transactional имеет «область действия метода»,
когда machoBO.handleEverthing("Data1");
вызывается,
inserData() обоих DAO выполняется под именем транзакции «MachoBO.handleEverthing».
Однако, когда MachoBO НЕ помечен @Transactional, inserData() обоих DAO НЕ использует одну и ту же область применения метода, и поэтому выполняется в рамках отдельных транзакций, а именно «EndpointData1DAO.inserData» и «EndpointData2DAO.insertData».
Однако следует отметить (хотя это и очевидно), что в случае, когда DAO аннотируется с помощью @Transactional с набором для распространения REQUIRES_NEW , insertData() DAO выполняется в отдельной транзакции.