Quarkus云原生微服务开发实战
上QQ阅读APP看书,第一时间看更新

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。

对于一个Bean类型,可能有多个不同的Bean实现该类型。最常见的例子是Java接口的Bean类型。每个接口的实现类都可以作为该Bean类型的实现。

所有的Bean都有且仅有一个作用域(Scope)。作用域决定了Bean的对象实例的生命周期。CDI规范中定义了一些常用的作用域。应用也可以创建自定义的作用域。

作用域分成普通作用域和伪作用域(Pseudo Scope)两类。绝大部分作用域是普通作用域。作用域类型以注解类型来表示。CDI规范中定义了几个内置的作用域,相应的注解类型在javax.enterprise.context包中。表3-1列出了Quarkus支持的内置作用域。

表3-1 Quarkus的内置作用域

下面代码中的UserService使用了@ApplicationScope作为作用域。一般来说,应用的服务层Bean都使用@ApplicationScope或@Singleton作为作用域。因为这些Bean并没有内部的状态,可以安全地在不同组件之间共享。只有在REST API层,才可能用到@RequestScope和@Session-Scope作用域。

除了普通作用域之外的都称为伪作用域。@Dependent是CDI规范中定义的伪作用域。对于@Dependent作用域中的Bean,每个依赖注入点的对象实例都是不同的。