2013-06-19 70 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

相关问题