【发布时间】:2021-09-30 21:06:49
【问题描述】:
我正在使用github.com/google/wire 在我正在处理的an open source example project 中进行依赖注入。
我在一个名为interfaces的包中有以下接口:
type LoginService interface {
Login(email, password) (*LoginResult, error)
}
type JWTService interface {
Generate(user *models.User) (*JWTGenerateResult, error)
Validate(tokenString string) (*JWTValidateResult, error)
}
type UserDao interface {
ByEmail(email string) (*models.User, error)
}
我的实现看起来像这样:
type LoginServiceImpl struct {
jwt interfaces.JWTService
dao interfaces.UserDao
logger *zap.Logger
}
func NewLoginService(jwt interfaces.JWTService, dao interfaces.UserDao, \
logger *zap.Logger) *LoginServiceImpl {
return &LoginServiceImpl{jwt: jwt, dao: dao, logger: logger }
}
type JWTServiceImpl struct {
key [32]byte
logger *zap.Logger
}
func NewJWTService(key [32]byte, logger *zap.Logger) (*JWTServiceImpl, error) {
r := JWTServiceImpl {
key: key,
logger: logger,
}
if !r.safe() {
return nil, fmt.Errorf("unable to create JWT service, unsafe key: %s", err)
}
return &r, nil
}
type UserDaoImpl struct {
db: *gorm.DB
logger: *zap.Logger
}
func NewUserDao(db *gorm.DB, logger *zap.Logger) *UserDao {
return &UserDaoImpl{ db: db, logger: logger }
}
我将在这里排除其他工厂函数和实现,因为它们看起来都非常相似。它们可能会返回错误或绝对可靠。
我还有另一个有趣的工厂用于创建数据库连接,我将只展示接口而不是实现:
func Connect(config interfaces.MySQLConfig) (*gorm.DB, error) { /* ... */ }
现在,解决问题。在我的命令行入口点中,我正在创建一个记录器:
logger, err := zap.NewDevelopment()
对于上面的每个工厂方法,我需要提供一个记录器而不是同一个记录器实例,就像这些方法调用如下:
logger, err := zap.NewDevelopment()
// check err
db, err := database.Connect(config)
// check err
userDao := dao.NewUserDao(db, logger.Named("dao.user"))
jwtService, err := service.NewJWTService(jwtKey)
// check err
loginService := service.NewLoginService(jwtService, userDao, logger.Named("service.login"))
我的wire.ProviderSet 结构如下所示:
wire.NewSet(
wire.Bind(new(interfaces.LoginService), new(*service.LoginServiceImpl)),
wire.Bind(new(interfaces.JWTService), new(*service.JWTServiceImpl)),
wire.Bind(new(interfaces.UserDao), new(*dao.UserDaoImpl)),
service.NewLoginService,
service.NewJWTService,
dao.NewUserDao,
database.Connect,
)
我已经阅读了用户指南、教程和最佳实践,但我似乎找不到将唯一的 zap.Logger 路由到这些工厂方法中的每一个,并随机路由 [32]byte 的方法用于 JWT 服务。
由于我的根记录器不是在编译时创建的,而且这些工厂方法中的每一个都需要自己独特的记录器,我如何告诉wire 将这些实例绑定到相应的工厂方法?我很难理解如何将相同类型的自定义实例路由到不同的工厂方法。
总结:
Wire 似乎倾向于在编译时做所有事情,将依赖注入配置存储在静态包级变量中。对于我的大多数用例来说,这没问题。
对于我的其余用例,我需要在运行依赖注入之前手动创建一些实例,并能够将各种
*zap.Logger实例路由到需要它的每个服务。基本上,我需要
wire做services.NewUserDao(Connect(mysqlConfig), logger.Named("dao.user"),但我不知道如何在wire中表达这一点,并在运行时将变量与wire的编译时方法合并。
如何在wire 中执行此操作?
【问题讨论】:
-
您可以尝试将其缩小为单个可执行文件吗?即使您有多个问题。
-
简而言之:“我需要构建一个
wire集合并将实时实例路由到依赖注入到我的工厂方法中,而不仅仅是编译时工厂和结构” -
@mh-cbon 我已经更新了我的问题,最后有一个简短的总结,详细说明了问题以及我需要做什么。