![Quarkus云原生微服务开发实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/908/41309908/b_41309908.jpg)
3.1 CDI中的Bean及其作用域
CDI中最基本的概念是Bean。Bean是创建上下文对象的模板,这些对象称为Bean的上下文对象实例。这里的上下文就是CDI名称中提到的Context,上下文是CDI规范中很重要的一个概念。CDI容器所管理的对象实例都与特定的上下文相关联。
CDI的Bean可以包含如下的属性。
· Bean类型的集合。
· 修饰符的集合。
· 作用域。
· 可选的Bean名称。
· 拦截器绑定的集合。
· Bean的实现。
· Bean是否作为替代。
在上述属性中,Bean的实现由开发人员以Java代码来编写。其他属性则以注解的形式出现在Bean类型上。如果没有显式的注解声明,Bean的属性会使用容器提供的默认值。
最常见的Bean是Java类。使用Java类的构造器可以创建出Bean的对象实例。一个Bean可以有多个类型。对于一个Java类来说,它的Bean类型包括它自身、它所有的父类以及它实现的全部接口的类型。比如下面代码中的UserServiceImpl类,它的Bean类型包括UserService-Impl、AbstractService和UserService。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/46_01.jpg?sign=1738843364-zxVag6d7fRbr1MPnBLl5QwfEdOIllFat-0-1d261816cf3016dfe380b768aaee2088)
对于一个Bean类型,可能有多个不同的Bean实现该类型。最常见的例子是Java接口的Bean类型。每个接口的实现类都可以作为该Bean类型的实现。
所有的Bean都有且仅有一个作用域(Scope)。作用域决定了Bean的对象实例的生命周期。CDI规范中定义了一些常用的作用域。应用也可以创建自定义的作用域。
作用域分成普通作用域和伪作用域(Pseudo Scope)两类。绝大部分作用域是普通作用域。作用域类型以注解类型来表示。CDI规范中定义了几个内置的作用域,相应的注解类型在javax.enterprise.context包中。表3-1列出了Quarkus支持的内置作用域。
表3-1 Quarkus的内置作用域
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/46_02.jpg?sign=1738843364-yMXv23Va3FfqBHmdubCpfeAiN135oav8-0-ac37e6efb65bb6bdf4f7b2e9260c752b)
下面代码中的UserService使用了@ApplicationScope作为作用域。一般来说,应用的服务层Bean都使用@ApplicationScope或@Singleton作为作用域。因为这些Bean并没有内部的状态,可以安全地在不同组件之间共享。只有在REST API层,才可能用到@RequestScope和@Session-Scope作用域。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/46_03.jpg?sign=1738843364-GXtdDWwmiVXuSaFzDAbYzChSTBr2yxjr-0-1a3ea95521c40a6de041e52689bff256)
除了普通作用域之外的都称为伪作用域。@Dependent是CDI规范中定义的伪作用域。对于@Dependent作用域中的Bean,每个依赖注入点的对象实例都是不同的。