diff --git a/modular/example/internal/service/expose/attack.go b/modular/example/internal/service/expose/attack.go new file mode 100644 index 00000000..d7b2766b --- /dev/null +++ b/modular/example/internal/service/expose/attack.go @@ -0,0 +1,5 @@ +package expose + +type Attack interface { + Name() string +} diff --git a/modular/example/internal/service/expose/login.go b/modular/example/internal/service/expose/login.go new file mode 100644 index 00000000..6beef399 --- /dev/null +++ b/modular/example/internal/service/expose/login.go @@ -0,0 +1,5 @@ +package expose + +type Login interface { + Name() string +} diff --git a/modular/example/internal/service/services/attack/attack.go b/modular/example/internal/service/services/attack/attack.go new file mode 100644 index 00000000..4b115246 --- /dev/null +++ b/modular/example/internal/service/services/attack/attack.go @@ -0,0 +1,27 @@ +package attack + +import ( + "fmt" + "github.com/kercylan98/minotaur/modular/example/internal/service/expose" +) + +type Service struct { + Login expose.Login + name string +} + +func (a *Service) OnInit() { + a.name = "attack" +} + +func (a *Service) OnPreload() { + fmt.Println(a.name, "call", a.Login.Name()) +} + +func (a *Service) OnMount() { + +} + +func (a *Service) Name() string { + return a.name +} diff --git a/modular/example/internal/service/services/login/login.go b/modular/example/internal/service/services/login/login.go new file mode 100644 index 00000000..99b3de3b --- /dev/null +++ b/modular/example/internal/service/services/login/login.go @@ -0,0 +1,27 @@ +package login + +import ( + "fmt" + "github.com/kercylan98/minotaur/modular/example/internal/service/expose" +) + +type Service struct { + Attack expose.Attack + name string +} + +func (l *Service) OnInit() { + l.name = "login" +} + +func (l *Service) OnPreload() { + fmt.Println(l.name, "call", l.Attack.Name()) +} + +func (l *Service) OnMount() { + +} + +func (l *Service) Name() string { + return l.name +} diff --git a/modular/example/main.go b/modular/example/main.go new file mode 100644 index 00000000..35d7a1cf --- /dev/null +++ b/modular/example/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "github.com/kercylan98/minotaur/modular" + "github.com/kercylan98/minotaur/modular/example/internal/service/services/attack" + "github.com/kercylan98/minotaur/modular/example/internal/service/services/login" +) + +func main() { + modular.RegisterServices( + new(attack.Service), + new(login.Service), + ) + modular.Run() +} diff --git a/modular/modular.go b/modular/modular.go new file mode 100644 index 00000000..58fc55df --- /dev/null +++ b/modular/modular.go @@ -0,0 +1,69 @@ +package modular + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/log" + "reflect" +) + +var application *modular + +func init() { + application = &modular{} +} + +type modular struct { + registerServices []Service + services []*service +} + +// RegisterServices 注册服务 +func (m *modular) RegisterServices(s ...Service) { + application.registerServices = append(application.registerServices, s...) +} + +// Run 运行模块化应用程序 +func Run() { + m := application + var names = make(map[string]bool) + var tvm = make(map[reflect.Type]reflect.Value) + for i := 0; i < len(m.registerServices); i++ { + s := newService(m.registerServices[i]) + if names[s.name] { + panic(fmt.Errorf("service %s is already registered", s.name)) + } + names[s.name] = true + tvm[s.vof.Type()] = s.vof + m.services = append(m.services, s) + } + + // OnInit + for i := 0; i < len(m.services); i++ { + s := m.services[i] + s.instance.OnInit() + log.Info(fmt.Sprintf("service %s initialized", s.name)) + } + + // OnPreload + for i := 0; i < len(m.services); i++ { + s := m.services[i] + for f := 0; f < s.vof.Elem().NumField(); f++ { + field := s.vof.Elem().Field(f) + for _, v := range tvm { + if v.Type().AssignableTo(field.Type()) { + field.Set(v) + break + } + } + } + s.instance.OnPreload() + log.Info(fmt.Sprintf("service %s preloaded", s.name)) + } + + // OnMount + for i := 0; i < len(m.services); i++ { + s := m.services[i] + s.instance.OnMount() + log.Info(fmt.Sprintf("service %s mounted", s.name)) + } +} diff --git a/modular/service.go b/modular/service.go new file mode 100644 index 00000000..55b443ee --- /dev/null +++ b/modular/service.go @@ -0,0 +1,36 @@ +package modular + +import "reflect" + +// Service 模块化服务接口,所有的服务均需要实现该接口,在服务的生命周期内发生任何错误均应通过 panic 阻止服务继续运行 +// - 生命周期示例: OnInit -> OnPreload -> OnMount +type Service interface { + // OnInit 服务初始化阶段,该阶段不应该依赖其他任何服务 + OnInit() + + // OnPreload 预加载阶段,在进入该阶段时,所有服务已经初始化完成,可在该阶段注入其他服务的依赖 + OnPreload() + + // OnMount 挂载阶段,该阶段所有服务本身及依赖的服务都已经初始化完成,可在该阶段进行服务功能的定义 + OnMount() +} + +// RegisterServices 注册服务 +func RegisterServices(s ...Service) { + application.RegisterServices(s...) +} + +func newService(instance Service) *service { + vof := reflect.ValueOf(instance) + return &service{ + name: vof.Type().String(), + instance: instance, + vof: vof, + } +} + +type service struct { + name string + instance Service + vof reflect.Value +}