Ther Service Layer
Grails 定义了service 层的概念,grails团队不赞成把核心业务放入到Controllers里面去,因为它不能提升重用和划分清晰。
grails把主要的业务逻辑放在业务层里面,controllers去负责处理request流程,转向(redirect)等等。
创建service
grails create-service simple
他的存放地址是grails-app/services/SimpleService.groovy
声明性事务
service中最具代表性的棘手问题是在两个Domian classes中的并行逻辑操作,这是因为他们的持久化跨越了两个操作。service允许我们授权一个事务划分,本质上就是说明一个service中类的所有方法都是被声明的。
class CountryService {
static transactional = false
}
关闭一个自动事务声明。
注意:只要DI是唯一的方法让service declarative方法工作,如果你使用new service 将不会让事务有效。
service 范围
默认情况下访问service方法不是同步,service是单例的,所以你必须小心在里面处理数据库储存,最好或最简单的方法就是不要在service中保存数据。
想要改变这种行为,你可以改变service的scope,目前支持以下几种。
- prototype
- request
- flash
- flow
- conversation
- singleton (defalult)
使用scopes的方法
static scope = "flow"
依赖注入service
基础:
grails使用spring的DI,grails支持DI by convention(约定)。
Grails仅仅支持DI by name,并不支持DI by typed。
给controller注入
class BookController {
def bookService
…
}
class AuthorService {
BookService bookService
}
service给service注入
class AuthorService {
def bookService
}
给Domian 注入
class Book {
…
def bookService
def buyBook() {
bookService.buyBook(this)
}
}
使用java的service
如果把service类放入grails-app/services 中,java类是不能引用他的。
有一个办法可以解决,创建一个as grails-app/services/bookstore目录
在你创建的service中声明一个package bookstore
package bookstore
class BookService {
void buyBook(Book book) {
// logic
}
}
或者声明一个接口
package bookstore;
interface BookStore {
void buyBook(Book book);
}
实现这个service
class BookService implements bookstore.BookStore {
void buyBook(Book b) {
// logic
}
}
创建一个java类放入到src/java中
package bookstore;
// note: this is Java class
public class BookConsumer {
private BookStore store; public void setBookStore(BookStore storeInstance) {
this.store = storeInstance;
}
…
}
进行spring配置,在grails-app/conf/spring/resources.xml 添加这些代码
<bean id="bookConsumer" class="bookstore.BookConsumer">
<property name="bookStore" ref="bookService" />
</bean>