mengstack-website/guide/dependency-injection.md
SoftUnis ecb29e0aa4 初始化 MengStack 官方网站仓库
包含 VitePress 文档站完整源码及全新自定义首页设计:
- 自定义首页组件 (Home.vue):Hero + 终端动效 + 核心能力 + 架构展示 + 快速开始 + CTA
- 自定义 Layout.vue:首页/文档页布局切换
- 金铜色品牌主题样式
- 完整文档页面(指南、API、更新日志、演示、社区)
- SEO 配置(sitemap、robots、meta 标签)
2026-10-02 23:37:25 +08:00

2.5 KiB
Raw Blame History

依赖注入

MengStack 使用 uber-go/fx 进行依赖注入,自动管理组件的生命周期和依赖关系。

为什么用依赖注入?

没有 DI 框架时,组装应用需要手动 wiring:

// 手动 wiring — 容易遗漏,难以维护
db := database.New(cfg.DB)
rdb := cache.New(cfg.Redis)
repo := infrastructure.NewUserRepo(db)
svc := application.NewService(repo, rdb, cfg.JWT)
handler := interfaces.NewHandler(svc)

使用 fx 后,依赖关系由框架自动解析:

// fx 自动解析依赖
fx.Provide(
    database.New,
    cache.New,
    application.NewService,
    interfaces.NewHandler,
)

fx.Module 组织

每个模块通过 fx.Module 声明自己的依赖:

// internal/modules/auth/interfaces/module.go
var Module = fx.Module("auth",
    fx.Provide(
        infrastructure.NewUserRepository,
        infrastructure.NewTokenRepository,
        application.NewService,
        NewHandler,
        NewAuthMiddleware,
        SetupRoutes,
    ),
)

主应用组装所有模块:

// internal/app/app.go
func NewApp() *fx.App {
    return fx.New(
        fx.Provide(config.Load, logger.New),
        database.Module,
        cache.Module,
        authinterfaces.Module,
        Module,
    )
}

生命周期管理

fx 自动管理组件的启动和停止顺序:

func newServer(lc fx.Lifecycle, engine *gin.Engine) *http.Server {
    srv := &http.Server{Addr: ":2222", Handler: engine}

    lc.Append(fx.Hook{
        OnStart: func(ctx context.Context) error {
            go srv.ListenAndServe()
            return nil
        },
        OnStop: func(ctx context.Context) error {
            return srv.Shutdown(ctx)
        },
    })

    return srv
}

fx 会确保:

  • OnStart 按依赖顺序执行(先数据库,后应用)
  • OnStop 按逆序执行(先应用,后数据库)

参数注入

通过函数参数声明依赖,fx 自动注入:

func newEngine(
    cfg *config.Config,      // fx 自动提供
    log *zap.Logger,         // fx 自动提供
    db *gorm.DB,             // fx 自动提供
    rdb *redis.Client,       // fx 自动提供
    authHandler *Handler,    // fx 自动提供
    authMW gin.HandlerFunc,  // fx 自动提供
) *gin.Engine {
    // ...
}

最佳实践

  1. 构造函数注入:通过 fx.Provide 注册构造函数
  2. 接口传递:尽量传递接口而非具体实现
  3. 模块隔离:每个业务模块声明自己的 fx.Module
  4. 避免全局状态:所有依赖通过注入获取