CDI基础入门之Beans解析

提及JavaEE开发,绝大多数人都去选择Spring这一系列的框架,很少会直接选择EJB方面的东西(具体历史遗留方面的问题可以自己查阅),所以说JSF,CDI等系列的东西学的人也就少了,所以这里开始讲解一些关于CDI的一些用法,具体可参照官方给出的文档(最新已到2.0版本).
CDI UserGuide:
这里写链接内容

1.基本注入@Inject

字段,构造方法,方法体

2.瞬态注入@Inject Instance myInstances;

当把一个依赖bean注入到一个长期存在的bean时,后者初始化时(@Inject)这个注入完成并只执行一次。
如果我想每次访问时都再次初始化并且重新注入时必须这样写:

@Inject Instance<MyBean> myBeanInstances;
public Mybean getMyBean() { return myBeanInstances.get(); }

而在CDI组的一个开发者,说希望CDI2.0变成

//现在还不是这样
@Inject @Transient MyBean myBean;

Bean 通常是一个包含业务逻辑的应用程序类。它可直接从 Java 代码中,调用或通过统一 EL 可能会调用它。Bean 可以访问事务性资源。Bean 之间的依赖关系由容器自动管理。大多数Bean是有状态和上下文。Bean 的生命周期是由容器进行管理。

第二方面,上下文真正意味着什么.由于一些Bean是有状态的.我们会有一个Bean实例.不同于无状态的组件模型(如EJB stateless session beans.)或一个单例组件模型(如servlet或单例bean),不同的用户用到/看到不同的Bean,然而,像一个无状态或单例模式,与有状态会话bean不同,客户端不控制实例的生命周期去显式地创建和销毁它。

相反,该 bean 的范围确定:生命周期的每个 bean 的实例和哪些客户端共享对该 bean 的特定实例的引用。

对于给定的线程在 CDI 应用程序中,可能与 bean 的范围关联活动上下文。这种情况下可能是唯一的线程 (例如,如果该 bean 是request scoped),或它可能与某些其他线程共享 (例如,如果该 bean 是session scoped),甚至其他所有线程 (如果它是application scoped)。客户端(例如,其他bean)执行相同的上下文将看到相同的bean的实例。

Bean types, qualifiers and dependency injection

要注入的Bean需要满足的条件是:

  • a bean type,

  • a set of qualifiers.

public classBookShopextendsBusinessimplementsShop<Book> {
  ...
}

上面代码的类型为BookShop ,Business ,Shop以及Object.

下面EJB的类型为:Business ,Shop以及Object.

@Stateful
public class BookShopBean extends Business implements BookShop, Auditable {
  ...
}

不是BookShop 类型是因为这个EJB不是客户端可见的Bean.
但是Bean可以显示的使用CDI注解 @TYPE 来指定Bean type.如下code:

@Typed(Shop.class)
public class BookShop extends Business implements Shop<Book> {
  ...
}

那么这个Bean的类型就限定为Shop,Object

有时,一个bean类型本身并没有提供足够的信息去知道到底哪个bean注入了容器。

例如,假设我们有两个PaymentProcessor接口的实现:CreditCardPaymentProcessor,DebitPaymentProcessor。

注入一个字段类型是PaymentProcessor的Bean将是不靠谱的,它会属于一种歧义类型.

在这些情况下,客户端必须重新进行明确的指定.

这时,我们可以使用CDI限定符注解:@Qualifier.它主要用来消除歧义类型.

如下,我们定义一个Qualifier:

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

接着,我们这样使用.

@CreditCard
public classCreditCardPaymentProcessorimplementsPaymentProcessor{ 
            ...
}

我们已经定义了一个限定符注解,以及对CreditCardPaymentProcessor 进行了限定符的使用.我们可以使用它来消除歧义的注入点。如:

@Inject @CreditCard PaymentProcessor paymentProcessor

这就回到我们的开始说的,要注入的Bean需要满足的条件是:

  • a bean type,

  • a set of qualifiers.

    注:

如果一个bean或注射点不明确指定一个限定词,他会有一个默认的限定词,就是@Default.

这只是简单的一种情况,后续还有其他情况的处理.慢慢来,不急.

更多详细参加后续文章.

Scope

bean定义了生命周期的范围和实例的可见性。CDI上下文模型是可扩展的,适应任意范围。然而,某些重要的范围是内置在规范,容器进行提供(如RequestScope,SessionScope,ConversationScope,applicationScope等)。

如下面的例子.

public @SessionScoped classShoppingCartimplementsSerializable{ 
... 
}

请注意:一旦使用SessionScope,是没办法在上下文中手动删除Bean.除非上下文被销毁.
这种情况请考虑使用RequsetScope或ConversationScope.

如果未显式指定一个范围,然后该bean属于特殊的范围称为dependent pseudo-scope(依赖伪范围).如该bean被注入到SessionScope里,那该bean就是SessionScope.
更多详细参加后续文章.

EL Name

@Named 注释只是能够让页面使用EL,没有其他功能.最常见的就是JSF视图通过EL引用某个bean。

public @SessionScoped @Named("cart")classShoppingCartimplementsSerializable{ ... }

在JSF/JSP页面中如下使用:

<h:dataTablevalue="#{cart.lineItems}"var="item">
  ...
</h:dataTable>

如果@Named(“cart”)后面没有写(“cart”),那默认值就是shoppingCart.
页面为:

<h:dataTablevalue="#{shoppingCart.lineItems}"var="item">
  ...
</h:dataTable>

Alternatives

我们已经看到在开发时限定符如何让我们一个接口选择多个实现。但有时我们有一个接口(或其他bean类型)的实现会根据部署环境的变化而变化。

public @Alternative classMockPaymentProcessorextendsPaymentProcessorImpl{ ... }

因此就会用到@Alternatives,在Bean.xml里进行相关的配置指定。具体后续再讲。

Interceptors

这个就暂时不讲,等后续有专门章节进行讲述。

2. What kinds of classes are beans?
  1. ManagedBean
  2. sessionBean(EJB Session Bean)

(就是EJB相关Bean,但不是消息驱动Bean和JPA实体,这2个非上下文对象,不能被注入的其他对象,但能注入其他对象,使用CDI其他功能。)

需要使用EJB的情况如下:

  • 方法级别的事务管理和安全,

  • 并发管理

  • 有状态会话bean的实例级钝化

  • 无状态会话bean实例池

  • 远程或 web 服务调用

  • 计时器和异步方法

3.Producer methods

Producer方法通过@Produces和定义quarfiler使用。

import javax.enterprise.inject.Produces;
@ApplicationScoped
public classRandomNumberGenerator{ 

  private java.util.Random random = new java.util.Random(System.currentTimeMillis());

  @Produces @Named @Random intgetRandomNumber(){
      return random.nextInt(100);
  }  
}

在其他页面调用:

@Inject @Random int randomNumber;

在JSF页面EL表达式为:

<p>Your raffle number is #{randomNumber}.</p>

这个是简单的应用,后续会有更详细说明。

4.Producer fields

这个可以说是Producer methods的简化版。具体待以后讲解。本章就先说到这里。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值