Configuration(args...): 代码会自动调用结构中"方法名与返回值类型名称一致的方法,进行初始化beanMap"
Set(args...): 该注入方式支持使用结构体中tag,其标记为:inject,默认标记值为`inject:"auto"`或`inject:""`或不写tag,以上方式都以单例方式注入,
若填入标记的值为"结构.方法的类型",如:`inject:"ServiceB.Hello()"`或`inject:"ServiceB.Hello"`,则会调用ServiceB的Hello方法进行依赖注入,
若ServiceA结构中包含了ServiceB,则使用tag`inject:"ServiceA.Hello()"`或`inject:"ServiceA.Hello"`方式也可注入,
前提是ServiceA中的Hello方法返回值类型为目标类型,仅当结构体中字段为Struct指针类型时,才可注入成功
Get(bean): 该方法返回容器中的Bean,使用前须判断是否为空指针,依赖注入方式为懒注入方式,仅当调用Get方法时才进行一次性注入(单例),动态注入(多例)
*/
package main
import (
"fmt"
"reflect"
"strings"
)
var beanMap map[reflect.Type]reflect.Value
var funcMap map[string]any
func init() {
beanMap = make(map[reflect.Type]reflect.Value)
funcMap = make(map[string]any)
}
func Set(beans ...any) {
for i := range beans {
_type := reflect.TypeOf(beans[i])
if !(_type.Kind() == reflect.Ptr && _type.Elem().Kind() == reflect.Struct) {
panic("it is not struct pointer")
}
if _, ok := beanMap[reflect.ValueOf(beans[i]).Type()]; !ok {
beanMap[reflect.ValueOf(beans[i]).Type()] = reflect.ValueOf(beans[i])
funcMap[reflect.TypeOf(beans[i]).Elem().Name()] = beans[i]
}
}
}
func Get[T any](bean T) T {
if t := reflect.TypeOf(bean); !(t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct) {
return bean
}
if beanPtr, ok := beanMap[reflect.TypeOf(bean)]; ok {
beanPtrType := reflect.TypeOf(beanPtr.Interface().(T)).Elem()
beanPtrValue := reflect.ValueOf(beanPtr.Interface().(T)).Elem()
for i := 0; i < beanPtrType.NumField(); i++ {
tField, vField := beanPtrType.Field(i), beanPtrValue.Field(i)
if tField.Type.Kind() == reflect.Ptr &&
tField.Type.Elem().Kind() == reflect.Struct &&
vField.IsNil() && vField.CanSet() {
switch tag := tField.Tag.Get("inject"); {
case tag == "auto" || tag == "": //单例模式
if ptr := Get(vField.Interface()); ptr != nil {
vField.Set(reflect.ValueOf(ptr))
}
default: //多例模式
str := strings.Split(tag, ".")
if len(str) != 2 {
panic("inject tag: " + tag + " error")
}
StructName, FuncName := str[0], strings.ReplaceAll(str[1], "()", "")
if mt, isOk := reflect.TypeOf(funcMap[StructName]).MethodByName(FuncName); isOk {
if mt.Type.NumIn() == 1 && mt.Type.NumOut() == 1 && //入参1(接收者本身) 出参1(创建的结构体指针)
mt.Type.Out(0).Kind() == reflect.Ptr &&
mt.Type.Out(0).Elem().Kind() == reflect.Struct &&
vField.Type().Elem().Name() == mt.Type.Out(0).Elem().Name() { // 类型一致
instance := mt.Func.Call([]reflect.Value{reflect.ValueOf(funcMap[StructName])})[0]
vField.Set(reflect.ValueOf(instance.Interface()))
if _, okay := beanMap[reflect.TypeOf(instance.Interface())]; !okay {
beanMap[reflect.TypeOf(instance.Interface())] = reflect.ValueOf(instance.Interface())
}
}
} else {
panic("inject tag: " + tag + " method not found")
}
}
}
}
return beanPtr.Interface().(T)
}
return bean
}
func Configuration(configs ...interface{}) {
for i := range configs {
_type := reflect.TypeOf(configs[i])
if !(_type.Kind() == reflect.Ptr && _type.Elem().Kind() == reflect.Struct) {
panic("it is not struct pointer")
}
funcMap[reflect.TypeOf(configs[i]).Elem().Name()] = configs[i]
for j := 0; j < _type.NumMethod(); j++ {
mt := _type.Method(j).Type
if mt.NumIn() == 1 && mt.NumOut() == 1 && //入参1(接收者本身) 出参1(创建的结构体指针)
mt.Out(0).Elem().Name() == _type.Method(j).Name && // 方法名和返回类型名一致时才注入
mt.Out(0).Kind() == reflect.Ptr && //是指针
mt.Out(0).Elem().Kind() == reflect.Struct { //是结构体
instance := _type.Method(j).Func.Call([]reflect.Value{reflect.ValueOf(configs[i])})[0] //_value.Method(j).Call(nil)[0]
if _, ok := beanMap[reflect.TypeOf(instance.Interface())]; !ok {
beanMap[reflect.TypeOf(instance.Interface())] = reflect.ValueOf(instance.Interface())
funcMap[reflect.TypeOf(instance.Interface()).Elem().Name()] = instance.Interface()
}
}
}
}
}
//------------------以下为测试代码
type ServiceA struct {
Name string
*ServiceB `inject:"ServiceB.Hello()"` // ServiceA.Hello or ServiceB.Hello
ServiceC
}
func (a *ServiceA) Hello() *ServiceB {
return &ServiceB{Name: "A多例模式"}
}
type ServiceB struct {
Name string
}
type ServiceC struct {
Name string
}
type ServiceD struct {
*ServiceA
*ServiceB `inject:"auto"`
*ServiceC `inject:"ServiceC.Init"`
}
func (b *ServiceB) Hello() *ServiceB {
return &ServiceB{Name: "多例模式"}
}
type Config struct{}
func (c *Config) ServiceA() *ServiceA { // 返回值与方法名一致
return &ServiceA{Name: "ServiceA"}
}
func (c *Config) ServiceB() *ServiceB {
return &ServiceB{Name: "ServiceB"}
}
func (c *Config) ServiceC() *ServiceC {
return &ServiceC{Name: "ServiceC"}
}
func (*ServiceC) Init() *ServiceC {
return &ServiceC{Name: "ServiceC-多例"}
}
func (c *Config) ServiceD() *ServiceD {
return &ServiceD{}
}
func (c *Config) TalkService() *TalkService {
return &TalkService{}
}
type TalkService struct {
}
func (t *TalkService) Talk() {
fmt.Println("I am TalkService")
}
func main() {
cfg := &Config{}
Configuration(cfg)
//Set(&ServiceA{Name: "ServiceA 你好呀"}, &ServiceB{}, &ServiceC{}, &ServiceD{})
fmt.Println(Get((*ServiceA)(nil)))
fmt.Println(Get((*ServiceA)(nil)).ServiceB)
fmt.Println(Get((*ServiceB)(nil)))
fmt.Println(Get((*ServiceC)(nil)))
fmt.Println(Get((*ServiceD)(nil)))
fmt.Println(Get((*ServiceD)(nil)).ServiceA)
fmt.Println(Get((*ServiceD)(nil)).ServiceA.ServiceB)
fmt.Println(Get((*ServiceD)(nil)).ServiceB)
fmt.Println(Get((*ServiceD)(nil)).ServiceC) //
fmt.Println()
if talk := Get((*TalkService)(nil)); talk != nil {
talk.Talk()
}
}