如何向Grails域对象注入类似服务的组件?

时间:2014-09-22 05:43:39

标签: grails dependency-injection grails-domain-class

我之前从未使用过Grails服务,但根据我的网络搜索,可以将它们注入到域对象中。所以,如果我有以下域类(假设在某处定义了BookService),

class Book {

    BookService bookService

}

当我使用Book实例化def book = new Book()对象时,应该设置book.bookService

如果是这种情况,如果我想注入外部服务(或类似服务的组件)该怎么办?例如,如果有可用的ISBN API客户端,我可以期望grails以相同的方式注入它吗?例如,假设客户端是IsbnApi,我如何自动注入它的另一个服务?下面的代码会起作用吗?

class Book {

    @Transient
    @Autowire
    IsbnApi isbnApi

}

根据之前对此问题的回答,我已经用这种方式定义了域类:

class Book {

    static transients = ['isbnApi']

    IsbnApi isbnApi

}

现在,这可能就是我所需要的,但我也想测试自动注入即使也可以运行而无需运行应用程序。在我的单元测试中,我必须手动设置模拟“服务”。

IsbnApi isbnApi = Mock()
Book book = new Book()
book.isbnApi = mockIsbnApi

我尝试通过将测试移至test/integration来检查自动注入,并使用doWithSpring设置bean。

def doWithSpring() {
    isbnApi = (InstanceFactoryBean, mockIsbnApi, isbnApi)
}

void "test automatic injection"() {
    given:
    IsbnApi isbnApi = Mock()
    Book book = new Book()
    //removed: book.isbnApi = mockIsbnApi

    expect:
    book.isbnApi //this fails
}

我还从this answer to a similar question找到了其他信息。特别是,

  

请注意,因为您正在使用'def',因此无需将其添加到   瞬态列表。您是否尝试从静态方法访问它?   它是一个实例字段,因此您只能从实例访问它。

2 个答案:

答案 0 :(得分:2)

按照惯例,Grails服务自动成为依赖注入的候选者(=它们可以注入其他类)。如果您想要其他课程,则必须将其添加到conf/spring/resources.groovy

E.g:

import foo.bar.IsbnApi

beans = {
  isbnApi(IsbnApi)
}

查看Bean Builder文档部分。

要确保您的字段不被视为持久属性,您可以使用静态transients字段。

例如:

class User {
  def grailsApplication
  static transients = ['grailsApplication']
}

请参阅transients documentation

答案 1 :(得分:0)

除了已经接受的答案之外,从grails 3.2.x开始,您还需要在映射块中的域对象或应用程序配置中全局启用自动装配

class Book {

    static transients = ['isbnApi']

    IsbnApi isbnApi

    static mapping = {
        autowire true
    }
}

默认情况下,它是禁用的,以提高读取性能,因此也许最好找到替代方法而不是启用它。

http://grailsblog.objectcomputing.com/posts/2017/05/09/injecting-a-service-into-a-domain-class.html