如何在 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 方法调用并记录它们。
希望对您有所帮助。
我正在创建一个用于记录目的的 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 方法调用并记录它们。
希望对您有所帮助。