Итак, вы инкапсулировали логику разграничения транзакций в одном месте и используете динамический прокси-сервер для улучшения существующих служб с помощью управления транзакциями и сокращения стандартного кода, верно?
Звучит довольно неплохо для меня.На самом деле то, что делают контейнеры, такие как Spring или EJB, когда мы говорим о декларативном разграничении транзакций , очень похоже.С точки зрения реализации вы можете сделать это с помощью динамического прокси или инструментария байт-кода, или даже использовать AspectJ.Однажды я сделал нечто очень похожее для крошечной тестовой среды.Вот сообщение в блоге об этом.
Хитрые части, которые я вижу:
1) Только откат ,Согласно спецификации JPA, транзакция объекта может быть помечена как « только откат ».Такая транзакция никогда не может совершить.Поэтому я чувствую, что вы должны проверить это между этими двумя строками:
result = method.invoke(object, args);
et.commit();
2) Повторный вход .Большинство систем с декларативной транзакцией реализуют семантику, в которой транзакция запускается, только если она еще не активна (см. «Обязательно» в этом списке аннотаций EJB ).Похоже, вам следует проверить это с помощью isActive
в вашей логике.
3) Обработка исключений .Будьте очень осторожны с распространением исключений в динамическом прокси.Предполагается, что прокси должен быть максимально прозрачным для клиента.Если из DAO просачивается исключение, отличное от DAOException
, прокси преобразует его в RuntimeException
.Не кажется оптимальным для меня.Также не путайте исключение, потому что invoke
не удалось, и исключение, заключенное в вызове, которое, я думаю, вы должны перебросить как есть:
catch ( InvocationTargetException e )
{
Throwable nested = e.getTargetException();
throw nested;
}
Заключение :Идея использовать динамический прокси в этом сценарии звучит хорошо для меня.Но я подозреваю, что есть несколько вещей, которые нужно перепроверить в вашем коде (я не помню всех деталей спецификаций JPA и обработки исключений с помощью динамического прокси, но есть некоторые сложные случаи).Этот вид кода может скрывать скрытые ошибки, поэтому стоит потратить время, чтобы сделать его пуленепробиваемым.