Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,6 @@ Go-Spring provides multiple ways to register Beans:
- **`gs.Object(obj)`** - Registers an existing object as a Bean
- **`gs.Provide(ctor, args...)`** - Uses a constructor to generate and register a Bean
- **`gs.Register(bd)`** - Registers a complete Bean definition (suitable for low-level encapsulation or advanced usage)
- **`gs.GroupRegister(fn)`** - Batch registers multiple Beans (commonly used for module initialization and other
scenarios)

Example:

Expand All @@ -221,14 +219,6 @@ gs.Object(&Service{}) // Register a struct instance
gs.Provide(NewService) // Register using a constructor
gs.Provide(NewRepo, gs.ValueArg("db")) // Constructor with parameters
gs.Register(gs.NewBean(NewService)) // Complete definition registration

// Batch register multiple Beans
gs.GroupRegister(func (p conf.Properties) []*gs.BeanDefinition {
return []*gs.BeanDefinition{
gs.NewBean(NewUserService),
gs.NewBean(NewOrderService),
}
})
```

### 2️⃣ Injection Methods
Expand Down Expand Up @@ -317,11 +307,10 @@ feature toggles, and gray release scenarios.
### 🎯 Common Condition Types

- **`OnProperty("key")`**: Activates when the specified configuration key exists
- **`OnMissingProperty("key")`**: Activates when the specified configuration key does not exist
- **`OnBean[Type]("name")`**: Activates when a Bean of the specified type/name exists
- **`OnMissingBean[Type]("name")`**: Activates when a Bean of the specified type/name does not exist
- **`OnSingleBean[Type]("name")`**: Activates when a Bean of the specified type/name is the only instance
- **`OnFunc(func(ctx CondContext) bool)`**: Uses custom condition logic to determine activation
- **`OnFunc(func(ctx ConditionContext) bool)`**: Uses custom condition logic to determine activation

Example:

Expand Down
12 changes: 1 addition & 11 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ Go-Spring 提供多种方式注册 Bean:
- **`gs.Object(obj)`** - 将已有对象注册为 Bean
- **`gs.Provide(ctor, args...)`** - 使用构造函数生成并注册 Bean
- **`gs.Register(bd)`** - 注册完整 Bean 定义(适合底层封装或高级用法)
- **`gs.GroupRegister(fn)`** - 批量注册多个 Bean(常用于模块初始化等场景)

示例:

Expand All @@ -198,14 +197,6 @@ gs.Object(&Service{}) // 注册结构体实例
gs.Provide(NewService) // 使用构造函数注册
gs.Provide(NewRepo, gs.ValueArg("db")) // 构造函数带参数
gs.Register(gs.NewBean(NewService)) // 完整定义注册

// 批量注册多个 Bean
gs.GroupRegister(func (p conf.Properties) []*gs.BeanDefinition {
return []*gs.BeanDefinition{
gs.NewBean(NewUserService),
gs.NewBean(NewOrderService),
}
})
```

### 2️⃣ 注入方式
Expand Down Expand Up @@ -291,11 +282,10 @@ Go-Spring 借鉴 Spring 的 `@Conditional` 思想,实现了灵活强大的条
### 🎯 常用条件类型

- **`OnProperty("key")`**:当指定配置 key 存在时激活
- **`OnMissingProperty("key")`**:当指定配置 key 不存在时激活
- **`OnBean[Type]("name")`**:当指定类型/名称的 Bean 存在时激活
- **`OnMissingBean[Type]("name")`**:当指定类型/名称的 Bean 不存在时激活
- **`OnSingleBean[Type]("name")`**:当指定类型/名称的 Bean 是唯一实例时激活
- **`OnFunc(func(ctx CondContext) bool)`**:使用自定义条件逻辑判断是否激活
- **`OnFunc(func(ctx ConditionContext) bool)`**:使用自定义条件逻辑判断是否激活

示例:

Expand Down
2 changes: 1 addition & 1 deletion conf/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ func getSlice(p Properties, et reflect.Type, param BindParam) (Properties, error
r := New()
for i, s := range arrVal {
k := fmt.Sprintf("%s[%d]", param.Key, i)
_ = r.Set(k, s) // always no error
_ = r.Set(k, s, 0) // always no error
}
return r, nil
}
Expand Down
16 changes: 9 additions & 7 deletions conf/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,20 +537,22 @@ func TestProperties_Bind(t *testing.T) {
p, err := conf.Load("./testdata/config/app.yaml")
assert.That(t, err).Nil()

err = p.Set("extra.intsV0", "")
fileID := p.AddFile("bind_test.go")

err = p.Set("extra.intsV0", "", fileID)
assert.That(t, err).Nil()
err = p.Set("extra.intsV2", "1,2,3")
err = p.Set("extra.intsV2", "1,2,3", fileID)
assert.That(t, err).Nil()
err = p.Set("prefix.extra.intsV2", "1,2,3")
err = p.Set("prefix.extra.intsV2", "1,2,3", fileID)
assert.That(t, err).Nil()

err = p.Set("extra.mapV2.a", "1")
err = p.Set("extra.mapV2.a", "1", fileID)
assert.That(t, err).Nil()
err = p.Set("extra.mapV2.b", "2")
err = p.Set("extra.mapV2.b", "2", fileID)
assert.That(t, err).Nil()
err = p.Set("prefix.extra.mapV2.a", "1")
err = p.Set("prefix.extra.mapV2.a", "1", fileID)
assert.That(t, err).Nil()
err = p.Set("prefix.extra.mapV2.b", "2")
err = p.Set("prefix.extra.mapV2.b", "2", fileID)
assert.That(t, err).Nil()

var c DBConfig
Expand Down
57 changes: 26 additions & 31 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,18 @@ package conf
import (
"errors"
"fmt"
"maps"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"time"

"github.com/go-spring/barky"
"github.com/go-spring/spring-core/conf/reader/json"
"github.com/go-spring/spring-core/conf/reader/prop"
"github.com/go-spring/spring-core/conf/reader/toml"
"github.com/go-spring/spring-core/conf/reader/yaml"
"github.com/go-spring/spring-core/conf/storage"
"github.com/go-spring/spring-core/util"
"github.com/spf13/cast"
)

Expand Down Expand Up @@ -222,13 +221,13 @@ var _ Properties = (*MutableProperties)(nil)
// but it costs more CPU time when getting properties because it reads property node
// by node. So `conf` uses a tree to strictly verify and a flat map to store.
type MutableProperties struct {
*storage.Storage
*barky.Storage
}

// New creates empty *MutableProperties.
func New() *MutableProperties {
return &MutableProperties{
Storage: storage.NewStorage(),
Storage: barky.NewStorage(),
}
}

Expand All @@ -247,47 +246,30 @@ func Load(file string) (*MutableProperties, error) {
if err != nil {
return nil, err
}
return Map(m), nil
p := New()
_ = p.merge(barky.FlattenMap(m), file)
return p, nil
}

// Map creates *MutableProperties from map.
func Map(m map[string]any) *MutableProperties {
p := New()
_ = p.merge(util.FlattenMap(m))
_, file, _, _ := runtime.Caller(1)
_ = p.merge(barky.FlattenMap(m), file)
return p
}

// merge flattens the map and sets all keys and values.
func (p *MutableProperties) merge(m map[string]string) error {
func (p *MutableProperties) merge(m map[string]string, file string) error {
fileID := p.AddFile(file)
for key, val := range m {
if err := p.Set(key, val); err != nil {
if err := p.Set(key, val, fileID); err != nil {
return err
}
}
return nil
}

// Data returns key-value pairs of the properties.
func (p *MutableProperties) Data() map[string]string {
m := make(map[string]string)
maps.Copy(m, p.RawData())
return m
}

// Keys returns keys of the properties.
func (p *MutableProperties) Keys() []string {
return util.OrderedMapKeys(p.RawData())
}

// Get returns key's value, using Def to return a default value.
func (p *MutableProperties) Get(key string, def ...string) string {
val, ok := p.RawData()[key]
if !ok && len(def) > 0 {
return def[0]
}
return val
}

// Resolve resolves string value that contains references to other
// properties, the references are defined by ${key:=def}.
func (p *MutableProperties) Resolve(s string) (string, error) {
Expand Down Expand Up @@ -338,5 +320,18 @@ func (p *MutableProperties) Bind(i any, tag ...string) error {

// CopyTo copies properties into another by override.
func (p *MutableProperties) CopyTo(out *MutableProperties) error {
return out.merge(p.RawData())
rawFile := p.RawFile()
newfile := make(map[string]int8)
oldFile := make([]string, len(rawFile))
for k, v := range rawFile {
oldFile[v] = k
newfile[k] = out.AddFile(k)
}
for key, v := range p.RawData() {
fileID := newfile[oldFile[v.File]]
if err := out.Set(key, v.Value, fileID); err != nil {
return err
}
}
return nil
}
4 changes: 3 additions & 1 deletion conf/reader/prop/prop.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ func Read(b []byte) (map[string]any, error) {

p := properties.NewProperties()
p.DisableExpansion = true
_ = p.Load(b, properties.UTF8) // always no error
if err := p.Load(b, properties.UTF8); err != nil {
return nil, err
}

ret := make(map[string]any)
for k, v := range p.Map() {
Expand Down
5 changes: 5 additions & 0 deletions conf/reader/prop/prop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ import (

func TestRead(t *testing.T) {

t.Run("error", func(t *testing.T) {
_, err := Read([]byte(`=1`))
assert.ThatError(t, err).Matches(`properties: Line 1: "1"`)
})

t.Run("basic type", func(t *testing.T) {
r, err := Read([]byte(`
empty=
Expand Down
136 changes: 0 additions & 136 deletions conf/storage/path.go

This file was deleted.

Loading