From 3e20be322fb337bac622beb3c3d5d808301d205a Mon Sep 17 00:00:00 2001 From: limpo1989 Date: Mon, 30 Oct 2023 17:50:27 +0800 Subject: [PATCH 1/2] Automatically decide whether to clean the container --- gs/app.go | 3 +-- gs/app_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ gs/gs.go | 5 ----- gs/gs_context.go | 13 +++++++++++++ gs/gs_test.go | 5 +++++ 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/gs/app.go b/gs/app.go index a3f45e25..801b112c 100644 --- a/gs/app.go +++ b/gs/app.go @@ -83,7 +83,7 @@ func (app *App) run(resourceLocator ResourceLocator) error { return err } - if err := app.container.refresh(false); err != nil { + if err := app.container.refresh(true); err != nil { return err } @@ -93,7 +93,6 @@ func (app *App) run(resourceLocator ResourceLocator) error { app.onAppStart(app.container) - app.container.clear() logger.Info("application started successfully") // Responding to the Ctrl+C and kill commands in the console. diff --git a/gs/app_test.go b/gs/app_test.go index 0e214746..84936777 100644 --- a/gs/app_test.go +++ b/gs/app_test.go @@ -80,3 +80,51 @@ func TestConfig(t *testing.T) { defer app.Shutdown("run test end") }) } + +func TestContextGetWire(t *testing.T) { + + type GetObject struct { + Name string `value:"${app.name}"` + } + + type ContextAware struct { + Ctx Context `autowire:""` + } + + var appCtx Context + + app := NewApp() + app.Property("app.name", "testapp") + app.Object(new(ContextAware)) + getbd := app.Provide(func(ctx Context) *GetObject { + appCtx = ctx + return &GetObject{} + }) + + go func() { + if err := app.Run(); nil != err { + panic(err) + } + }() + + time.Sleep(200 * time.Millisecond) + + t.Run("Context#Get", func(t *testing.T) { + var getObj *GetObject + err := appCtx.Get(&getObj) + assert.Nil(t, err) + assert.Equal(t, getObj, getbd.Interface()) + }) + + t.Run("Context#Wire", func(t *testing.T) { + + type WireObject struct { + Get *GetObject `autowire:""` + } + + wireObj, err := appCtx.Wire(new(WireObject)) + assert.Nil(t, err) + assert.Equal(t, wireObj.(*WireObject).Get, getbd.Interface()) + }) + +} diff --git a/gs/gs.go b/gs/gs.go index 28b3fa87..33f07d8c 100644 --- a/gs/gs.go +++ b/gs/gs.go @@ -79,11 +79,6 @@ type Context interface { Go(fn func(ctx context.Context)) } -// ContextAware injects the Context into a struct as the field GSContext. -type ContextAware struct { - GSContext Context `autowire:""` -} - type tempContainer struct { props *conf.Properties beans []*BeanDefinition diff --git a/gs/gs_context.go b/gs/gs_context.go index 7740f4e6..6c7f23e5 100644 --- a/gs/gs_context.go +++ b/gs/gs_context.go @@ -73,6 +73,10 @@ func (c *container) Get(i interface{}, selectors ...BeanSelector) error { return errors.New("i can't be nil") } + if nil == c.tempContainer { + return errors.New("Ioc container is auto cleared, if you want use Get/Wire please use autowire tag to inject `gs.Context` ") + } + v := reflect.ValueOf(i) if v.Kind() != reflect.Ptr { return errors.New("i must be pointer") @@ -99,6 +103,15 @@ func (c *container) Get(i interface{}, selectors ...BeanSelector) error { // If the input is a constructor, it immediately executes that constructor and then performs property binding and dependency injection on the returned result. // In both cases, the function returns the actual value of the bean object after its execution is complete. func (c *container) Wire(objOrCtor interface{}, ctorArgs ...arg.Arg) (interface{}, error) { + + if objOrCtor == nil { + return nil, errors.New("objOrCtor can't be nil") + } + + if nil == c.tempContainer { + return nil, errors.New("Ioc container is auto cleared, if you want use Get/Wire please use autowire tag to inject `gs.Context` ") + } + b := NewBean(objOrCtor, ctorArgs...) stack := newWiringStack(c.logger) if err := c.wireBean(b, stack); nil != err || len(stack.beans) > 0 { diff --git a/gs/gs_test.go b/gs/gs_test.go index 3f7f4d9f..f12f9257 100644 --- a/gs/gs_test.go +++ b/gs/gs_test.go @@ -2879,6 +2879,11 @@ func TestDestroyDependence(t *testing.T) { assert.Nil(t, err) } +// ContextAware injects the Context into a struct as the field GSContext. +type ContextAware struct { + GSContext Context `autowire:""` +} + type TContextAware struct { ContextAware } From cc3a4a6a08b5079aa6e27d2b096ba1217600f23e Mon Sep 17 00:00:00 2001 From: limpo1989 Date: Mon, 30 Oct 2023 18:03:40 +0800 Subject: [PATCH 2/2] Fix data-race on TestContextGetWire --- gs/app_test.go | 48 ------------------------------------------------ gs/gs_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/gs/app_test.go b/gs/app_test.go index 84936777..0e214746 100644 --- a/gs/app_test.go +++ b/gs/app_test.go @@ -80,51 +80,3 @@ func TestConfig(t *testing.T) { defer app.Shutdown("run test end") }) } - -func TestContextGetWire(t *testing.T) { - - type GetObject struct { - Name string `value:"${app.name}"` - } - - type ContextAware struct { - Ctx Context `autowire:""` - } - - var appCtx Context - - app := NewApp() - app.Property("app.name", "testapp") - app.Object(new(ContextAware)) - getbd := app.Provide(func(ctx Context) *GetObject { - appCtx = ctx - return &GetObject{} - }) - - go func() { - if err := app.Run(); nil != err { - panic(err) - } - }() - - time.Sleep(200 * time.Millisecond) - - t.Run("Context#Get", func(t *testing.T) { - var getObj *GetObject - err := appCtx.Get(&getObj) - assert.Nil(t, err) - assert.Equal(t, getObj, getbd.Interface()) - }) - - t.Run("Context#Wire", func(t *testing.T) { - - type WireObject struct { - Get *GetObject `autowire:""` - } - - wireObj, err := appCtx.Wire(new(WireObject)) - assert.Nil(t, err) - assert.Equal(t, wireObj.(*WireObject).Get, getbd.Interface()) - }) - -} diff --git a/gs/gs_test.go b/gs/gs_test.go index f12f9257..d7f8b2da 100644 --- a/gs/gs_test.go +++ b/gs/gs_test.go @@ -3038,3 +3038,48 @@ func TestConfiguration(t *testing.T) { }) } + +func TestContextGetWire(t *testing.T) { + + type GetObject struct { + Name string `value:"${app.name}"` + } + + type ContextAware struct { + Ctx Context `autowire:""` + } + + var appCtx Context + + c := New() + c.Properties().Set("app.name", "testapp") + c.Object(new(ContextAware)) + getbd := c.Provide(func(ctx Context) *GetObject { + appCtx = ctx + return &GetObject{} + }) + + err := c.Refresh() + assert.Nil(t, err) + + t.Run("Context#Get", func(t *testing.T) { + var getObj *GetObject + err := appCtx.Get(&getObj) + assert.Nil(t, err) + assert.Equal(t, getObj, getbd.Interface()) + assert.Equal(t, getObj.Name, "testapp") + }) + + t.Run("Context#Wire", func(t *testing.T) { + + type WireObject struct { + Get *GetObject `autowire:""` + } + + wireObj, err := appCtx.Wire(new(WireObject)) + assert.Nil(t, err) + assert.Equal(t, wireObj.(*WireObject).Get, getbd.Interface()) + assert.Equal(t, wireObj.(*WireObject).Get.Name, "testapp") + }) + +}