Java Spring AOP: использование CustomizableTraceInterceptor с JavaConfig @EnableAspectJAutoProxy, а не XML <aop: advisor> - программирование

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" ...>?

4b9b3361

Ответ 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());
    }
}