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
5543Go-Spring 使用 Go Modules 管理依赖,安装非常简单:
5644
@@ -66,7 +54,7 @@ Go-Spring 的核心理念之一就是**开箱即用**。下面通过两个简单
6654
6755``` go
6856func 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
9381func 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
119107func (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
222186Go-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{}) // 注册结构体实例
235197gs.Provide (NewService) // 使用构造函数注册
236198gs.Provide (NewRepo, ValueArg (" db" )) // 构造函数带参数
237199gs.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
286243gs.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
307262gs.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
360311Go-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
385334Go-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
435384gs.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})
441390gs.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
524473func (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
584533func (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