diff --git a/annotation/component.go b/annotation/component.go index f7fde6b..d0bb5f8 100644 --- a/annotation/component.go +++ b/annotation/component.go @@ -1,6 +1,12 @@ package annotation -type Component struct { - Names *[]string - Scope *ScopeType +import ( + "git.loafle.net/commons_go/di" +) + +type ComponentAnnotation struct { + Names []string + InitMethod string // func (receiver interface{}, cr ComponentRegistry) error + DestroyMethod string // func (receiver interface{}, cr ComponentRegistry) error + Scope di.ScopeType } diff --git a/annotation/inject.go b/annotation/inject.go index 730b3d8..027aad8 100644 --- a/annotation/inject.go +++ b/annotation/inject.go @@ -1,6 +1,5 @@ package annotation type Inject struct { - Name *string - Required *bool + Name string } diff --git a/annotation/resource.go b/annotation/resource.go new file mode 100644 index 0000000..d78a905 --- /dev/null +++ b/annotation/resource.go @@ -0,0 +1,5 @@ +package annotation + +type Resource struct { + Name string +} diff --git a/annotation/scope.go b/annotation/scope.go deleted file mode 100644 index dd6dee2..0000000 --- a/annotation/scope.go +++ /dev/null @@ -1,8 +0,0 @@ -package annotation - -type ScopeType int - -const ( - ScopeTypeSingleton ScopeType = iota - ScopeTypeTransiant -) diff --git a/constants.go b/constants.go new file mode 100644 index 0000000..dec394a --- /dev/null +++ b/constants.go @@ -0,0 +1,25 @@ +package di + +// `annotation:"@Inject(name? string)"` +// field 에 적용 +// 1. 타입으로 매칭 없으면 에러 2. 여러개의 타입이 검색되면 그 중에 name으로 매칭 + +// `annotation:"@Resource(name? string)"` +// field 에 적용 +// 1. 이름으로 매칭 2. 타입으로 매칭 +// 이름이 지정되지 않으면 field 이름으로 먼저 찾고 없으면 타입으로 매칭 + +// @Component +// Component 등록 시에 파라미터로 제공 +// names []string +// initMethod string +// destroyMethod string +// scope enum singleton, transiant + +type ScopeType int + +const ( + ScopeTypeDefault ScopeType = iota // == ScopeTypeSingleton + ScopeTypeSingleton + ScopeTypeTransiant +) diff --git a/ex b/ex deleted file mode 100644 index b6e6ef9..0000000 --- a/ex +++ /dev/null @@ -1,112 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "log" - "reflect" - - "git.loafle.net/prototype/reflection/service" -) - -func main() { - var err error - r := &Registry{} - // if err = r.RegisterType(&Dao{}); nil != err { - // log.Printf("%v \n", err) - // } - if err = r.RegisterType(reflect.TypeOf((*service.MemberService)(nil))); nil != err { - log.Printf("%v \n", err) - } - // if err = r.RegisterType(&prsu.UserService{}); nil != err { - // log.Printf("%v \n", err) - // } - // if err = r.RegisterType(prsu.UserService{}); nil != err { - // log.Printf("%v \n", err) - // } - // if err = r.RegisterFactory(NewService); nil != err { - // log.Printf("%v \n", err) - // } - - // if err = r.RegisterType(&Controller{}); nil != err { - // log.Printf("%v \n", err) - // } - -} - -func NewService() *Service { - return &Service{} -} - -type Registry struct { -} - -func (r *Registry) RegisterType(t reflect.Type) error { - // t := reflect.TypeOf(s) - if nil == t { - return errors.New("can't provide an untyped nil") - } - - if !IsType(t, reflect.Struct) { - return fmt.Errorf("must provide struct, got %v", t) - } - - name, rt := GetTypeName(t) - log.Printf("The name of Type: %s", name) - - fN := rt.NumField() - for i := 0; i < fN; i++ { - f := rt.Field(i) - log.Printf("The PkgPath: %s", f.PkgPath) - log.Printf("The field[%s] of [%s] is pointer :%v", f.Name, name, f.Type.Kind() == reflect.Ptr) - log.Printf("The tag of [%s.%s]: %s", name, f.Name, f.Tag.Get("annotation")) - } - - return nil -} - -// func (r *Registry) RegisterFactory(s interface{}) error { -// t := reflect.TypeOf(s) -// if nil == t { -// return errors.New("can't provide an untyped nil") -// } - -// if !IsType(t, reflect.Func) { -// return fmt.Errorf("must provide constructor function, got %v (type %v)", s, t) -// } - -// log.Printf("The name of Type: %s", GetTypeName(t)) -// log.Printf("The name of Type: %v", t.IsVariadic()) -// log.Printf("The name of Type: %s", t.PkgPath()) -// log.Printf("The name of Type: %s", GetTypeName(t.Out(0))) - -// return nil -// } - -type Controller struct { - service *Service `annotation:"transiant:singleton"` - MemberService *service.MemberService `annotation:"transiant:singleton"` -} - -type Service struct { - Dao *Dao `annotation:"transiant:singleton"` -} - -type Dao struct { -} - -func IsType(t reflect.Type, kind reflect.Kind) bool { - if reflect.Ptr == t.Kind() { - return IsType(t.Elem(), kind) - } - - return kind == t.Kind() -} - -func GetTypeName(t reflect.Type) (string, reflect.Type) { - if reflect.Ptr == t.Kind() { - return GetTypeName(t.Elem()) - } - - return fmt.Sprintf("%s/%s", t.PkgPath(), t.Name()), t -} diff --git a/registry/definition.go b/registry/definition.go index afe057a..8df8cfb 100644 --- a/registry/definition.go +++ b/registry/definition.go @@ -2,27 +2,9 @@ package registry import "reflect" -type typeDefinition struct { - pkgName string - typeName string - targetType reflect.Type - realType reflect.Type - - fields map[string] +type ComponentDefinition struct { + PkgName string + TypeName string + Type reflect.Type + RealType reflect.Type } - -type fieldDefinition struct { - pkgName string - typeName string - targetType reflect.Type - realType reflect.Type - -} - -type Service struct { - DAO *DAO `di-annotation:""` -} - -type DAO struct { - -} \ No newline at end of file diff --git a/registry/registry.go b/registry/registry.go index 179cc66..10df00b 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -4,22 +4,25 @@ import ( "fmt" "reflect" + cda "git.loafle.net/commons_go/di/annotation" cdur "git.loafle.net/commons_go/di/util/reflect" ) type ComponentRegistry interface { - RegisterType(t reflect.Type, name string) error - RegisterFactory(i interface{}) error + RegisterType(t reflect.Type, ca *cda.ComponentAnnotation) error + RegisterFactory(i interface{}, ca *cda.ComponentAnnotation) error GetInstance(t reflect.Type) (interface{}, error) GetInstanceByName(name string) (interface{}, error) } type defaultComponentRegistry struct { - definitions map[string]reflect.Type + definitionsByType map[reflect.Type]*ComponentDefinition + + definitionByName map[string]*ComponentDefinition } -func (cr *defaultComponentRegistry) RegisterType(t reflect.Type, name string) error { +func (cr *defaultComponentRegistry) RegisterType(t reflect.Type, ca *cda.ComponentAnnotation) error { if nil == t { return fmt.Errorf("DI: t[reflect.Type] is nil") } @@ -27,18 +30,21 @@ func (cr *defaultComponentRegistry) RegisterType(t reflect.Type, name string) er return fmt.Errorf("DI: t[reflect.Type] must be specified but is %v", t) } - rt, pkgName, tName := cdur.GetTypeName(t, true) + rt, pkgName, tName := cdur.GetTypeName(t) cr.definitions[name] = rt return nil } -func (cr *defaultComponentRegistry) RegisterFactory(i interface{}) error { - - return nil -} - func (cr *defaultComponentRegistry) GetInstance(t reflect.Type) (interface{}, error) { + if nil == t { + return nil, fmt.Errorf("DI: t[reflect.Type] is nil") + } + + cd, ok := cr.definitionsByType[t] + if !ok { + cd = cr.buildDefinition(t) + } return nil, nil } @@ -47,3 +53,18 @@ func (cr *defaultComponentRegistry) GetInstanceByName(name string) (interface{}, return nil, nil } + +func (cr *defaultComponentRegistry) buildDefinition(t reflect.Type) (*ComponentDefinition, error) { + if nil == t { + return nil, fmt.Errorf("DI: t[reflect.Type] is nil") + } + + rt, pkgName, tName := cdur.GetTypeName(t) + cd := &ComponentDefinition{} + cd.PkgName = pkgName + cd.TypeName = tName + cd.Type = t + cd.RealType = rt + + return nil, nil +}