服务 (Services)
服务管理
在 nstarter 框架中,服务主要承载业务中核心的实现逻辑部分。考虑到本身业务之前各服务之间存在有互相调用的灵活需求,业务服务同样通过 IoC 容器来注册管理,同时也可以实现服务层内部发现。
nstarter-core 针对服务管理提供了对应的工具方法与装饰器:
import {
service,
injectService,
registerSvc,
getSvc
} from 'nstarter-core';
-
服务注册
服务对象统一以实例化的类进行定义,对应的业务逻辑方法直接申明在相关的类上。服务对象使用时,一般以单例方式,或者也可以采用实例化的方式引用。在定义服务对象时,与组件定义的过程类似,使用
service装饰器来为相关对象自动绑定作为服务对象引用的相关元数据信息。import { service } from 'nstarter-core';
@service()
export class PingService {
public ping() {
console.log('ping');
}
}service装饰器支持可选传入一个标识符用于标识注册的服务对象。定义标识后,在引用时也可以使用同样的标识符进行引用。服务标识可以是string或者固定的Symbol对象。默认情况下,service会根据定义的服务对象类名自动生成对应的标识符用于使用,而无需额外自定义管理。在完成服务对象定义后,还需要将对应的服务对象注册到服务管理容器上,一般使用
registerSvc方法来实现。同时,对于在服务层外部获取的服务对象,可以直接通过使用getSvc工具方法来引用出被注册的对象实例。import { registerSvc, getSvc } from 'nstarter-core';
import { PingService } from './ping.service';
registerSvc(PingService);
export const pingService = getSvc<PingService>(PingService); -
内部服务引用
对于服务层内部的的其他服务之间互相引用,可以通过
injectService装饰器配合service装饰器的申明,来将被依赖的业务服务实例直接注册到目标服务对象上,随后便可以直接使用对应依赖的业务方法执行相关的业务逻辑调用。injectService与service类似,同样提供了一个可选参数,用于传入引用的服务对象标识符。默认情况下,目标对象的类属性只要满足对应对象类名的驼峰命名规则,即可在不定义标识符的情况下自动完成发现与注册。例如,使用PingService定义的服务对象,在被其他服务对象引用时,直接使用pingService参数引用即可自动完成关联引用。在需要自定义的场景下,也支持配置自己所需要的标识符进行标识引用。import { PingService } from './ping.service';
import { injectService, service } from 'nstarter-core';
@service()
export class PongService {
@injectService()
private pingService: PingService;
public pong() {
console.log('pong');
}
public ping() {
this.pingService.ping();
}
} -
领域隔离的服务管理
ℹ️
nstarter-core:1.1.0版本在支持的新特性。在不同类型的工程实际服务层逻辑组织中,对于一些封装有复杂服务层逻辑的 npm 业务工程包,或者使用 monorepo 方式管理的复杂独立模块工程项目,如果仍然维持将所有不同领域的服务对象,注册到同一个公共服务管理容器中,会带来一系列的服务管理和使用上的困境。典型的例子,由于服务对象的开发实现会按照模块隔离,不同模块下无法直接关注到其他模块服务对象的定义实现,使用公共注册容器,会直接导致服务注册域使用的冲突。
为了解决这个问题,
nstarter-core从1.1.0版本开始,引入了服务对象的领域隔离管理机制。通过使用getScopedServiceDecorators装饰器生成方法,可以生成指定领域下的服务层装饰器。获取对应领域的service,injectService装饰器后,便可通过与默认全局装饰器完全相同的方式来使用。import { getScopedServiceDecorators } from 'nstarter-core';
const scope = Symbol.for('demo_scope');
const { service, injectService } = getScopedServiceDecorators(scope);