Skip to content

Commit 0a4163e

Browse files
lvan100lianghuan
authored andcommitted
update README.md
1 parent 817d245 commit 0a4163e

File tree

1 file changed

+86
-137
lines changed

1 file changed

+86
-137
lines changed

README_CN.md

Lines changed: 86 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,40 @@
55
<img src="https://img.shields.io/github/go-mod/go-version/go-spring/spring-core" alt="go-version"/>
66
<img src="https://img.shields.io/github/v/release/go-spring/spring-core?include_prereleases" alt="release"/>
77
<img src="https://codecov.io/gh/go-spring/spring-core/branch/main/graph/badge.svg" alt="test-coverage"/>
8+
<br/>
89
</div>
910

11+
[English](README.md)
12+
1013
**Go-Spring** 是一个功能强大、使用方便的 Go 应用开发框架,其灵感来源于 Java 生态中的 Spring 和 Spring Boot,
1114
它的设计目标是将 Java 世界中的优秀开发理念无缝迁移到 Go 语言中,从而提升开发效率、增强模块可复用性、提高代码可维护性。
1215

1316
它为 Go 应用带来了类似 Spring Boot 的体验,提供自动配置、依赖注入、配置热更新、条件注入、生命周期管理、微服务支持等功能,
1417
力求“一站式”解决实际开发问题。同时,它又高度兼容 Go 标准库,延续了 Go 一贯的简洁与高性能,特别适合构建现代 Go 微服务系统。
1518

16-
### 🌟 框架亮点
17-
18-
-**秒级启动**
19-
利用 Go 的 `init()` 机制实现 Bean 主动注册,省去运行时扫描,提升应用启动速度。
20-
21-
- 🧩 **极致易用**
22-
支持结构体标签注入和链式 API 配置,开发者无需编写复杂的模板代码,快速上手开发。
23-
24-
- 🔄 **配置热更新**
25-
支持动态属性绑定与运行时刷新,无需重启应用即可实时生效,适用于灰度发布、动态调整等场景。
19+
## 🌟 框架亮点
2620

27-
- 📦 **微服务原生支持**
28-
内置标准 HTTP Server 启动器与注册机制,具备丰富的生命周期钩子,构建微服务更高效。
21+
1.**秒级启动:** 利用 Go 的 `init()` 机制实现 Bean 主动注册,省去运行时扫描,提升应用启动速度。
22+
2. 🧩 **极致易用:** 支持结构体标签注入和链式 API 配置,开发者无需编写复杂的模板代码,快速上手开发。
23+
3. 🔄 **配置热更新:** 支持属性绑定与运行时刷新,无需重启应用即可实时生效,适用于灰度发布、动态调整等场景。
24+
4. 📦 **微服务原生支持:** 内置标准 HTTP Server 启动器与注册机制,具备丰富的生命周期钩子,构建微服务更高效。
25+
5. 🧪 **完善的测试能力:** 提供 Mock 与单元测试工具,便于开发者编写高质量、可验证的测试用例。
26+
6. 🔍 **运行时零反射:** 框架仅在启动时使用反射完成 Bean 构造与注入,运行时不依赖反射,保障性能表现。
27+
7. 💡 **零侵入式设计:** 框架对业务代码无强依赖,使用者无需实现特定接口即可被管理,保持代码干净、易迁移。
2928

30-
- 🧪 **完善的测试能力**
31-
提供 Mock 与单元测试工具,便于开发者编写高质量、可验证的测试用例。
29+
## ✨ 核心功能
3230

33-
- 🔍 **运行时零反射**
34-
框架仅在启动时使用反射完成 Bean 构造与注入,运行时不依赖反射,保障性能表现。
31+
1. **🚀 自动配置:** 自动加载配置文件、构建 Bean,支持环境隔离与多文件合并。
32+
2. **⚙️ 依赖注入:** 结构体字段注入、构造函数注入、接口注入等多种形式。
33+
3. **🌀 配置热更新:** 支持运行时刷新配置,动态响应配置变更。
34+
4. **🔄 生命周期管理:** 支持自定义初始化与销毁函数,并提供优雅的退出机制。
35+
5. **🔌 服务注册:** 原生兼容 HTTP,支持自定义 Server 模型。
36+
6. **🧪 条件注入:** 支持按属性、环境、Bean 存在与否等灵活注入控制。
37+
7. **🔧 Bean 注册管理:** 提供灵活的 Bean 注册与构建 API。
38+
8. **📡 微服务支持:** 内建 Job、Runner、Server 三种运行模型,助力构建多形态微服务架构。
39+
9. **🧪 单元测试支持:** 内置 Mock、自动注入等机制,支持高质量测试开发。
3540

36-
- 💡 **零侵入式设计**
37-
框架对业务代码无强依赖,使用者无需实现特定接口即可被管理,保持代码干净、易迁移。
38-
39-
## ✨ 核心功能总览
40-
41-
| 功能 | 描述 |
42-
|--------------|------------------------------------------|
43-
| 🚀 自动配置 | 自动加载配置文件、构建 Bean,支持环境隔离与多文件合并 |
44-
| ⚙️ 依赖注入 | 结构体字段注入、构造函数注入、接口注入等多种形式 |
45-
| 🌀 配置热更新 | 支持运行时刷新配置,动态响应配置变更 |
46-
| 🔄 生命周期管理 | 支持自定义初始化与销毁函数,并提供优雅的退出机制 |
47-
| 🔌 服务注册 | 原生兼容 HTTP,支持自定义 Server 模型 |
48-
| 🧪 条件注入 | 支持按属性、环境、Bean 存在与否等灵活注入控制 |
49-
| 🔧 Bean 注册管理 | 提供灵活的 Bean 注册与构建 API |
50-
| 📡 微服务支持 | 内建 Job、Runner、Server 三种运行模型,助力构建多形态微服务架构 |
51-
| 🧪 单元测试支持 | 内置 Mock、自动注入等机制,支持高质量测试开发 |
52-
53-
## 📦 安装
41+
## 📦 安装方式
5442

5543
Go-Spring 使用 Go Modules 管理依赖,安装非常简单:
5644

@@ -66,7 +54,7 @@ Go-Spring 的核心理念之一就是**开箱即用**。下面通过两个简单
6654

6755
```go
6856
func main() {
69-
http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
57+
http.HandleFunc("/echo", func (w http.ResponseWriter, r *http.Request) {
7058
_, _ = w.Write([]byte("hello world!"))
7159
})
7260
gs.Run()
@@ -93,14 +81,14 @@ curl http://127.0.0.1:9090/echo
9381
func init() {
9482
// Register the Service struct as a bean.
9583
gs.Object(&Service{})
96-
84+
9785
// Provide a [*http.ServeMux] as a bean.
98-
gs.Provide(func(s *Service) *http.ServeMux {
86+
gs.Provide(func (s *Service) *http.ServeMux {
9987
http.HandleFunc("/echo", s.Echo)
10088
http.HandleFunc("/refresh", s.Refresh)
10189
return http.DefaultServeMux
10290
})
103-
91+
10492
sysconf.Set("start-time", time.Now().Format(timeLayout))
10593
sysconf.Set("refresh-time", time.Now().Format(timeLayout))
10694
}
@@ -118,8 +106,8 @@ type Service struct {
118106

119107
func (s *Service) Echo(w http.ResponseWriter, r *http.Request) {
120108
str := fmt.Sprintf("start-time: %s refresh-time: %s",
121-
s.StartTime.Format(timeLayout),
122-
s.RefreshTime.Value().Format(timeLayout))
109+
s.StartTime.Format(timeLayout),
110+
s.RefreshTime.Value().Format(timeLayout))
123111
_, _ = w.Write([]byte(str))
124112
}
125113

@@ -151,28 +139,22 @@ curl http://127.0.0.1:9090/echo
151139
# 输出中的 refresh-time 已更新
152140
```
153141

154-
## 🔧 配置管理
142+
### 更多示例
155143

156-
Go-Spring 提供了灵活强大的配置加载机制,支持从多种来源获取配置项,轻松满足多环境、多部署场景的需求
144+
访问 [gs/examples](gs/examples) 查看更多示例
157145

158-
### 🔍 支持的配置来源
146+
## 🔧 配置管理
159147

160-
| 来源类型 | 描述 |
161-
|-----------|---------------------------------------------|
162-
| `sysconf` | 内存配置,适用于测试或临时注入 |
163-
| 本地文件 | 支持 `.yaml``.yml``.properties``.toml` 等格式 |
164-
| 远程文件 | 通过远程 URL 拉取配置,支持定时轮询更新 |
165-
| 环境变量 | 读取系统环境变量作为配置项 |
166-
| 命令行参数 |`--key=value` 形式注入参数,覆盖配置文件与环境变量 |
148+
Go-Spring 提供了灵活强大的配置加载机制,支持从多种来源获取配置项,轻松满足多环境、多部署场景的需求。
167149

168-
### 🔗 配置加载优先级(从高到低)
150+
1. **命令行参数(最高优先级)**`-Dkey=value` 形式注入参数
151+
2. **环境变量** 读取系统环境变量作为配置项
152+
3. **远程文件** 获取远程配置文件,支持定时轮询更新
153+
4. **本地文件** 支持格式:`.yaml`/`.yml`/`.properties`/`.toml`
154+
5. **`sysconf`内存配置** 适用于测试或临时注入
155+
6. **默认值(最低优先级)** 通过结构体标签设置
169156

170-
1. 命令行参数
171-
2. 环境变量
172-
3. 远程配置文件
173-
4. 本地配置文件
174-
5. `sysconf` 内存设置
175-
6. 默认值(通过结构体标签设置)
157+
> 注:优先级从1到6依次降低,高优先级的配置会覆盖低优先级的配置。
176158
177159
#### 示例配置文件:
178160

@@ -194,24 +176,6 @@ type AppConfig struct {
194176
}
195177
```
196178

197-
### 🌡️ 热更新配置
198-
199-
Go-Spring 支持热更新,结合 `gs.Dync[T]` 类型,可以实时响应配置变化,而无需重启服务。
200-
201-
```go
202-
type AppInfo struct {
203-
Version gs.Dync[string] `value:"${app.version}"`
204-
}
205-
```
206-
207-
运行时触发刷新:
208-
209-
```go
210-
_ = gs.RefreshProperties()
211-
```
212-
213-
刷新后,所有 `gs.Dync[T]` 绑定字段会自动更新。
214-
215179
## 🔧 Bean 管理
216180

217181
在 Go-Spring 中,**Bean 是应用的核心构建单元**。框架采用显式注册 + 标签声明的模式,结合灵活的条件装配,
@@ -221,12 +185,10 @@ _ = gs.RefreshProperties()
221185

222186
Go-Spring 提供多种方式注册 Bean:
223187

224-
| 方法 | 描述 |
225-
|-----------------------------|--------------------------|
226-
| `gs.Object(obj)` | 将已有对象注册为 Bean |
227-
| `gs.Provide(ctor, args...)` | 使用构造函数生成并注册 Bean |
228-
| `gs.Register(bd)` | 注册完整 Bean 定义,适合底层封装或高级用法 |
229-
| `gs.GroupRegister(fn)` | 批量注册多个 Bean,常用于模块初始化等场景 |
188+
- **`gs.Object(obj)`** - 将已有对象注册为 Bean
189+
- **`gs.Provide(ctor, args...)`** - 使用构造函数生成并注册 Bean
190+
- **`gs.Register(bd)`** - 注册完整 Bean 定义(适合底层封装或高级用法)
191+
- **`gs.GroupRegister(fn)`** - 批量注册多个 Bean(常用于模块初始化等场景)
230192

231193
#### 示例
232194

@@ -235,12 +197,7 @@ gs.Object(&Service{}) // 注册结构体实例
235197
gs.Provide(NewService) // 使用构造函数注册
236198
gs.Provide(NewRepo, ValueArg("db")) // 构造函数带参数
237199
gs.Register(gs.NewBean(NewService)) // 完整定义注册
238-
```
239-
240-
批量注册:
241-
242-
```go
243-
gs.GroupRegister(func(p Properties) []*BeanDefinition {
200+
gs.GroupRegister(func (p Properties) []*BeanDefinition { // 批量注册
244201
return []*BeanDefinition{
245202
gs.NewBean(NewUserService),
246203
gs.NewBean(NewOrderService),
@@ -284,20 +241,18 @@ gs.Provide(NewService)
284241

285242
```go
286243
gs.Provide(NewService,
287-
TagArg("${log.level}"), // 从配置注入
244+
TagArg("${log.level}"), // 从配置注入
288245
ValueArg("some static value"), // 直接值注入
289246
BindArg(parseFunc, "arg"), // option 函数注入
290247
)
291248
```
292249

293250
可用的参数类型:
294251

295-
| 参数类型 | 描述 |
296-
|---------------------|-------------|
297-
| `TagArg(tag)` | 从配置中提取值 |
298-
| `ValueArg(value)` | 使用固定值 |
299-
| `IndexArg(i, v)` | 按参数位置注入 |
300-
| `BindArg(fn, args)` | option 函数注入 |
252+
- **`TagArg(tag)`**:从配置中提取值
253+
- **`ValueArg(value)`**:使用固定值
254+
- **`IndexArg(i, v)`**:按参数位置注入
255+
- **`BindArg(fn, args)`**:通过 option 函数注入
301256

302257
### 🔄 Bean 生命周期配置
303258

@@ -306,8 +261,8 @@ gs.Provide(NewService,
306261
```go
307262
gs.Provide(NewService).
308263
Name("myService").
309-
Init(func(s *Service) { ... }).
310-
Destroy(func(s *Service) { ... }).
264+
Init(func (s *Service) { ... }).
265+
Destroy(func (s *Service) { ... }).
311266
Condition(OnProperty("feature.enabled")).
312267
DependsOn("logger").
313268
Export((*MyInterface)(nil)).
@@ -316,17 +271,15 @@ gs.Provide(NewService).
316271

317272
配置项说明:
318273

319-
| 方法 | 说明 |
320-
|------------------|-----------------------|
321-
| `Name(string)` | 指定 Bean 名称 |
322-
| `Init(fn)` | 初始化函数(支持方法名字符串) |
323-
| `Destroy(fn)` | 销毁函数(支持方法名字符串) |
324-
| `DependsOn(...)` | 指定依赖的其他 Bean 名称 |
325-
| `Condition(...)` | 条件装配控制(见下一节) |
326-
| `Export(...)` | 将 Bean 作为接口导出,支持多接口导出 |
327-
| `AsRunner()` | 注册为 `Runner`,运行在主线程 |
328-
| `AsJob()` | 注册为后台任务 Job |
329-
| `AsServer()` | 注册为服务 Server(需实现接口) |
274+
- **`Name(string)`**:指定 Bean 名称
275+
- **`Init(fn)`**:初始化函数(支持方法名字符串)
276+
- **`Destroy(fn)`**:销毁函数(支持方法名字符串)
277+
- **`DependsOn(...)`**:指定依赖的其他 Bean 名称
278+
- **`Condition(...)`**:条件装配控制(见下一节)
279+
- **`Export(...)`**:将 Bean 作为接口导出,支持多接口导出
280+
- **`AsRunner()`**:注册为 `Runner`,运行在主线程
281+
- **`AsJob()`**:注册为后台任务 Job
282+
- **`AsServer()`**:注册为服务 Server(需实现接口)
330283

331284
## ⚙️ 条件注入(Condition)
332285

@@ -337,14 +290,12 @@ Go-Spring 支持基于条件的 Bean 注入机制,这使得组件可以根据
337290

338291
### 🎯 支持的条件类型
339292

340-
| 条件方法 | 描述 |
341-
|--------------------------------------|-------------------------|
342-
| `OnProperty("key")` | 指定配置 key 存在并有值时激活 |
343-
| `OnMissingProperty("key")` | 指定配置 key 不存在时激活 |
344-
| `OnBean[Type]("name")` | 当指定类型/名称的 Bean 存在时激活 |
345-
| `OnMissingBean[Type]("name")` | 当指定类型/名称的 Bean 不存在时激活 |
346-
| `OnSingleBean[Type]("name")` | 当指定类型/名称的 Bean 是唯一实例时激活 |
347-
| `OnFunc(func(ctx CondContext) bool)` | 自定义条件逻辑 |
293+
- **`OnProperty("key")`**:当指定配置 key 存在且有值时激活
294+
- **`OnMissingProperty("key")`**:当指定配置 key 不存在时激活
295+
- **`OnBean[Type]("name")`**:当指定类型/名称的 Bean 存在时激活
296+
- **`OnMissingBean[Type]("name")`**:当指定类型/名称的 Bean 不存在时激活
297+
- **`OnSingleBean[Type]("name")`**:当指定类型/名称的 Bean 是唯一实例时激活
298+
- **`OnFunc(func(ctx CondContext) bool)`**:使用自定义条件逻辑判断是否激活
348299

349300
### 🔍 示例:按属性控制注册
350301

@@ -359,12 +310,10 @@ gs.Provide(NewService).
359310

360311
Go-Spring 支持组合多个条件,构建更复杂的判断逻辑:
361312

362-
| 方法 | 描述 |
363-
|-------------|-------------|
364-
| `Not(...)` | 条件取反 |
365-
| `And(...)` | 所有条件都满足时成立 |
366-
| `Or(...)` | 任一条件满足即成立 |
367-
| `None(...)` | 所有条件都不满足时成立 |
313+
- **`Not(...)`** - 对条件取反
314+
- **`And(...)`** - 所有条件都满足时成立
315+
- **`Or(...)`** - 任一条件满足即成立
316+
- **`None(...)`** - 所有条件都不满足时成立
368317

369318
#### 示例:组合条件控制 Bean 激活
370319

@@ -380,7 +329,7 @@ gs.Provide(NewService).
380329

381330
该 Bean 会在 `feature.enabled` 开启且未注册 `*DeprecatedService` 时启用。
382331

383-
## 🔁 配置动态刷新(热更新)
332+
## 🔁 配置动态刷新
384333

385334
Go-Spring 内置了轻量的配置热更新能力。通过 `gs.Dync[T]` 类型与 `gs.RefreshProperties()` 方法的组合,
386335
可以实现应用在运行中动态响应配置变化,无需重启。
@@ -389,7 +338,7 @@ Go-Spring 内置了轻量的配置热更新能力。通过 `gs.Dync[T]` 类型
389338

390339
### 🌡 使用方式
391340

392-
#### 1. 使用 `gs.Dync[T]` 声明动态字段
341+
1. 使用 `gs.Dync[T]` 声明动态字段
393342

394343
通过泛型类型 `gs.Dync[T]` 包装字段,即可监听配置变化并自动更新:
395344

@@ -401,7 +350,7 @@ type Config struct {
401350

402351
> 调用时通过 `.Value()` 获取当前值,框架在配置变更时会自动更新该值。
403352
404-
#### 2. 调用 `gs.RefreshProperties()` 手动触发刷新
353+
2. 调用 `gs.RefreshProperties()` 手动触发刷新
405354

406355
在配置发生变化后,调用此方法可以让所有动态字段立即更新:
407356

@@ -433,15 +382,15 @@ func RefreshVersion(w http.ResponseWriter, r *http.Request) {
433382

434383
```go
435384
gs.Object(&App{})
436-
gs.Provide(func(app *App) *http.ServeMux {
385+
gs.Provide(func (app *App) *http.ServeMux {
437386
http.Handle("/", app)
438387
http.HandleFunc("/refresh", RefreshVersion)
439388
return http.DefaultServeMux
440389
})
441390
gs.Run()
442391
```
443392

444-
访问 `/` 会输出当前版本,访问 `/refresh` 后,再次访问 `/` 即可看到更新后的版本号。
393+
运行程序后,访问 `/` 会输出当前版本,访问 `/refresh` 后,再次访问 `/` 即可看到更新后的版本号。
445394

446395
## 🖥️ 自定义 Server
447396

@@ -468,7 +417,7 @@ type ReadySignal interface {
468417
}
469418
```
470419

471-
用于协调服务“何时准备好”。你可以在 `ListenAndServe` 中等到主流程触发启动完成信号,然后正式对外提供服务。
420+
你可以在 `ListenAndServe` 中等到主流程触发启动完成信号,然后正式对外提供服务。
472421

473422
### 🛠 示例:标准库 HTTP Server 接入
474423

@@ -523,7 +472,7 @@ func (s *GRPCServer) ListenAndServe(sig gs.ReadySignal) error {
523472

524473
func (s *GRPCServer) Shutdown(ctx context.Context) error {
525474
stopped := make(chan struct{})
526-
go func() {
475+
go func () {
527476
s.svr.GracefulStop()
528477
close(stopped)
529478
}()
@@ -583,16 +532,16 @@ type Job struct{}
583532

584533
func (j *Job) Run(ctx context.Context) error {
585534
for {
586-
select {
587-
case <-ctx.Done():
588-
fmt.Println("job exit")
535+
select {
536+
case <-ctx.Done():
537+
fmt.Println("job exit")
538+
return nil
539+
default:
540+
if gs.Exiting() {
589541
return nil
590-
default:
591-
if gs.Exiting() {
592-
return nil
593-
}
594-
time.Sleep(300 * time.Millisecond)
595-
fmt.Println("job tick")
542+
}
543+
time.Sleep(300 * time.Millisecond)
544+
fmt.Println("job tick")
596545
}
597546
}
598547
}

0 commit comments

Comments
 (0)