繁体   English   中英

如何在AspectJ编译器中使用Spring @Component批注

[英]How to use Spring @Component annotation with AspectJ compiler

为了简化重现问题,我排除了项目的一部分: GitHub repo 当我用Javac编译它时,一切都会按预期进行。 当我打开URL /user//user/2/时,我看到在控制台中登录:

Access: execution(List ru.krivochenko.demo.user.UserController.getAll()) Access: execution(User ru.krivochenko.demo.user.UserController.getOne(Integer))

但是我想使用AspectJ编译器。 当我切换到它时,会发生错误:

java.lang.NoSuchMethodError: ru.krivochenko.demo.logging.LoggingAspect: method <init>()V not found

据我了解,这是因为LoggingAspect没有no-args构造LoggingAspect 如果添加它,则会收到另一个错误,因为未注入logger

java.lang.NullPointerException: null at ru.krivochenko.demo.logging.LoggingAspect.beforeGettingUsers(LoggingAspect.java:28) ~[classes/:na]

因此,我们可以看到,AspectJ忽略了带有args的Autowired构造函数。

在我的仓库的分支via-setter ,我实现了另一个解决方案。 我删除了LoggingAspect @Component批注,并将构造函数注入替换为setter注入。 DemoApplication.java我加@Bean的配置LoggingAspect 它工作正常,但在某些情况下,它需要从应用程序上下文获取依赖项。 解决该问题的最佳做法是什么?

感谢帮助。

您通过setter注入配置方面的方法对我来说是有效的。 有关如何将AspectJ与Spring结合使用的更多信息,请查阅Spring手册中的相应章节 ,特别是有关如何通过Spring IoC配置AspectJ方面的描述。 它主要是在LTW的背景下进行解释的,但它对于CTW应该几乎相同。

Spring Aspects和编译时编织不会自动集成。 这是主要的,因为Aspectj和Spring是相当分开的,我怀疑Spring推荐的方法是不使用编译时编织。

因此,默认情况下,Aspects不是弹簧魔术,我们需要添加一些管道以确保它们是正确的。

在这方面,需要注意的是,方面不是春季管理的(方面是由Aspectj管理的,因此我们需要添加一些内容以确保对其进行管理)。

因此,您的方面需要无参数构造函数的原因(因此必须使用字段注入)。

传统上,我必须将以下xml添加到我的xml配置文件中:

<bean id="securityAspect" class="com.<skip>.security.AuthorizationAspect"
        factory-method="aspectOf" autowire="byType" />

之所以如此有效是因为AspectJ编译器将静态方法AspectOf添加到各方面,并且此方法可用于获取Aspectj创建(和使用)的Aspect实例。

此方法显然在源代码中不可用,因此我们不能仅将其添加到应用程序类(DemoApplication)中:

@Bean
public LoggingAspect loggingAspect() {
    return LoggingAspect.aspectOf();
}

那该怎么办? 我的下一个选择是编写一些反射代码来调用此方法,然后查看了这个非常有帮助的示例 ,该示例恰好演示了您的需求-AspectJ的Aspects类具有实用的方法,可以为我们完成此工作,因此在我们的代码中添加以下内容DemoApplication我们取得了成功:

@Bean
public LoggingAspect loggingAspect() {
    return Aspects.aspectOf(LoggingAspect.class);
}

顺便说一句,从LoggingAspect中删除@Component,因为这将意味着Aspectj和Spring都将创建该类的实例...

顺便说一句,我还建议您在测试类中添加以下内容,以在测试中演示问题:

@Autowired
private UserController controller;

@Test
public void contextLoads() {
    controller.getAll();
    controller.getOne(1);
}

顺便说一句,其他解决此问题的建议使用@Configurable。 我怀疑这可能有效,但您需要确保在AspectJ编译时配置中包含spring方面java,并且我不确定它可能仍无法正常工作,因为我不确定Spring上下文是否会及时准备就绪。 即,如果Aspect是在spring上下文之前创建的,则@Configurable将不起作用,因为尚未创建要注入的bean。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM