ing
This commit is contained in:
parent
35e3b97fb9
commit
93072d1a5e
10
Gopkg.lock
generated
10
Gopkg.lock
generated
|
@ -5,13 +5,19 @@
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "git.loafle.net/overflow/annotation-go"
|
name = "git.loafle.net/overflow/annotation-go"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "9d80d778c61e1a08a46c19835e36f18cf08c1f91"
|
revision = "178b12d303bdd83566a35d71cce68b0c6cc1f4d3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "git.loafle.net/overflow/util-go"
|
name = "git.loafle.net/overflow/util-go"
|
||||||
packages = ["reflect"]
|
packages = ["reflect"]
|
||||||
revision = "01cc315e25b38331c0a366d8025600ed4e297e8e"
|
revision = "fae2846a85aad314ee44957d428478fbe800045f"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/yaml.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
|
version = "v2.2.1"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
|
|
|
@ -17,4 +17,5 @@ var InjectAnnotationType = reflect.TypeOf((*InjectAnnotation)(nil))
|
||||||
type InjectAnnotation struct {
|
type InjectAnnotation struct {
|
||||||
oa.Annotation `@name:"@Inject"`
|
oa.Annotation `@name:"@Inject"`
|
||||||
Name string `json:"name" @default:""`
|
Name string `json:"name" @default:""`
|
||||||
|
Required bool `json:"required" @default:"true"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,5 @@ var InjectableAnnotationType = reflect.TypeOf((*InjectableAnnotation)(nil))
|
||||||
|
|
||||||
type InjectableAnnotation struct {
|
type InjectableAnnotation struct {
|
||||||
oa.Annotation `@name:"@Injectable"`
|
oa.Annotation `@name:"@Injectable"`
|
||||||
Name string `json:"name" @default:""`
|
Name string `json:"name" @default:""`
|
||||||
InitMethod string `json:"initMethod"`
|
|
||||||
DestroyMethod string `json:"destroyMethod"`
|
|
||||||
Scope ScopeType `json:"scope"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScopeType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
ScopeTypeDefault ScopeType = "Default" // == ScopeTypeSingleton
|
|
||||||
ScopeTypeSingleton ScopeType = "Singleton"
|
|
||||||
ScopeTypeTransiant ScopeType = "Transiant"
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package annotation
|
|
||||||
|
|
||||||
// @Resource(name? string)
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
oa "git.loafle.net/overflow/annotation-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
oa.Register(ResourceAnnotationType)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ResourceAnnotationType = reflect.TypeOf((*ResourceAnnotation)(nil))
|
|
||||||
|
|
||||||
type ResourceAnnotation struct {
|
|
||||||
oa.Annotation `@name:"@Resource"`
|
|
||||||
Name string `json:"name" @default:""`
|
|
||||||
}
|
|
71
annotation/scope.go
Normal file
71
annotation/scope.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package annotation
|
||||||
|
|
||||||
|
// @Scope(name? string)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
oa "git.loafle.net/overflow/annotation-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
oa.Register(ScopeAnnotationType)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ScopeAnnotationType = reflect.TypeOf((*ScopeAnnotation)(nil))
|
||||||
|
|
||||||
|
type ScopeAnnotation struct {
|
||||||
|
oa.Annotation `@name:"@Scope"`
|
||||||
|
Value ScopeType `json:"value" @default:"singleton"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScopeType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
ScopeTypeDefault ScopeType = iota + 1
|
||||||
|
ScopeTypeSingleton
|
||||||
|
ScopeTypeTransiant
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
scopeTypeID = map[ScopeType]string{
|
||||||
|
ScopeTypeDefault: "default",
|
||||||
|
ScopeTypeSingleton: "singleton",
|
||||||
|
ScopeTypeTransiant: "transiant",
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeTypeKey = map[string]ScopeType{
|
||||||
|
"default": ScopeTypeDefault,
|
||||||
|
"singleton": ScopeTypeSingleton,
|
||||||
|
"transiant": ScopeTypeTransiant,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (st ScopeType) String() string {
|
||||||
|
return scopeTypeID[st]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st ScopeType) MarshalJSON() ([]byte, error) {
|
||||||
|
value, ok := scopeTypeID[st]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Invalid EnumType[%s] value", st)
|
||||||
|
}
|
||||||
|
return json.Marshal(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st ScopeType) UnmarshalJSON(b []byte) error {
|
||||||
|
var s string
|
||||||
|
err := json.Unmarshal(b, &s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := scopeTypeKey[s]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Invalid EnumType[%s] value", s)
|
||||||
|
}
|
||||||
|
st = value
|
||||||
|
return nil
|
||||||
|
}
|
128
registry.go
128
registry.go
|
@ -13,7 +13,8 @@ import (
|
||||||
|
|
||||||
type Registry interface {
|
type Registry interface {
|
||||||
RegisterType(t reflect.Type)
|
RegisterType(t reflect.Type)
|
||||||
RegisterResource(name string, resource interface{}) error
|
RegisterSingleton(singleton interface{}) error
|
||||||
|
RegisterSingletonByName(name string, singleton interface{}) error
|
||||||
|
|
||||||
GetInstance(t reflect.Type) (interface{}, error)
|
GetInstance(t reflect.Type) (interface{}, error)
|
||||||
GetInstances(ts []reflect.Type) ([]interface{}, error)
|
GetInstances(ts []reflect.Type) ([]interface{}, error)
|
||||||
|
@ -59,7 +60,7 @@ func (r *InstanceRegistry) RegisterType(t reflect.Type) {
|
||||||
log.Panicf("t[reflect.Type] is nil")
|
log.Panicf("t[reflect.Type] is nil")
|
||||||
}
|
}
|
||||||
if !our.IsTypeKind(t, reflect.Struct, true) {
|
if !our.IsTypeKind(t, reflect.Struct, true) {
|
||||||
log.Panicf("t[reflect.Type] must be specified but is %v", t)
|
log.Panicf("t[reflect.Type] must be Struct but is %v", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
td, err := r.buildDefinition(t)
|
td, err := r.buildDefinition(t)
|
||||||
|
@ -91,14 +92,42 @@ func (r *InstanceRegistry) RegisterType(t reflect.Type) {
|
||||||
r.definitionByName[name] = td
|
r.definitionByName[name] = td
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterResource(name string, resource interface{}) error {
|
func RegisterSingleton(singleton interface{}) error {
|
||||||
return AppRegistry.RegisterResource(name, resource)
|
return AppRegistry.RegisterSingleton(singleton)
|
||||||
}
|
}
|
||||||
func (r *InstanceRegistry) RegisterResource(name string, resource interface{}) error {
|
func (r *InstanceRegistry) RegisterSingleton(singleton interface{}) error {
|
||||||
if _, ok := r.instanceByName[name]; ok {
|
t := reflect.TypeOf(singleton)
|
||||||
return fmt.Errorf("Resource[%s] is already exist", name)
|
|
||||||
|
if nil == t {
|
||||||
|
log.Panicf("t[reflect.Type] is nil")
|
||||||
}
|
}
|
||||||
r.instanceByName[name] = resource
|
|
||||||
|
rt, _, tName := our.GetTypeInfo(t)
|
||||||
|
if !our.IsTypeKind(rt, reflect.Struct, true) {
|
||||||
|
log.Panicf("t[reflect.Type] must be Struct but is %v", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.instanceByType[rt] = singleton
|
||||||
|
|
||||||
|
r.RegisterSingletonByName(tName, singleton)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterSingletonByName(name string, singleton interface{}) error {
|
||||||
|
return AppRegistry.RegisterSingletonByName(name, singleton)
|
||||||
|
}
|
||||||
|
func (r *InstanceRegistry) RegisterSingletonByName(name string, singleton interface{}) error {
|
||||||
|
t := reflect.TypeOf(singleton)
|
||||||
|
|
||||||
|
if nil == t {
|
||||||
|
log.Panicf("t[reflect.Type] is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := r.instanceByName[name]; ok {
|
||||||
|
return fmt.Errorf("name[%s] of Singleton is already exist", name)
|
||||||
|
}
|
||||||
|
r.instanceByName[name] = singleton
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -138,9 +167,9 @@ func (r *InstanceRegistry) GetInstance(t reflect.Type) (instance interface{}, er
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
td *TypeDefinition
|
td *TypeDefinition
|
||||||
comV interface{}
|
injectableV interface{}
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
rt, _, _ := our.GetTypeInfo(t)
|
rt, _, _ := our.GetTypeInfo(t)
|
||||||
|
@ -150,8 +179,8 @@ func (r *InstanceRegistry) GetInstance(t reflect.Type) (instance interface{}, er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if comV, ok = r.instanceByType[td.RealType]; ok {
|
if injectableV, ok = r.instanceByType[td.RealType]; ok {
|
||||||
return comV, nil
|
return injectableV, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.New(rt)
|
v := reflect.New(rt)
|
||||||
|
@ -159,6 +188,14 @@ func (r *InstanceRegistry) GetInstance(t reflect.Type) (instance interface{}, er
|
||||||
|
|
||||||
instance = v.Interface()
|
instance = v.Interface()
|
||||||
r.instanceByType[td.RealType] = instance
|
r.instanceByType[td.RealType] = instance
|
||||||
|
|
||||||
|
if a, err := oa.GetTypeAnnotation(td.Type, annotation.InjectableAnnotationType); nil == err && nil != a {
|
||||||
|
_a := a.(*annotation.InjectableAnnotation)
|
||||||
|
if "" != _a.Name {
|
||||||
|
r.instanceByName[_a.Name] = instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = nil
|
err = nil
|
||||||
defer func() {
|
defer func() {
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -177,6 +214,7 @@ func (r *InstanceRegistry) GetInstance(t reflect.Type) (instance interface{}, er
|
||||||
return nil, fmt.Errorf("%v", err)
|
return nil, fmt.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
if nil != ass {
|
if nil != ass {
|
||||||
|
LOOP:
|
||||||
for n, as := range ass {
|
for n, as := range ass {
|
||||||
f := rv.FieldByName(n)
|
f := rv.FieldByName(n)
|
||||||
|
|
||||||
|
@ -191,26 +229,47 @@ func (r *InstanceRegistry) GetInstance(t reflect.Type) (instance interface{}, er
|
||||||
|
|
||||||
a, ok = as[annotation.InjectAnnotationType]
|
a, ok = as[annotation.InjectAnnotationType]
|
||||||
if ok {
|
if ok {
|
||||||
if fV, err = r.GetInstance(f.Type()); nil != err {
|
_a := a.(*annotation.InjectAnnotation)
|
||||||
return
|
if "" == _a.Name {
|
||||||
}
|
if fV, err = r.GetInstance(f.Type()); nil == err {
|
||||||
}
|
log.Printf("%s of %s injected by type[%s]", n, td.RealType.Name(), reflect.TypeOf(fV))
|
||||||
|
f.Set(reflect.ValueOf(fV))
|
||||||
|
continue LOOP
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("cannot find instance for %s[Type:%s]", n, f.Type())
|
||||||
|
}
|
||||||
|
|
||||||
a, ok = as[annotation.ResourceAnnotationType]
|
if fV, err = r.GetInstanceByName(n); nil == err {
|
||||||
if ok {
|
log.Printf("%s of %s injected by name[%s]", n, td.RealType.Name(), n)
|
||||||
name := a.(*annotation.ResourceAnnotation).Name
|
f.Set(reflect.ValueOf(fV))
|
||||||
if "" == name {
|
continue LOOP
|
||||||
name = n
|
} else {
|
||||||
}
|
err = fmt.Errorf("cannot find instance for %s[Name:%s]", n, n)
|
||||||
if fV, err = r.GetInstanceByName(name); nil != err {
|
}
|
||||||
return
|
} else {
|
||||||
}
|
if fV, err = r.GetInstanceByName(_a.Name); nil == err {
|
||||||
}
|
log.Printf("%s of %s injected by name[%s]", n, td.RealType.Name(), _a.Name)
|
||||||
|
f.Set(reflect.ValueOf(fV))
|
||||||
|
continue LOOP
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("cannot find instance for %s[Name:%s]", n, _a.Name)
|
||||||
|
}
|
||||||
|
|
||||||
if nil != err {
|
if fV, err = r.GetInstance(f.Type()); nil == err {
|
||||||
return
|
log.Printf("%s of %s injected by type[%s]", n, td.RealType.Name(), reflect.TypeOf(fV))
|
||||||
|
f.Set(reflect.ValueOf(fV))
|
||||||
|
continue LOOP
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("cannot find instance for %s[Type:%s]", n, f.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil != err {
|
||||||
|
if _a.Required {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f.Set(reflect.ValueOf(fV))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,11 +280,18 @@ func GetInstanceByName(name string) (interface{}, error) {
|
||||||
return AppRegistry.GetInstanceByName(name)
|
return AppRegistry.GetInstanceByName(name)
|
||||||
}
|
}
|
||||||
func (r *InstanceRegistry) GetInstanceByName(name string) (interface{}, error) {
|
func (r *InstanceRegistry) GetInstanceByName(name string) (interface{}, error) {
|
||||||
|
if td, ok := r.definitionByName[name]; ok {
|
||||||
|
v, err := r.GetInstance(td.Type)
|
||||||
|
if nil == err {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v, ok := r.instanceByName[name]
|
v, ok := r.instanceByName[name]
|
||||||
if ok {
|
if ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("Resource[%s] is not exist", name)
|
return nil, fmt.Errorf("Instance[%s] is not exist", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInstances returns instance of annotated
|
// GetInstances returns instance of annotated
|
||||||
|
|
|
@ -52,7 +52,6 @@ func TestRegisterType(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
args args
|
args args
|
||||||
}{
|
}{
|
||||||
// TODO: Add test cases.
|
|
||||||
{
|
{
|
||||||
name: "InjectableService",
|
name: "InjectableService",
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -99,7 +98,7 @@ func TestInstanceRegistry_RegisterType(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterResource(t *testing.T) {
|
func TestRegisterSingletonByName(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
name string
|
name string
|
||||||
resource interface{}
|
resource interface{}
|
||||||
|
@ -113,14 +112,14 @@ func TestRegisterResource(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if err := RegisterResource(tt.args.name, tt.args.resource); (err != nil) != tt.wantErr {
|
if err := RegisterSingletonByName(tt.args.name, tt.args.resource); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("RegisterResource() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("RegisterSingletonByName() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstanceRegistry_RegisterResource(t *testing.T) {
|
func TestInstanceRegistry_RegisterSingletonByName(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
parent Registry
|
parent Registry
|
||||||
definitionByType map[reflect.Type]*TypeDefinition
|
definitionByType map[reflect.Type]*TypeDefinition
|
||||||
|
@ -149,8 +148,8 @@ func TestInstanceRegistry_RegisterResource(t *testing.T) {
|
||||||
instanceByType: tt.fields.instanceByType,
|
instanceByType: tt.fields.instanceByType,
|
||||||
instanceByName: tt.fields.instanceByName,
|
instanceByName: tt.fields.instanceByName,
|
||||||
}
|
}
|
||||||
if err := r.RegisterResource(tt.args.name, tt.args.resource); (err != nil) != tt.wantErr {
|
if err := r.RegisterSingletonByName(tt.args.name, tt.args.resource); (err != nil) != tt.wantErr {
|
||||||
t.Errorf("InstanceRegistry.RegisterResource() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("InstanceRegistry.RegisterSingletonByName() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -208,7 +207,6 @@ func TestGetInstance(t *testing.T) {
|
||||||
args args
|
args args
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
// TODO: Add test cases.
|
|
||||||
{
|
{
|
||||||
name: "InjectService",
|
name: "InjectService",
|
||||||
args: args{
|
args: args{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user