是否可以通过编程方式注册 AOP 建议,之后 应用程序已启动并且上下文已初始化?
当我尝试时,这些建议不起作用,据说是因为他们需要在 bean 在上下文中可用之前对其进行包装。
像这样的东西(它不起作用):
@Bean
private AspectJExpressionPointcutAdvisor createPointcutAdvisor(AWSXRayRecorder awsxRayRecorder, String name, String pointcut) {
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setExpression("execution ...()");
advisor.setAdvice(new CustomAdvice("custom bean"));
return advisor;
}
澄清:我需要从配置文件中读取建议列表,并相应地注册切入点。我需要标签用于记账目的。文件内容在编译时是未知的。
label: execution(* com.my.ns.OtherClass(..))
label2: execution(* com.my.ns.Class(..))
最佳答案
以前的解决方案过于侵入性,因为它不仅可以即时创建建议,还可以处理建议 bean。这复制了 Spring 的 AbstractAdvisorAutoProxyCreator 的功能,特别是 getAdvicesAndAdvisorsForBean 方法,Spring 将在其中找到合格的顾问并将其应用于每个 bean。更好的方法是简单地以编程方式创建顾问,让 Spring 处理通知 bean、创建代理等的其余管道。
创建 Advisor 的一种简单方法是使用 @Bean 注解创建 Advisor bean:
@Bean
public Advisor advisorBean() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* com.testit.MyAspectedService.*(..))");
return new DefaultPointcutAdvisor(pointcut, new MyMethodInterceptor());
}
MyMethodInterceptor 类实现 MethodInterceptor 接口(interface)的地方:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("in interceptor");
//get the method and arguments we are intercepting
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments();
//... do stuff before the method
//call the underlying method
return invocation.proceed();
}
}
这样做是为了创建一个 周边咨询顾问 bean 命名为“advisorBean”,用于对声明为 Spring bean MyAspectedService 的所有方法调用
@Service
public class MyAspectedService {
//various service methods
}
这种方法只专注于创建必要的顾问和拦截实现,并将方面的编织委托(delegate)给 Spring 框架。
关于Spring:在运行时以编程方式注册建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49072611/