当前位置: 首页 > 知识库问答 >
问题:

在CDI上运行时自动执行Injectind

宣俊豪
2023-03-14

我试图找出CDI和适合我需要的最佳方法。我有一个与普通tcp通信交互的服务(TcpServiceImpl)。现在这个服务有一些地方需要通知某人发生了什么事情。对于这些信息,我有接口TcpConnection,需要将其CDI注入到正确的实现中。另一个问题是服务TcpServiceImpl本身被注入一个作业(TcpConnectionJob)中,该作业定期执行并调用服务来完成任务。这意味着服务TcpServiceImpl将多次存在。每个都有它处理的另一个tcp连接,并且有另一个需要在接口中注入另一个驱动程序/协议的设备TcpConnection

让我展示参与此场景的三个要素:

以下是将获得多个实现的接口:

public interface TcpConnection
{

  /**
   * Connected.
   *
   * @throws NGException the NG exception
   */
  public void connected() throws NGException;

  /**
   * This method will send the received data from the InputStream of the connection.
   *
   * @param data the received data
   * @throws NGException the  NG exception
   */
  public void received( byte[] data ) throws NGException;

  /**
   * Usable for the protocol to send data to the device.
   *
   * @param data the data to send to the device ( Will be converted to byte[] with getBytes() )
   * @throws NGException the  NG exception
   */
  public void send( String data ) throws NGException;

  /**
   * Usable for the protocol to send data to the device.
   *
   * @param data the data to send to the device ( Will be send as is )
   * @throws NGException the NG exception
   */
  public void send( byte[] data ) throws NGException;

  /**
   * This method will inform the protocol that the connection got closed.
   *
   * @throws NGException the NG exception
   */
  public void closed() throws NGException;
}

另外,下面是在我的现有服务中何时调用此函数的示例片段:

public class TCPServiceImpl implements TCPService, Runnable
{
/** The callback. */
private TcpConnection callback;
private void disconnect()
{
  connection.disconnect();
  if ( !getStatus( jndiName ).equals( ConnectionStatus.FAILURE ) )
  {
     setStatus( ConnectionStatus.CLOSED );
  }
  /* TODO: Tell driver connection is closed! */
  callback.closed();
}
}

下面是调用服务的类,然后需要为接口动态注入正确的实现。

public class TcpConnectionJob implements JobRunnable
{
  /** The service. */
  private TCPService service;

  public void execute()
  {
    service.checkConnection( connection );
  }
}

服务注入回调必须链接到将转换数据或处理设备逻辑的正确“协议”或“驱动程序”的实现。接口将有多个不同的驱动程序实现,我需要注入正确的驱动程序实现。此决定的限定符可以是设备的名称。现在我看了以下链接:

理解CDI中类型安全的必要性

如何以编程方式查找和注入CDI托管bean,其中限定符包含类的名称

如何在多个类实现中使用CDI限定符?

问题:

但我仍然不确定使用哪种方式/方法以及正确的方式是什么。任何帮助都将不胜感激。

我的第一个想法是将我的接口复制到一个限定符接口,并在这个接口的后面添加输入限定符的可能性。这是个好主意吗?

共有2个答案

法和安
2023-03-14

这就是我想出的解决方案。现在唯一的问题是得到一个工作回调,但那是不同的。以下是对我有效的解决方案:

/**
 * The Qualifier interface TcpDriver. The value of this annotation is the name the implementation
 * is found under. Please only enter values that are configured in the wildfly config as the name of
 * the device.
 */
@Documented
@Qualifier
@Retention( RUNTIME )
@Target( { TYPE, FIELD, METHOD, PARAMETER } )
public @interface TcpDriver
{

  /**
   * Value.
   *
   * @return the string
   */
  String value();
}

仅针对限定符接口的默认实现:

/**
 * The Class TcpDriverImpl.
 */
public class TcpDriverImpl extends AnnotationLiteral<TcpDriver> implements TcpDriver
{

  /** The Constant serialVersionUID. */
  private static final long serialVersionUID = 1L;

  /** The name. */
  private final String name;

  /**
   * Instantiates a new tcp driver impl.
   *
   * @param name the name
   */
  public TcpDriverImpl( final String name )
  {
    this.name = name;
  }

  /** {@inheritDoc} */
  @Override
  public String value()
  {
    return name;
  }

}

现在有一个测试实现来测试它:

@TcpDriver( "terminal1" )
@Dependent
public class TestDriverImpl implements TcpConnection
{

  /** The log. */
  private Log log;

  @Inject
  public void init( Log log )
  {
    this.log = log;
  }

  @Override
  public void connected() throws NGException
  {
    // TODO Auto-generated method stub
    log.info( "IT WORKS!!" );
  }

  @Override
  public void received( byte[] data ) throws NGException
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void send( String data ) throws NGException
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void send( byte[] data ) throws NGException
  {
    // TODO Auto-generated method stub

  }

  @Override
  public void closed() throws NGException
  {
    // TODO Auto-generated method stub
    log.info( "BYE BYE" );
  }

}

最后但并非最不重要的一点是,我将所有这些注入到我的服务中的方式:

  /** The callback Instance for the driver to find. */
  @Inject
  @Any
  private Instance<TcpConnection> callback;

  private TcpConnection driver;
  /**
  * Inject driver.
  */
  private void injectDriver()
  {
    final TcpDriver driver = new TcpDriverImpl( name );
    this.driver = callback.select( driver ).get();
  }

我希望这能帮助那些和我有同样要求的人。

PS:如果您在测试实现中检查日志输出,然后查看日志,那么可以使用一个小日志来显示它的工作原理:)

2017-02-28 08:37:00,011 INFO  starting TCPConnection: TcpDevice1 with status: NOT_CONNECTED
2017-02-28 08:37:00,018 INFO  initializing terminal1
2017-02-28 08:37:00,019 INFO  Creating socket for: terminal1 with port: XXXXX
2017-02-28 08:37:00,023 INFO  Updated Status to CONNECTED for connection TcpDevice1
2017-02-28 08:37:00,024 INFO  opened connection to terminal1
2017-02-28 08:37:00,026 INFO  (terminal1) IT WORKS!!
2017-02-28 08:37:00,038 INFO  (terminal1) terminal1: In threaded method run
2017-02-28 08:37:00,039 INFO  (terminal1) waiting for data...
2017-02-28 08:39:00,045 INFO  (terminal1) Socket closed!
2017-02-28 08:39:00,045 INFO  (terminal1) BYE BYE
祁建业
2023-03-14

使用CDI事件,不要使用回调阻塞。一些资源:

https://docs.oracle.com/javaee/7/tutorial/cdi-adv005.htm

http://www.adam-bien.com/roller/abien/entry/java_ee_6_observer_with

http://www.next-presso.com/2014/06/you-think-you-know-everything-about-cdi-events-think-again/

 类似资料:
  • 问题内容: 我正试图让nvidia-docker在我的centos7系统上运行: 到目前为止,一切都很好: 现在,让我们尝试使用nvidia运行时: 但是奇怪的是 问题答案: 所以…最后,我完全禁用了selinux并重新启动,并对其进行了修复。

  • 另一个,如果我有另一个应用程序使用相同的使用者组,所有的分区会被重新分配到该应用程序吗?

  • 我对shell脚本和ssh命令等特别陌生。我想知道我是否可以在从一台服务器上载/下载文件到另一台服务器时自动执行简单的sftp提示。 以下是我的工作: 命令:sftpusername@ServerHost 我基本上希望实现自动化,因为我将调用一个脚本,该脚本将通过源服务器上的InfoSphere Datastage序列作业将文件从源服务器上传到远程服务器。 请原谅我的无礼,如果这个问题没有意义,如

  • 我正在尝试使用Glassfish 4.0的最新升级版运行一个特别简单的测试用例。我已经尝试将META-INF/beans.xml放在所有可能的排列中,包括它自己在WEB-INF/lib中的jar 我得到的最好的结果是以下错误,后面列出了布局来源: 布局: < code>beans.xml的源: 的源代码: < code>Test.java的源代码: 的来源:

  • 本文向大家介绍在Python中自动执行PDF,包括了在Python中自动执行PDF的使用技巧和注意事项,需要的朋友参考一下 使用的模块: 在此脚本中,我们将使用PyPDF2模块,该模块将为我们提供各种功能,例如提取数据,读取pdf文件,拆分文件并写入新文件。 下载PyPDF2: 通用方式:pip安装PyPDF2 Pycharm用户:转到python项目解释器并从那里安装它。 PyPDF2提供的各种

  • 本文向大家介绍在Windows启动时自动运行Python脚本?,包括了在Windows启动时自动运行Python脚本?的使用技巧和注意事项,需要的朋友参考一下 将Python脚本添加到Windows启动时,基本上表示Python脚本将在Windows启动时运行。这可以通过两步过程来完成- 步骤#1:在Windows启动文件夹中添加或添加脚本 在启动Windows后,它会执行(相当于双击)其启动文件