Grails:在领域类中动态注入服务

5
我需要根据域属性注入一个服务,目前我想到了以下方法:
ApplicationHolder.application.getServiceClass("package.${property}Service").clazz

但是这种方式加载不会注入它所依赖的服务。我做错了吗?

3个回答

15

新的实例将会绕过Spring的依赖管理;你需要从应用程序上下文中获取已配置的单例bean。使用下面这个替代方案:

def service = ApplicationHolder.application.getMainContext().getBean("${property}Service")

假设'property' 是服务的部分bean名称,也就是说对于 FooBarService,属性必须是 'fooBar'。如果是 'FooBar',则可以使用 GrailsNameUtils.getPropertyName() 来修复它:

import grails.util.GrailsNameUtils

String beanName = GrailsNameUtils.getPropertyName(property) + 'Service'
def service = ApplicationHolder.application.getMainContext().getBean(beanName)

太好了,它起作用了。我尝试使用getBean方法,但是我把'FooBar'传递给它了 :) - rukoche
直到我将 .getMainContext. 替换为 .getMainContext().,上述代码对我来说才能正常工作。 - sebnukem
谢谢,看到你的编辑被错误地拒绝后,我已经修复了它。 - Burt Beckwith

3

我认为领域类不应该包含任何逻辑(除了验证器)。

在我的项目中,我通常为每个领域类创建一个服务(例如,对于类“User”,我创建一个名为“UserService”的服务),并将所有逻辑都放在其中,即使是小的部分也是如此,这些部分通常会在领域类中。

我认为很多来自Java/C++世界的程序员会觉得这很丑陋,但它更适合Grails的架构。


3
Grails领域类确实不太适合放置业务逻辑,但这很遗憾,因为我必须同意Fowler的观点:http://en.wikipedia.org/wiki/Anemic_Domain_Model。 - Kimble
1
当有人说“领域类根本不应该包含逻辑”时,Eric Evans可能会感到力量的干扰。这听起来像是一种领域对象反模式,完全违背了领域驱动设计的原则。 - Mark Rogers
在我的情况下,我想基于Grails环境设置索引TTL。有什么更好的模式吗? - Kirby

0

是的。服务不会被注入到域对象中。如果您的域对象需要某些东西来处理特定的用例,请让拥有该用例的服务代表域对象调用其他服务。


2
任何Spring bean都可以像在控制器中一样注入到域类中,例如“def fooService”。这种情况的常见用途是在自定义验证器中调用服务。 - Burt Beckwith
可以;我只是不同意它应该这样。验证器与像账户或个人这样的域对象不同。这是完全不同的用例。 - duffymo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接