我想知道是否有可能在Grails上创建一个服务接口,而我找不到合适的方法。 这种解释并不令人满意,因为它似乎混合了Java和Groovy:
http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html
在我看来,框架的设计缺陷很糟糕,因为接口机制是Java(以及大多数OO语言)的最佳功能之一。
有任何想法澄清这个问题吗?
谢谢! Mulone
答案 0 :(得分:18)
您可以拥有一个界面,但实际上您不需要一个界面。如果我理解正确,您希望有两个服务实现,并能够选择使用哪个。
只需实现两个名为MyService1
和MyService2
的服务,然后在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.groovy
,ImplTwoService.groovy
)
4)在resources.groovy中添加一个条目,您可以在其中定义要使用的实现(最终,测试环境或您需要的任何其他内容):
beans = {
if (...development, useFTP, etc...) {
springConfig.addAlias 'myService', 'ImplOneService'
} else {
springConfig.addAlias 'myService', 'ImplTwoService'
}
}
我的评论:在groovy中使用界面真的好像是某种"我想坚持使用一些我更熟悉的东西"。在这种情况下,强类型。但它确实是常规说法中的一个很好的部分"不用担心,如果你愿意,可以保持java方式"。