【问题标题】:NoAspectBoundException error in class constructor of AspectJ class with Dependency Injection具有依赖注入的 AspectJ 类的类构造函数中的 NoAspectBoundException 错误
【发布时间】:2016-05-18 08:13:00
【问题描述】:

我在我的 Java 程序中有一个使用注解 @Aspect 的 AspectJ 类,我想使用 @Inject 向接口类注入一个类构造函数,但它给了我 NoAspectBoundException 错误,如下所示:

de.hpi.cloudraid.exception.InternalClientError: org.aspectj.lang.NoAspectBoundException: Exception while initializing de.hpi.cloudraid.service.MeasurementAspect: java.lang.NoSuchMethodError: de.hpi.cloudraid.service.MeasurementAspect: method <init>()V not found

这是我班的sn-p:

@Aspect
public class MeasurementAspect {

    private final RemoteStatisticService remoteStatisticService;

    @Inject
    public MeasurementAspect(RemoteStatisticService remoteStatisticService) {
        this.remoteStatisticService = remoteStatisticService;
    }
....
}

我尝试使用像 private @Inject RemoteStatisticService remoteStatisticService 这样的普通注入;但它给了我 NullPointerException 的错误。

感谢任何帮助。谢谢

【问题讨论】:

  • 你需要一个无参数的构造函数。依赖注入在方面不起作用,您需要在应用启动时手动注入。有关类似问题,请参阅我的 answer。这不是公认的答案,但我认为它比使用类型间声明的公认答案更简单,并且要求也必须管理建议的 bean,这不是我的答案中的要求。
  • @NándorElődFekete 感谢您的建议,但在本例中为 GreeterAspect.aspectOf().setGreeter(greeter);在我的情况下实现无法想到类似的解决方案,因为我正在注入接口类,我相信不可能制作接口类的 getter 和 setter。此外,我的包中不存在 aspectOf() 方法,可能是因为我使用的是注释而不是方面类的纯 AspectJ 实现? CMIIW
  • @NándorElődFekete 我实际上想过使用“第三方”类,而不是将接口注入到方面,我会将接口注入到此类中,但仍然出现 NullPointerException 错误。也许你可以帮忙调查一下here 谢谢
  • 你可以为接口做setter和getter,没关系,只是一个类型。我错过了你说它是 AspectJ 注释样式的部分,所以我会在这里提供一个快速的答案。

标签: java maven dependency-injection aspectj


【解决方案1】:

方面不是依赖注入的候选对象,因此您必须解决此限制。它们也由 aspectj 运行时而不是 CDI 实例化,您无法控制它们的实例化。

您可以做的是,创建一个由 CDI 容器处理的单独类,并将方面的依赖项注入到这个帮助程序类中。然后从这个帮助类手动设置你的方面的依赖关系。你可以把这个帮助类标记为一个启动单例,这样它就可以在启动时运行它的依赖关系。

您可以使用与此类似的启动单例辅助 bean:

@Singleton
@Startup
public class MeasurementAspectSetup {

    @Inject
    private RemoteStatisticService remoteStatisticService;

    @PostConstruct
    private void setupAspect() {
        Aspects.aspectOf(MeasurementAspect.class)
            .setRemoteStatisticService(this.remoteStatisticService);
    }

}

当然,您必须将RemoteStatisticService 的设置器添加到方面,或者更改字段在方面中的可见性并直接设置它。您还需要从方面中删除参数构造函数,以便可以使用默认的无参数构造函数。

【讨论】:

  • 在这种情况下,我应该将接口 RemoteStatisticService 注入或启动到 MeasurementAspect 类中吗?
  • 我已经尝试了将接口 RemoteStatisticService 注入 MeasurementAspect 的代码,但仍然出现 NullPointerException 错误。 Here 是MeasurementAspect 类的代码(仅摘录,因为它太长了)
  • 创建一个类似于我的答案中的单例启动 bean。在setupAspect() 方法中放置一个调试断点并检查应用程序启动时发生的情况。它应该停止在该方法中,您应该使用该方法来设置您的方面依赖项。方法完成后,您的方面应该可以运行了。您可以在方面使用布尔标志来指示设置已完成,并在运行时检查其值,以便您的方面在设置完成之前不会尝试运行。
  • @NándorElődFekete我实际上已经尝试创建一个单独的类,我可以用它来注入接口,Aspect 类只需要实例化这个类,你可以看到我的另一个问题here 但问题是依赖注入仍然为 NullPointerException
  • 此答案不会尝试解决您的简单 CDI 问题。它只是试图解决在 CDI 环境中设置方面依赖关系的问题。为了让它工作,它需要一个有效的 CDI 设置。如果remoteStatisticService 字段没有被注入到MeasurementAspectSetup 辅助类中,则意味着您需要先解决该问题。您可能缺少RemoteStatisticService 接口的实现。
【解决方案2】:

@Nándor Előd Fekete 上面的回答让我找到了一个类似的解决方案,使用更现代的注释和构造函数注入:

@Component
public class MeasurementAspectSetup {

    private RemoteStatisticService remoteStatisticService;

    MeasurementAspectSetup(RemoteStatisticService remoteStatisticService) {
        this.remoteStatisticService = remoteStatisticService;
    }

    @PostConstruct
    private void setupAspect() {
        Aspects.aspectOf(MeasurementAspect.class)
            .setRemoteStatisticService(this.remoteStatisticService);
    }

}

我希望几年后解决方案的更新对其他人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多