程序员我爱编程Java

Java CDI 相关整理

2018-05-28  本文已影响38人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

1. 简介

<dependency>
   <groupId>javax.enterprise</groupId>
   <artifactId>cdi-api</artifactId>
   <version>2.0</version>
   <scope>provided</scope>
</dependency>

2. @Inject 注解

2.1 构造器依赖注入

public class SomeBean {
  
  private final Service service;

  @Inject
  public SomeBean(Service service){
    this.service = service;
  }

}

2.2 字段依赖注入

public class SomeBean {
  
  @Inject
  private Service service;

}

2.3 初始化方法依赖注入

public class SomeBean {
  
  private Service service;
  
  @Inject
  public void setService(Service service) {
    this.service = service;
  }

}

3. @Any 修饰符

public class SomeBean {
  
  @Inject
  public void listServiceImplementations(
      @Any Instance<Service> serviceList) {

    for(Service service : serviceList){
      System.out.println(service.getClass().getCanonicalName());
    }

  }
}

4. 注入到生产者方法中

4.1 用例说明

4.1.1 服务

public interface MessageSender {

  void sendMessage();
  
}

public class EmailMessageSender implements MessageSender {

  @Override
  public void sendMessage() {
    System.out.println("Sending email message");
  }

}
public class SmsMessageSender implements MessageSender {

  @Override
  public void sendMessage() {
    System.out.println("Sending SMS message");
  }

}

4.1.2 生成者

@SessionScoped
public class MessageSenderFactory implements Serializable {

  private static final long serialVersionUID = 5269302440619391616L;

  @Produces
  public MessageSender getMessageSender(){
    return new EmailMessageSender();
  }
  
}
@Inject
private MessageSender messageSender;

4.1.3 多 Bean 的实现(多态)

package com.byteslounge.bean;

public enum MessageTransportType {
  EMAIL, SMS;
}
@SessionScoped
public class MessageSenderFactory implements Serializable {

  private static final long serialVersionUID = 5269302440619391616L;

  private MessageTransportType messageTransportType;

  @Produces
  public MessageSender getMessageSender() {

    switch (messageTransportType) {
    
      case EMAIL:
        return new EmailMessageSender();
  
      case SMS:
      default:
        return new SmsMessageSender();

    }
  }
}

4.1.4 通过 @Qualifier 实现多态

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

  MessageTransportType value();
    
}
@SessionScoped
public class MessageSenderFactory implements Serializable {

  private static final long serialVersionUID = 5269302440619391616L;

  @Produces
  @MessageTransport(MessageTransportType.EMAIL)
  public MessageSender getEmailMessageSender(){
    return new EmailMessageSender();
  }
  
  @Produces
  @MessageTransport(MessageTransportType.SMS)
  public MessageSender getSmsMessageSender(){
    return new SmsMessageSender();
  }
  
}
@Inject
@MessageTransport(MessageTransportType.EMAIL)
private MessageSender messageSender;
@Inject
@MessageTransport(MessageTransportType.SMS)
private MessageSender messageSender;

4.1.5 生产 CDI 管理 Bean

@Produces
public MessageSender getEmailMessageSender(EmailMessageSender emailMessageSender){
     return emailMessageSender;
}

4.1.6 生产方法的作用域

@Produces
@SessionScoped
public MessageSender getEmailMessageSender(
  EmailMessageSender emailMessageSender){
  
  return emailMessageSender;
}
@Produces
@SessionScoped
public SomeService getService(SomeService someService){
  return someService;
}
@Produces
@SessionScoped
public SomeService getService(@New SomeService someService){
  return someService;
}

5. Bean 的作用域

作用域 描述
ApplicationScoped 当 Bean 被定义为 Application 作用域时,意味着 Bean 中只有一个实例将存在于整个应用程序中。在 Bean 初始化后,每当客户端请求这个 Bean 的实例时,容器总是提供相同的 Bean 实例。
SessionScoped SessionScoped 主要用于 Web 环境下应用的开发。当我们使用一个作用域为 Session 的 CDI Bean 时,表示 Bean 实例的生命周期取决于每个 HTTP 会话。
RequestScoped RequestScoped 主要用于 Web 环境下应用的开发。当我们使用一个作用域为 Request 的 CDI Bean时,表示 Bean 实例的生命周期取决于每个 HTTP 请求。
ConversationScoped ConversationScoped 主要用于 Web 环境下应用的开发。如同其名一样,ConversationScoped 标志客户端同服务端的一次交流 。他们可能被用于保持多个 Ajax 请求或者不同页面请求与服务端交互的状态信息。
作用域 描述
TransactionScoped Transaction 作用域的 Bean 将通过活动事务的持续时间生成其生命周期。一旦这种类型的 Bean 在事务中被第一次引用,CDI 容器将创建 Bean 的实例并在整个事务生命周期中重用它。如果 Bean 在相同事务中稍后再次引用,容器将提供相同的实例给调用者。
FlowScoped 在 JSF 流中使用 Flow 作用域 Bean。流程用于表示工作单元,并由包含的视图集和 Bean 定义。一个流式作用域 Bean 将在其第一次引用的流的持续时间中产生它的生命周期。
ViewScoped View 作用域 Bean 将在 JSF 视图的持续时间中产生它的生命周期。由于这种 Bean 在整个视图生命周期中保持它们的状态,因此它们以对话的方式在客户端和服务器之间建立 Ajax 交互变得很有作用。
伪作用域 描述
Singleton 如同其名一样,Singleton Bean 标志着单实例,如果一个 Bean 被用作 Singleton 意味着从始至终仅仅有一个实例存在。
Dependent Dependent scope Bean 的作用域与其被注入的 Bean 的作用域一样。如当一个定义为Dependent 的 Bean 被注入到一个会话 Bean 中,那么这个 Bean 的作用域和生命周期同这个会话Bean 一样,当会话结束此 Bean 的生命周期也就截止了。

5.1 代理

5.2 可序列化的作用域

5.3 Singleton pseudo-scope

5.4 Dependent pseudo-scope

6. Bean 销毁

6.1 用例说明

public interface Connection {
  void connect();
  void closeConnection();
}
public class ConnectionImpl implements Connection {

  @Override
  public void connect() {
    System.out.println("Connecting...");
  }

  @Override
  public void closeConnection() {
    System.out.println("Closing connection...");
  }

}
public class ConnectionFactory {

  @Produces
  @RequestScoped
  @TestConnection
  public Connection getConnection(){
    Connection conn = new ConnectionImpl();
    conn.connect();
    return conn;
  }
  
  public void closeConnection(
    @Disposes
    @TestConnection Connection connection){
    connection.closeConnection();
  }
  
}
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, PARAMETER})
public @interface TestConnection {
}
@Inject
@TestConnection
private Connection connection;

参考资料

Java EE CDI Producer methods tutorial

上一篇 下一篇

猜你喜欢

热点阅读