Spring 使用方面时未调用 Boot RestController 的构造函数

Constructor of Spring Boot RestController not invoked when using aspect

我是 AOP 的新手,目前正在尝试为使用自定义注释注释的控制器方法实现一个方面。 当调用 myFunction 时,我总是在 repository 上得到 NullPointerException。看来我有两个控制器实例。其中之一是在没有自动装配存储库的情况下实例化的。当我删除@MyAnnotation 时,一切都按预期工作。

你能给我一些关于如何强制 Spring/AspectJ 使用我的构造函数的提示吗?

我的控制器看起来像:

@RestController
@RequestMapping(value = "/api")
public class MyController {
    private Repository repository;

    public MyController(Repository repository) {
        this.repository = repository;
    }

    @RequestMapping(value = "/{variable1}", method = GET)
    @MyAnnotation
    public final FeatureCollection myFunction(
        final @PathVariable(required = true) long variable1
    ) {
        repository.findById(variable1);
        (...)
    }
}

看点:

@Aspect
public class MyAspect {
    @Around("@annotation(MyAnnotation)")
    public Object any(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }
}

配置:

@Configuration
@EnableAspectJAutoProxy
public class WebConfig {
    @Bean
    public MyAspect myAspect() {
        return new MyAspect();
    }
}

尝试使用@Autowired 注释构造函数

@Autowired
public MyController(Repository repository) {
    this.repository = repository;
}

是因为注解的方法是final.

如果您可以删除 final 关键字,它将起作用。

如果您 google 类似于“spring aop final 方法”,您会找到更多信息,但基本上,当 Spring 创建代理时,它会生成一个子class 从你原来的 class,用你的方面包装对 super 的调用。问题是 final 方法不能被 subclass 继承,所以代理很难工作。因此,很多限制来自于此,AOP 对 final 的东西不太适用。

文档中提到了此限制,我认为您不会找到解决方法:

11.6 Proxying mechanisms

...

final methods cannot be advised, as they cannot be overridden.

希望对您有所帮助!