Комментарии 11
Первый же результат по запросу "
Я сам такое не городил, поэтому вопрос: Вы это пробовали? Работает? Знали об этом способе?
@async @transactional
" гугл мне выдал эту ссылку: forum.spring.io/forum/spring-projects/container/76021-async-transactionalЯ сам такое не городил, поэтому вопрос: Вы это пробовали? Работает? Знали об этом способе?
kefirfromperm развернул решение, на которое я мягко намекал :)
Проблема как раз в том, что вызывается метод того же класса. Таким образом, на него не накладываются аспекты. docs.spring.io/spring/docs/4.0.5.RELEASE/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies
Ваше решение плохо тем, что:
1. создание транзакции привязано к вызову метода, а не к определению метода;
2. если на методе навешаны дополнительные аспекты, то они не будут работать.
Решений здесь 3:
1. вынести метод в отдельный класс;
2. через контекст получать proxy и вызывать на нем наш метод;
3. скомпилировать всё в AspectJ.
Все они не лишены недостатков, но более универсальны, чем написание своего TaskExecutor.
Ваше решение плохо тем, что:
1. создание транзакции привязано к вызову метода, а не к определению метода;
2. если на методе навешаны дополнительные аспекты, то они не будут работать.
Решений здесь 3:
1. вынести метод в отдельный класс;
2. через контекст получать proxy и вызывать на нем наш метод;
3. скомпилировать всё в AspectJ.
Все они не лишены недостатков, но более универсальны, чем написание своего TaskExecutor.
Добрый день,
Метод вынести можно, если это приемлемо для архитектуры (есть другой бин, в которм он будет смотреться гармонично). А что, если этот метод задумывался как правит? Или ещё часто бывает, что асинхронно нужно вызвать пару строк, которые в метод оформлять совсем не хочется.
Когда-то разрабатывая EJB bean, я делал вот так:
Выглядит как hook или workaround; не стал бы рекомендовать кому-либо так делать.
Тоже вариант. Однако, сделать универсальный Аспект, субъективно, сложнее чем унивесальный TaskExecutor.
Решений здесь 3:
1. вынести метод в отдельный класс;
Метод вынести можно, если это приемлемо для архитектуры (есть другой бин, в которм он будет смотреться гармонично). А что, если этот метод задумывался как правит? Или ещё часто бывает, что асинхронно нужно вызвать пару строк, которые в метод оформлять совсем не хочется.
2. через контекст получать proxy и вызывать на нем наш метод;
Когда-то разрабатывая EJB bean, я делал вот так:
@Stateless
public class FooServiceImpl implements FooService {
@EJB
private FooService fooService;
@TransactionAttribute
public void method1() {
// some operations
fooService.method2();
}
@TransactionAttribute
@Asynchronous
public void method2() {
// some high load operations
}
}
Выглядит как hook или workaround; не стал бы рекомендовать кому-либо так делать.
3. скомпилировать всё в AspectJ.
Тоже вариант. Однако, сделать универсальный Аспект, субъективно, сложнее чем унивесальный TaskExecutor.
Здесь да, универсального решения нет.
Виталь, а что тебе в 3-м варианте не нравится, кроме того, что немного повозиться с настройками надо? У Сереги и у меня на проекте это решило проблему с прокси, пока работает и устраивает. Позволяет указать настройку в одном месте и забыть о каких-либо правилах вызова одного метода из другого.
Я считаю первый способ близким к идеальному.
Всегда можно сделать пометку в комментариях, что на самом деле метод «приватный».
Важно то, что не придется писать и поддерживать лишнюю кучу кода.
Всегда можно сделать пометку в комментариях, что на самом деле метод «приватный».
Важно то, что не придется писать и поддерживать лишнюю кучу кода.
3-й вариант вполне универсальный. По крайней мере, проблем с прокси не возникнет. Создавать какие-либо аспекты тоже не требуется. Посмотрите настройку "<tx:annotation-driven mode=«aspectj»/>"
Quadrix, mode=«aspectj» решит вопрос с вызовом транзакционного метода (@Transactional) в том же классе. Но не забываем про асинхронность, если уходить от использования TaskExecutor, то потребуется
В целом смысл всего этого — дать варинт исполнения произвольного кода(не обязательно метода того же класса) асинхронно и в рамках транзакции. Т.е. посыл такой — если Вы используете TaskExecutor, но не хватает транзакционности, то статья даёт решение.
@Async
, а для её обработки по-прежнему нужен dynamic proxy.В целом смысл всего этого — дать варинт исполнения произвольного кода(не обязательно метода того же класса) асинхронно и в рамках транзакции. Т.е. посыл такой — если Вы используете TaskExecutor, но не хватает транзакционности, то статья даёт решение.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Spring: Реализация TaskExecutor c поддержкой транзакций