如何在Grails服务中将接口与实现分开?

时间:2011-02-02 10:01:37

标签: grails interface groovy service

我想知道是否有可能在Grails上创建一个服务接口,而我找不到合适的方法。 这种解释并不令人满意,因为它似乎混合了Java和Groovy:

http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html

在我看来,框架的设计缺陷很糟糕,因为接口机制是Java(以及大多数OO语言)的最佳功能之一。

有任何想法澄清这个问题吗?

谢谢! Mulone

4 个答案:

答案 0 :(得分:18)

您可以拥有一个界面,但实际上您不需要一个界面。如果我理解正确,您希望有两个服务实现,并能够选择使用哪个。

只需实现两个名为MyService1MyService2的服务,然后在grails-app/conf/spring/resource.groovy中指定:

beans = {
    ... 
    // syntax is beanId(implementingClassName) { properties }
    myService(MyService1)
    ...
}

甚至:

beans = {
    ...
    if (someConfigurationOption) {
        myService(MyService1)
    } else {
        myService(MyService2)
    }
}

这就是你如何告诉Spring为myService实际注入哪些服务。现在,您可以使用myService之类的:

public MyController {
    def myService
    ...
}

并且Spring将自动连接正确的实现。这允许您根据某些配置配置要使用的服务实现。

答案 1 :(得分:5)

  • 在存储com.mycompany.mypackage.MyInterface.groovy
  • 的班级under src/groovy中定义服务界面
  • 定义存储在grails-app/services

    下的服务实现
    class MyService implements MyInterface {
        // service implementation goes here
    }
    

答案 2 :(得分:1)

它不是一个设计缺陷。 Groovy与java不同,因为它是一种使用'duck-typing'的动态语言。在groovy中有趣的是,还有接口。因此,如果您遵循@ don的建议,您可以确保您的服务符合界面,但您使用grails进行DI的方式是仅指定服务实现。即你没有得到编译时检查 where 你使用服务实现,就像在java中一样。

请注意,这里没有紧耦合。耦合意味着某种东西与某种类型有关。但是使用groovy的松散打字系统,类型本质上是动态生物。因此在java中,如果将类型声明为特定实现,则稍后更改类型时代码可能无法编译。在groovy中,如果使用'def',代码将始终编译...(我认为这是正确的)

答案 3 :(得分:0)

我发现的最佳解决方案是使用 Spring bean别名。基本上你需要:

1)在src / groovy(MyService.groovy

中创建一个接口

2)在您需要的任何地方注入您的服务:

class MyController {
    MyService myService
}

3)创建实施该界面的常规服务(ImplOneService.groovyImplTwoService.groovy

4)在resources.groovy中添加一个条目,您可以在其中定义要使用的实现(最终,测试环境或您需要的任何其他内容):

beans = {
    if (...development, useFTP, etc...) {
        springConfig.addAlias 'myService', 'ImplOneService'
    } else {
        springConfig.addAlias 'myService', 'ImplTwoService'
    }
}

Complete sources here

我的评论:在groovy中使用界面真的好像是某种"我想坚持使用一些我更熟悉的东西"。在这种情况下,强类型。但它确实是常规说法中的一个很好的部分"不用担心,如果你愿意,可以保持java方式"。