2017-02-27 74 views
0

我想弄清楚CDI和適合我需求的最佳方法。 我有一個服務(TcpServiceImpl)與純TCP通信交互。現在這項服務有一些地方需要通知某人某事發生了。對於這些信息,我有Interface TcpConnection,需要將CDI注入到正確的實現中。另一個問題是服務TcpServiceImpl本身被注入一個定期執行並調用服務來執行任務的作業(TcpConnectionJob)中。 這意味着服務TcpServiceImpl將存在多次。每一個都有另外一個tcp連接,並且有另一個設備需要在Interface TcpConnection中注入另一個驅動/協議。通過CDI在運行時自動執行Injectind實現

讓我教的三個要素參與這樣的場景:

這裏是會得到多個實現的接口:

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); 
    } 
} 

服務注入callback必須被鏈接到正確的「協議」或「驅動器」,將翻譯的數據或處理邏輯的設備的實現。將有多個驅動程序實現的接口行爲不同,我需要注入正確的。該決定的限定詞可以是設備的名稱。現在,我看了看下面的鏈接:

Understanding the necessity of type Safety in CDI

How to programmatically lookup and inject a CDI managed bean where the qualifier contains the name of a class

How to use CDI qualifiers with multiple class implementations?

問:

但是,我還是不確定哪種方式/方法來使用,是什麼正確的方式。任何幫助,將不勝感激。

我的第一個想法是關於將我的界面複製到Qualifier Interface並添加這個輸入限定符的可能性。這是一個好主意嗎?

回答

0

所以這是我的解決方案,我想出了。現在唯一的問題是要回調工作,但這是不同的。繼承人爲我工作的解決方案:

/** 
* 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 
1
+0

可悲的是我不能使用CDI事件它的工作原理。我本來想這樣做,但由於預計會有大量的流量和數據通過應用程序,我的建議就被拒絕了。 據我所知,事件是同步的,所以觸發一個事件將導致程序等待所有的觀察者被完成,直到進一步的代碼被執行。但是如果我在通知其他人數據進來時需要注意更多傳入數據呢? – Nico

+0

@Nico:看看這篇有趣的文章,它解釋瞭如何製作CDI事件異步。它可以成爲您的解決方案:http://piotrnowicki.com/2013/05/asynchronous-cdi-events/ – Rouliboy

+0

感謝您的文章。真的很高興知道,我會保存它,但我想在不使用CDI事件的情況下考慮解決方案。讓我們說這是不可能的,因爲拒絕某人。我的想法是關於創建一個製片人與某個限定詞相結合的方式。這是一個有效的策略嗎? – Nico