0

0

使用 CDI 限定符解决接口注入歧义问题

碧海醫心

碧海醫心

发布时间:2025-10-20 12:54:07

|

525人浏览过

|

来源于php中文网

原创

使用 cdi 限定符解决接口注入歧义问题

本文旨在解决在使用 CDI(Contexts and Dependency Injection)时,由于接口存在多个实现类而导致的注入歧义问题。通过引入 CDI 限定符,我们将学习如何明确指定需要注入的实现类,从而避免注入失败,并确保应用程序的正确运行。文章将提供详细的代码示例和步骤,帮助读者理解和应用 CDI 限定符,提升 CDI 开发技能。

在使用 CDI 进行依赖注入时,如果一个接口有多个实现类,CDI 容器将无法确定应该注入哪个实现类,从而导致注入歧义错误。 本文将介绍如何使用 CDI 限定符来解决这个问题,并提供详细的代码示例和步骤。

理解 CDI 注入歧义

在 CDI 中,Bean 是通过其类型和限定符来识别的。默认情况下,类型是从定义 Bean 的 Bean 类的传递类型闭包派生的(或者从定义 Bean 的生产者方法/字段的返回类型派生的)。

例如,如果有一个接口 Hello,它有两个实现类 HelloImpl1 和 HelloImpl2,那么 CDI 容器会识别出两个具有以下类型的 Bean:

  • {Hello, HelloImpl1}
  • {Hello, HelloImpl2}

如果没有使用任何限定符,当尝试使用 @Inject Hello hello 注入 Hello 接口时,CDI 容器会发现有两个符合条件的 Bean,因此无法确定应该注入哪个 Bean,从而导致注入歧义错误。

使用 CDI 限定符解决歧义

解决 CDI 注入歧义的正确方法是使用 CDI 限定符。限定符允许我们为 Bean 添加额外的标识信息,从而使 CDI 容器能够区分不同的 Bean。

1. 定义限定符

首先,需要定义一个自定义的限定符。限定符本身是一个注解,需要使用 @Qualifier、@Retention 和 @Target 元注解进行标记。

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
public @interface MyQualifier {
}

在上面的代码中,@MyQualifier 是我们自定义的限定符。@Retention(RUNTIME) 表示该注解在运行时保留,@Target 指定该注解可以应用于哪些元素(例如,类型、字段、方法、参数)。

2. 使用限定符标记 Bean

DALL·E 2
DALL·E 2

OpenAI基于GPT-3模型开发的AI绘图生成工具,可以根据自然语言的描述创建逼真的图像和艺术。

下载

接下来,需要使用自定义的限定符来标记需要区分的 Bean。

import jakarta.enterprise.context.Dependent;
import jakarta.inject.Named;

@Dependent // this is just an example, use any scope you need or have been using
@MyQualifier // specify qualifier of this bean
@Named("HelloImpl1")
public class HelloImpl1 implements Hello {
    // some very cool code
    @Override
    public String sayHello() {
        return "Hello from HelloImpl1";
    }
}
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Named;

@Dependent // this is just an example, use any scope you need or have been using
@Named("HelloImpl2")
public class HelloImpl2 implements Hello {
    // some very cool code
    @Override
    public String sayHello() {
        return "Hello from HelloImpl2";
    }
}

在上面的代码中,HelloImpl1 类使用 @MyQualifier 注解进行标记,表示它具有 MyQualifier 限定符。

3. 在注入点使用限定符

最后,需要在注入点使用相同的限定符来指定需要注入的 Bean。

import jakarta.inject.Inject;

public class MyClass {
    // declare the injection point with qualifier(s)
    @Inject
    @MyQualifier
    Hello helloBean;

    public void doSomething() {
        System.out.println(helloBean.sayHello());
    }
}

在上面的代码中,helloBean 字段使用 @MyQualifier 注解进行标记,表示需要注入具有 MyQualifier 限定符的 Hello 接口的实现类。

完整示例

以下是一个完整的示例,演示如何使用 CDI 限定符解决接口注入歧义问题:

// Hello.java
public interface Hello {
    String sayHello();
}

// HelloImpl1.java
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Named;

@Dependent // this is just an example, use any scope you need or have been using
@MyQualifier // specify qualifier of this bean
@Named("HelloImpl1")
public class HelloImpl1 implements Hello {
    // some very cool code
    @Override
    public String sayHello() {
        return "Hello from HelloImpl1";
    }
}

// HelloImpl2.java
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Named;

@Dependent // this is just an example, use any scope you need or have been using
@Named("HelloImpl2")
public class HelloImpl2 implements Hello {
    // some very cool code
    @Override
    public String sayHello() {
        return "Hello from HelloImpl2";
    }
}

// MyQualifier.java
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
public @interface MyQualifier {
}

// MyClass.java
import jakarta.inject.Inject;

public class MyClass {
    // declare the injection point with qualifier(s)
    @Inject
    @MyQualifier
    Hello helloBean;

    public void doSomething() {
        System.out.println(helloBean.sayHello());
    }

    public static void main(String[] args) {
        // This part depends on your CDI container (e.g., Weld, OpenWebBeans)
        // Here's a simplified example using a hypothetical CDI container:
        MyClass myClass = CDI.current().select(MyClass.class).get();
        myClass.doSomething();
    }
}

注意事项

  • 确保限定符的 @Retention 设置为 RUNTIME,以便在运行时可以使用限定符。
  • 确保在 Bean 的声明和注入点使用相同的限定符。
  • 可以使用多个限定符来进一步区分 Bean。

总结

通过使用 CDI 限定符,我们可以解决接口注入歧义问题,并明确指定需要注入的实现类。 这可以提高应用程序的可靠性和可维护性,并使 CDI 注入更加灵活和强大。 建议阅读 CDI 规范,了解更多关于类型安全解析和限定符的信息。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1074

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

169

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1239

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.19

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

137

2025.07.29

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

3

2026.01.26

edge浏览器怎样设置主页 edge浏览器自定义设置教程
edge浏览器怎样设置主页 edge浏览器自定义设置教程

在Edge浏览器中设置主页,请依次点击右上角“...”图标 > 设置 > 开始、主页和新建标签页。在“Microsoft Edge 启动时”选择“打开以下页面”,点击“添加新页面”并输入网址。若要使用主页按钮,需在“外观”设置中开启“显示主页按钮”并设定网址。

6

2026.01.26

苹果官方查询网站 苹果手机正品激活查询入口
苹果官方查询网站 苹果手机正品激活查询入口

苹果官方查询网站主要通过 checkcoverage.apple.com/cn/zh/ 进行,可用于查询序列号(SN)对应的保修状态、激活日期及技术支持服务。此外,查找丢失设备请使用 iCloud.com/find,购买信息与物流可访问 Apple (中国大陆) 订单状态页面。

15

2026.01.26

npd人格什么意思 npd人格有什么特征
npd人格什么意思 npd人格有什么特征

NPD(Narcissistic Personality Disorder)即自恋型人格障碍,是一种心理健康问题,特点是极度夸大自我重要性、需要过度赞美与关注,同时极度缺乏共情能力,背后常掩藏着低自尊和不安全感,影响人际关系、工作和生活,通常在青少年时期开始显现,需由专业人士诊断。

3

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.9万人学习

C# 教程
C# 教程

共94课时 | 7.6万人学习

Java 教程
Java 教程

共578课时 | 51.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号