如何在 Spring AOP 中将基础包作为切入点表达式内的变量传递?

How to pass base package as a variable inside pointcut expression in Spring AOP?

我正在创建一个用于记录目的的 java 库,这样如果任何应用程序使用我的库,那么 spring AOP 的建议将应用于应用程序的每个方法。但是在我的库中,我不知道将要使用它的应用程序的基础包。因此,应用程序应在 application.properties 文件中指定其基础包,我的库将使用它并将其作为变量放入我的切入点中。但似乎切入点表达式只接受其中的内容。

我不想采用基于注释的方法。

@Component
@Aspect
@Slf4j
public class LoggingAop {

    @Value("${base.package}")
    String basePackage;

    @Pointcut("within("+basePackage+"..*)") //error
    public void logAllMethods()
    {

    }
}

以下问题的答案解释了为什么基于注解的 Spring AOP 配置无法做到这一点

  • Get rid of "The value for annotation attribute must be a constant expression" message
  • How to supply value to an annotation from a Constant java

Spring boot 支持xml based configurations 可以实现需求如下

假设我们必须拦截基础包中的所有方法调用com.app.service

在 resources/application.properties.

中有一个条目
base.package=com.app.service

在基础包中记录方法调用的 Aspect 可以如下所示

package com.app.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class LogAspect {

    Logger log = LoggerFactory.getLogger(LogAspect.class);

    public Object logAllMethods(ProceedingJoinPoint pjp) throws Throwable {
        log.info("Log before method call");
        try {
            return pjp.proceed();
        }finally {
            log.info("Log after method call");
        }
    }
}

aop配置可以定义如下。

文件:resources/aop-application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="logAspect" class="com.app.aspect.LogAspect"></bean>  

<aop:config>  
  <aop:aspect id="logallaspect" ref="logAspect" >  
     <!-- @Around -->  
     <aop:pointcut id="logAllMethodsAround" expression="within(${base.package}..*)" />  
     <aop:around method="logAllMethods" pointcut-ref="logAllMethodsAround" />  
  </aop:aspect>  
</aop:config>

</beans>

请注意,切入点表达式是使用 application.properties 条目构造的。

记得加载aop-application-context.xml如下

@SpringBootApplication
@ImportResource("classpath:aop-application-context.xml")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

以上代码将通知定义的基础包中所有可拦截的 Spring bean 方法调用并记录它们。

希望对您有所帮助。