- Есть ли достойные примеры включения вышеуказанного поведения, обычно выполняемого с первыми двумя вариантами с использованием AspectJ LTW?
У меня есть пара примеров AspectJ в моей учетной записи GitHub. В обоих этих примерах показано, как перехватывать вызовы внутри одного и того же целевого объекта (самовызов), а также перехватывать частные методы.
- Пример создания исходного кода Spring Boot с AspectJ
- Пример плетения Spring Boot во время загрузки с AspectJ
Оба примера похожи, за исключением того, как аспекты вплетены в целевые классы.
Пожалуйста, прочитайте README примеров, чтобы узнать больше о каждом типе плетения и о том, как использовать каждый из примеров.
- Есть ли способ выборочно включить AspectJ LTW, например не для @Async и @Transactional, а только для @Cacheable?
Да, вы можете фильтровать по одному из следующих параметров:
По типу аннотации вызывающего метода.
@Before("call(* com.basaki.service.UselessService.sayHello(..))" +
" && cflow(@annotation(trx))")
public void inspectMethod(JoinPoint jp,
JoinPoint.EnclosingStaticPart esjp, Transactional trx) {
log.info(
"Entering FilterCallerAnnotationAspect.inspectMethod() in class "
+ jp.getSignature().getDeclaringTypeName()
+ " - method: " + jp.getSignature().getName());
}
По имени вызывающего метода.
@Before("call(* com.basaki.service.UselessService.sayHello(..))" +
" && cflow(execution(* com.basaki.service.BookService.read(..)))")
public void inspectMethod(JoinPoint jp,
JoinPoint.EnclosingStaticPart esjp) {
log.info(
"Entering FilterCallerMethodAspect.inspectMethod() in class "
+ jp.getSignature().getDeclaringTypeName()
+ " - method: " + jp.getSignature().getName());
}
Вы можете найти рабочие примеры здесь.
Обновлено
Вопрос. Правильно ли я понимаю, что если бы я хотел включить переплетение во время компиляции для обеспечения транзакционности, я бы: 1. Больше не использовал TransactionAwareDataSourceProxy в моей конфигурации DataSource; 2. Добавьте в мое приложение следующее: @EnableTransactionManagement(mode=AdviceMode.ASPECTJ).
Переплетения Spring AOP и CTW/LTW AspectJ полностью ортогональны, т. е. независимы друг от друга.
- Компиляция и LTW изменяют фактический байт-код, т. е. строки кода вставляются в тело метода целевого объекта.
- АОП основан на прокси, т. е. вокруг целевого объекта существует оболочка. Любой вызов целевого объекта перехватывается объектом-оболочкой Spring. Вы также можете использовать Spring AOP с CTW/LTW, если возникнет такая необходимость. В этом случае Spring AOP сделает прокси измененной цели.
Вам понадобится @EnableTransactionManagement
, если вы хотите включить возможность управления транзакциями Spring на основе аннотаций.
В. В ваших примерах я вижу, что вы не запускаете приложение каким-то особенным образом для CTW. Этого будет достаточно, или я что-то пропустил?
Да, в CTW вам не нужно ничего особенного во время запуска, так как дополнительный байт-код уже вставлен в исходный код компилятором AspectJ (ajc
) во время компиляции. Например, вот оригинальный исходный код:
@CustomAnnotation(description = "Validates book request.")
private Book validateRequest(BookRequest request) {
log.info("Validating book request!");
Assert.notNull(request, "Book request cannot be empty!");
Assert.notNull(request.getTitle(), "Book title cannot be missing!");
Assert.notNull(request.getAuthor(), "Book author cannot be missing!");
Book entity = new Book();
entity.setTitle(request.getTitle());
entity.setAuthor(request.getAuthor());
return entity;
}
Вот тот же фрагмент кода после компиляции компилятором AspectJ, ajc
:
private Book validateRequest(BookRequest request) {
JoinPoint var3 = Factory.makeJP(ajc$tjp_0, this, this, request);
CustomAnnotationAspect var10000 = CustomAnnotationAspect.aspectOf();
Annotation var10002 = ajc$anno$0;
if (ajc$anno$0 == null) {
var10002 = ajc$anno$0 = BookService.class.getDeclaredMethod("validateRequest", BookRequest.class).getAnnotation(CustomAnnotation.class);
}
var10000.inspectMethod(var3, (CustomAnnotation)var10002);
log.info("Validating book request!");
Assert.notNull(request, "Book request cannot be empty!");
Assert.notNull(request.getTitle(), "Book title cannot be missing!");
Assert.notNull(request.getAuthor(), "Book author cannot be missing!");
Book entity = new Book();
entity.setTitle(request.getTitle());
entity.setAuthor(request.getAuthor());
return entity;
}
Находясь в LTW, вам нужен агент Java, так как код изменяется во время загрузки, т. е. когда классы загружаются загрузчиками классов Java.
person
Indra Basak
schedule
10.02.2018
@EnableAspectJAutoProxy
и настроив свои аспекты с помощью@Bean
фабричных методов, если у вас есть аспекты, которые необходимо настроить к весне. - person Nándor Előd Fekete   schedule 29.01.2018@Cacheable
,@Transactional
,@Async
, а также прокси-функций Spring AOP на AspectJ? Существуют ли какие-либо доступные примеры, демонстрирующие этот вариант использования (даже лучше, если есть рассмотрение плюсов и минусов)? - person user991710   schedule 30.01.2018@Cacheable
,@Transactional
и@Async
поддерживаются аспектами в модуле spring-aspects. - person Nándor Előd Fekete   schedule 05.02.2018