当前位置: 首页 > 知识库问答 >
问题:

如何以编程方式查找和注入限定符包含类名的CDI托管bean

朱宇航
2023-03-14

我试图以编程方式查找并注入一个CDI托管bean,其中限定符包含一个类的名称(不是我想要注入的类),但是我遇到的问题是,我用来查找正确bean的代码总是返回null

我要注入的bean使用名为@CQRSCommandHandler的自定义注释进行注释,该注释包含用作限定符的类的名称,bean还实现了名为CommandHandler的接口。我使用的类实现了接口命令

基于我对CDI的有限了解,我认为为了以编程方式查找使用@CQRSCommandHandler注释限定的正确bean,我需要扩展AnnotationLiteral,然后我可以使用实例来选择bean。

@CQRSCommandHandler注释的代码如下:

@Qualifier
@Documented
@Retention(value= RetentionPolicy.RUNTIME)
public @interface CQRSCommandHandler {
    Class<? extends Command> command();
}

扩展AnnotationLiteral的代码如下:

public class CQRSCommandHandlerQualifier extends AnnotationLiteral<CQRSCommandHandler> implements CQRSCommandHandler {

    private static final long serialVersionUID = 1L;
    private final Class<? extends Command> command;

    public CQRSCommandHandlerQualifier(Class<? extends Command> command) {
        this.command = command;
    }

    @Override
    public Class<? extends Command> command() {
        return command;
    }

}

我使用CDI查找正确bean的代码如下:

@Inject
@Any
private Instance<CommandHandler> commandHandlerInstance;

private CommandHandler findCommandHandlerFor(Command command) {

    CommandHandler commandHandler = commandHandlerInstance.select(new CQRSCommandHandlerQualifier(command.getClass())).get();  //This always returns null
    return commandHandler;
}

尽管谷歌搜索了好几个小时,我还是不明白为什么commandHandlerInstance。选择(新的CQRSCommandHandlerQualifier(command.getClass()))。get()不返回用@CQRSCommandHandler(command=MyCommand.class)注释的bean实例,其中bean实现CommandHandler接口和MyCommand。类实现html" target="_blank">接口命令

这是以编程方式查找和注入CDI托管bean的正确方法吗?如果是这样,上面的代码哪里出错了?如果没有,实现相同最终结果的最佳方式是什么?

使现代化

下面的代码是我试图查找的bean的示例实现:

@CQRSCommandHandler(command = CreateToDoItemCommand.class)
public class CreateToDoItemCommandHandler implements CommandHandler {

    @Override
    public <R> Object handle(Command command) {
        System.out.println("This is the CreateToDoItemCommandHandler");
        return null;
    }
}

以下代码是CommandHandler的接口:

public interface CommandHandler {

    public <R> Object handle(Command command);

}

以下代码是我在限定符中用作参数的类的示例:

public class CreateToDoItemCommand implements Command {

    private String todoId;
    private String description;

    public CreateToDoItemCommand(String todoId, String description) {
        this.todoId = todoId;
        this.description = description;
    }

    public String getTodoId() {
        return todoId;
    }

    public String getDescription() {
        return description;
    }

}

我在Eclipse中浏览了代码,似乎commandHandlerInstanceInstance对象是null

更新2

根据@redge的建议,我已将实例化的每个步骤分别放在一行中,如下所示:

private CommandHandler findCommandHandlerFor(Command command) {
    CQRSCommandHandlerQualifier qualifier = new CQRSCommandHandlerQualifier(command.getClass());
    Instance<CommandHandler> instance = commandHandlerInstance.select(qualifier);
    CommandHandler commandHandler = instance.get();
    return commandHandler;
}

问题似乎在于这行代码实例

我运行此代码在GlashFish4与焊接2.0.0 SP1附带,但我也刚刚尝试运行相同的代码在GlashFish4.1和已安装焊接版本2.2.10。SP1是Maven Central的最新版本,但也会出现相同的问题。


共有1个答案

宗项禹
2023-03-14

你有玻璃鱼4.1。我怀疑你有一个beans.xml文件,如果你有,应该根据你当前的设置标记为Bean-Disportation-Mode="all"。如果您不这样做,或者您使用bean-发现-模式="注释",那么您需要为每个命令添加bean定义注释,例如为每个命令添加@Application ationScoped,以便能够解析它们。

 类似资料:
  • 如何以编程方式将Java CDI 1.1托管bean注入静态方法中的局部变量?

  • 问题内容: 如何以静态方法以编程方式将Java CDI 1.1+托管bean注入局部变量? 问题答案: 要注入class的实例: 在CDI 1.1+中可用

  • 我有一个用@Example注释的bean。这个bean实现了一些接口。我想通过使用它的类名以编程方式注入这个bean,但我不想指定它的限定符 我得到了一个不满意的依赖项错误,因为它正在搜索带有@Any的bean,而这个bean有@Any和@Example,由于某种原因,它不满足 这可以在CDI中实现吗?

  • 我在我的应用程序中使用EJB3.1。 我想在我的应用程序中将一个EJB的JNDI查找名称发送到另一个应用程序,以便它可以在运行时使用它 用程序找出任意EJB的查找名的过程是什么?

  • 在控制器中引用FactoryBean,然后。但是,对于这样一个简单的情况,我真的需要创建一个新类吗? 有一个工厂方法来构造托管bean。这个方法仍然存在显式实例化POJO的问题,因此它本身需要对它进行Spring注入。此外,这是完整的样板文件。 bean的构造非常琐碎,所以我认为Spring中有一种更简单的方法来完成它。有吗?

  • 我想从方法中检索注释(自定义编写的注释)。通常我可以通过访问 但是如果bean由CDI容器管理(我使用的是OpenWebBeans),那么类在运行时会得到增强。然后我必须使用超类来请求注释。目前,我试图通过在类名中查找“$$”来检测是否管理该类。但对我来说,这似乎是一个非常肮脏的解决方案。 有什么好方法可以从CDI管理的bean中检索注释吗? 详细地说,我的代码是这样的:我创建了一个注释“Cool