Java Spring AOP: использование CustomizableTraceInterceptor с JavaConfig @EnableAspectJAutoProxy, а не XML <aop: advisor>
Spring AOP имеет трассировщик уровня метода, называемый CustomizableTraceInterceptor
. Используя Spring подход к настройке XML, можно было бы настроить этот трассировщик следующим образом:
<bean id="customizableTraceInterceptor" class="
org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="enterMessage" value="Entering $[methodName]($[arguments])"/>
<property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/>
</bean>
<aop:config>
<aop:advisor advice-ref="customizableTraceInterceptor"
pointcut="execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))"/>
</aop:config>
Я хотел бы настроить конфигурацию с использованием стиля Spring JavaConfig (т.е. использовать аннотации Java, особенно @EnableAspectJAutoProxy
для активации AspectJ в JavaConfig).
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = { "some.package" })
@ComponentScan(basePackages = { "some.package2", "some.package3" })
@EnableAspectJAutoProxy
public class FacebookDomainConfiguration {
@Bean someBean() {
...
}
...
}
Что такое @EnableAspectJAutoProxy
-стильный эквивалент для <aop:advisor advice-ref="customizableTraceInterceptor" ...>
?
Ответы
Ответ 1
К сожалению, вы не можете, потому что язык Java не поддерживает литералы метода, которые необходимы для поддержки этого в Spring JavaConfig. Ошибка была открыта для этого, но отмечена как "Не исправить": https://jira.springsource.org/browse/SPR-8148.
Два параметра, упомянутые в отчете об ошибке:
- Продолжайте использовать
<aop:config>
, включив соответствующий фрагмент XML, используя @ImportResource
- Преобразуйте существующие элементы
<aop:config>
, чтобы использовать стиль @Aspect
. [это невозможно с помощью CustomizableTraceInterceptor
]
Ответ 2
Я делаю так:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class TraceLoggerConfig {
@Bean
public CustomizableTraceInterceptor customizableTraceInterceptor() {
CustomizableTraceInterceptor customizableTraceInterceptor = new CustomizableTraceInterceptor();
customizableTraceInterceptor.setUseDynamicLogger(true);
customizableTraceInterceptor.setEnterMessage("Entering $[methodName]($[arguments])");
customizableTraceInterceptor.setExitMessage("Leaving $[methodName](), returned $[returnValue]");
return customizableTraceInterceptor;
}
@Bean
public Advisor jpaRepositoryAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))");
return new DefaultPointcutAdvisor(pointcut, customizableTraceInterceptor());
}
}
Ответ 3
Просто хотел добавить ответ AdrienC.
Я буду использовать точечное выражение для ссылки на агрегированную точку, более четкое разделение, imho
package org.example;
@Configuration
@EnableAspectJAutoProxy
@Aspect
public class AopConfiguration {
/** Pointcut for execution of methods on {@link Service} annotation */
@Pointcut("execution(public * (@org.springframework.stereotype.Service org.example..*).*(..))")
public void serviceAnnotation() { }
/** Pointcut for execution of methods on {@link Repository} annotation */
@Pointcut("execution(public * (@org.springframework.stereotype.Repository org.example..*).*(..))")
public void repositoryAnnotation() {}
/** Pointcut for execution of methods on {@link JpaRepository} interfaces */
@Pointcut("execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))")
public void jpaRepository() {}
@Pointcut("serviceAnnotation() || repositoryAnnotation() || jpaRepository()")
public void performanceMonitor() {}
@Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
return new PerformanceMonitorInterceptor(true);
}
@Bean
public Advisor performanceMonitorAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("org.example.AopConfiguration.performanceMonitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());
}
}