我之前从未使用过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',因此无需将其添加到 瞬态列表。您是否尝试从静态方法访问它? 它是一个实例字段,因此您只能从实例访问它。
答案 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']
}
答案 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