Spring:在运行时以编程方式注册建议

标签 spring aspectj spring-aop

是否可以通过编程方式注册 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/

相关文章:

java - Spring-AngularJS-文件上传-org.apache.commons.fileupload.FileUploadException : the request was rejected because no multipart boundary was found

java - Spring 存储库和 DATA_FORMAT 与 nativeQuery=false

java - AspectJ 无法解析对 bean 'selectAll' 的引用

java - 将切面转换为原生 AspectJ 表示法

spring - 使用 Tomcat、Spring 和 Weaver (BcelClassWeaver) 启动期间出现异常

java - Spring任务执行器和调度器

java - .class 文件中缺少 @Autowired 注释

Java AOP在构造对象时设置字段值

spring - 如何将切面限制为用名称指定的 bean?

java - 如何在 spring AOP 类中使用 HystrixCommand