2013-06-19 120 views
2

我有一個與經紀賬戶的API交互的服務。它工作正常,但現在我需要在同一經紀商與兩個不同賬戶交互。如何創建兩個配置相同服務的實例?

看起來好像處理這個問題的最好方法是使配置服務來指定目標帳戶,然後實例化兩個不同的實例,每個帳戶一個實例。

我不確定這是在Grails中支持還是如何去解決。

兩個問題:

  1. 有沒有更好的方式來做到這一點?
  2. 如果不是,我如何實例化和配置兩個不同的服務實例?

附加信息:

兩個答案都有驚無險。讓我試着澄清:

我不想進入細節,但它可能有助於解釋我後。我使用盈透證券交易API,他們不會讓你像其他券商那樣直接與他們的服務器交談。你必須通過套接字來談談他們的IB網關,這是他們提供的一個軟件,它基本上代表了他們的服務器。因此,您的應用會與IB網關通話,IB網關代表您的應用與Interactive Brokers的服務器通話。

問題是IB網關必須作爲其配置的一部分登錄到一個帳戶。因此,爲了交易兩個不同的賬戶,您別無選擇,只能配置兩個不同的IB網關,因爲每個賬戶只能訪問配置的賬戶。

因此,我的Grails代碼進行交易必須選擇正確的IB網關進行交談。這意味着它需要知道與每個賬戶相對應的IB網關的IP地址和端口。除了IP地址和端口的這個設置外,與IB網關通信的兩個Grails服務之間沒有區別。

我想要的是重用相同的服務類,每個服務類都被實例化爲一個單例,只是有一個不同的IP地址和端口進行通信。

因此,製作兩種不同的服務是不可取的,因爲代碼在其他方面是相同的。 (如果我添加第三個或第四個IB網關,這將變得相當臭的代碼。)

而這個設置應該存在於應用程序的生命中,所以我不認爲範圍的改變真的是答案,無論是。

我真的想要兩個相同服務的實例,只是有不同的配置。

我希望能幫助解釋這種情況。你有什麼建議?謝謝!

+0

當你說服務,你的意思是Grails服務?爲什麼你覺得這是最好的方式爲每個帳戶創建服務類的新實例,而不是使用默認的'singleton'範圍? – dmahapatro

+0

是的,Grails服務。我不確定你是什麼意思。我期望每個服務是一個單身人士,運行相同的代碼,但與包含帳號的實例字段。您是否建議同一個單獨服務處理這兩個帳戶的訂單?如果是這樣,由於API的設計方式,這實際上不起作用。我需要爲每個帳戶提供專門的服務。 – greymatter

+0

關於可用服務範圍的更多詳細信息,請參閱Elias訪問[本頁](http://grails.org/doc/2.2.1/guide/services.html#scopedServices)所述的答案。 – dmahapatro

回答

2

如果相同的業務邏輯適用於這兩個帳戶,但考慮到你不能有一個單一的服務類說話的兩個帳戶的API,然後是你可以有2個服務類(這只不過是2個不同的春天bean)與默認單例作用域。

class Account1Service{ 
} 

class Account2Service{ 
} 

我也會嘗試如果我可以在這裏使用繼承在這種情況下,如果我有共同的邏輯,可以共享。但請記住,如果你是從一個抽象類,然後抽象類必須放置在src/groovy就是外面/grails-app/違抗依賴注入繼承服務類。在這種情況下,你可能最終得到(未經測試,但你能不能堅持DRY概念)

// src/groovy 
abstract class BrokerageService { 
    def populateAccountDetails(Long accountId) 
    def checkAccountStatus(Long accountId) 
} 

//grails-app/services 
class Account1Service extends BrokerageService { 
    //Implement methods + add logic particular to Account1 
    //By default transacitonal 
} 

class Account2Service extends BrokerageService { 
    //Implement methods + add logic particular to Account2 
    //By default transacitonal 
} 

也保持了一份說明,範圍singleton,你會格外小心(最好避免)保持在全球範圍的性質服務類。儘量使無國籍儘可能。除非另有情況或業務邏輯的要求使用服務水平範圍像sessionflowrequest,我會一直堅持到默認singleton範圍。

要回答你的第二個問題,你不需要任何實例使用Grails服務類的。當使用適當的命名法時,容器會注入適當的服務類(使用Spring IoC)。

//camelCase lower initial 
def account1Service 
def account2Service 

UPDATE
這是爲了應對所提供的附加信息:在上面的例子中,服務類將自動如果你在那裏你婉TTO使用的服務按照類命名約定注入OP。

參照上述場景,在默認的singleton範圍內只能有一個service類來處理事情。最好的部分是,由於您要離開您的網絡,並且不擔心自己的數據庫事務,因此服務類可以設置爲非事務性。但這又取決於情況需要。以下是服務類的外觀。

//grails-app/service 
class BrokerageService{ 

    //Service method to be called from controller or any endpoint 
    def callServiceMethod(Long accountId){ 
     ....... 
     doSomethingCommonToAllAccounts() 
     ......... 

     def _ibConfig = [:] << lookupIBGatewayConfigForAccount(accountId) 
     ........ 

     //Configure an IB Gateway according to the credentials 
     //Call IB Gateway for Account using data got from _ibConfig map 
     //Call goes here 
    } 

    def doSomethingCommonToAllAccounts(){ 
     ........ 
     ........ 
    } 

    def lookupIBGatewayConfigForAccount(accountId){ 
     def configMap = [:] 
     //Here lookup the required IP, account credentials for the provided account 
     //If required lookup from database, if you think the list of accounts would grow 
     //For example, if account is JPMorgan, get credentials related to JPMorgan 

     //put everything in map 
     configMap << [ip: "xxx.xx.xx.xxx", port: 80, userName: "Dummy"] //etc 

     return configMap 
    } 
} 

服務類的範圍是單這意味着有將只有一個堆中類,這也意味着,任何類級別屬性(比其他方法)將是有狀態的實例。在這種情況下,你只處理將是無狀態的方法,並且足以達到目的。每次交易發生時,您都可以獲得所需的東西,而無需花費堆積或創建新的BrokerageService實例。

每筆交易(包括一個賬戶)最終都會調用服務,從數據庫(或配置屬性或平面文件或屬性文件)查找憑證,然後配置IB網關並呼叫/通話給網關。

+0

請參閱添加到問題的其他信息。 – greymatter

1

Grails服務應該是singletons by default,沒有任何狀態與它正在做什麼相關聯,通常只有一個實例。也就是說,你通常不會有實例字段。

但是,如果您覆蓋默認範圍,您可以擁有它們。例如,您可以使您的服務在會話範圍內添加以下靜態變量:

static scope = "session" 

然後,您將爲每個用戶會話創建一個實例。

爲您的特定情況下,你可能想看看原型範圍,這將在每次需要注射的時間給你服務的新實例。如果您希望他們對相同的數據採取行動,您只需確保在注入後始終使用該實例。

看看the docs about Scoped Services

+0

請參閱添加到問題的其他信息。 – greymatter

相關問題