- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
一个Go编程语言的运行依赖注入库。依赖注入是更广泛的控制反转技术的一种形式。它用于增加程序的模块化并使其具有可扩展性.
type A struct {
Name string
}
func NewA() *A {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
name := "A-" + strconv.Itoa(r.Int())
return &A{Name: ls}
}
services := NewServiceCollection()
services.AddSingleton(NewA)
//serviceCollection.AddSingletonByImplementsAndName("redis-master", NewRedis, new(abstractions.IDataSource))
//serviceCollection.AddTransientByImplements(NewRedisClient, new(redis.IClient))
//serviceCollection.AddTransientByImplements(NewRedisHealthIndicator, new(health.Indicator))
serviceProvider := services.Build()
var env *A
_ = serviceProvider.GetService(&env) // used
依赖注入是更广泛的控制反转技术的一种形式。它用于增加程序的模块化并使其具有可扩展性.
go get -u github.com/yoyofxteam/dependencyinjection@v1.0.1
首先,我们需要创建两个基本类型:http。服务器和http.ServeMux。让我们创建一个简单的构造函数来初始化它
// NewServer creates a http server with provided mux as handler.
func NewServer(mux *http.ServeMux) *http.Server {
return &http.Server{
Handler: mux,
}
}
// NewServeMux creates a new http serve mux.
func NewServeMux() *http.ServeMux {
return &http.ServeMux{}
}
支持的构造器签名形式如下
func([dep1, dep2, depN]) (result, [cleanup, error])
现在让我们来容器构建这些类型.
下面展示是Low API, 也可以用High API来构建
import (
di "github.com/yoyofxteam/dependencyinjection"
)
container := di.New(
// provide http server
di.Provide(NewServer),
// provide http serve mux
di.Provide(NewServeMux)
)
函数di. new()解析构造函数,编译依赖关系图并返回*di。用于交互的容器类型。如果无法编译,容器会出现恐慌.
我认为在应用程序初始化时而不是在运行时出现恐慌是很常见的.
我们可以从容器中提取构建的服务器。为此,定义提取类型的变量,并将变量指针传递给Extract函数.
如果未找到提取的类型或构建实例的过程导致错误,则提取返回错误。 如果没有错误发生,我们就可以使用这个变量,就像我们自己构建它一样.
// declare type variable
var server *http.Server
// extracting
err := container.Extract(&server)
if err != nil {
// check extraction error
}
server.ListenAndServe()
请注意,默认情况下,容器作为单例创建实例 , 但也可使用Provide做行为上的改变.
## Invocation
作为提取的替代方法,我们可以使用Invoke()函数。它解析函数依赖并调用函数。调用函数可能返回可选错误。
```golang
// NewServer creates a http server with provided mux as handler.
func NewServer(handler http.Handler) *http.Server {
return &http.Server{
Handler: handler,
}
}
对于一个容器来说,要知道作为http的实现。处理程序是必须使用的,我们使用选项di.As()。这个选项的参数必须是一个指向接口的指针,比如new(Endpoint).
这种语法可能看起来很奇怪,但我还没有找到更好的方式来指定接口.
修改依赖注入容器初始化代码
container := inject.New(
// provide http server
inject.Provide(NewServer),
// provide http serve mux as http.Handler interface
inject.Provide(NewServeMux, inject.As(new(http.Handler)))
)
现在容器使用提供*http。ServeMux作为http。服务器构造函数中的处理程序。使用接口有助于编写更多可测试的代码.
容器自动将接口的所有实现分组到[] 组。例如,提供with inject.As(new(http.Handler))自动创建一个组[]http.Handler.
让我们使用这个特性添加一些http控制器。控制器有典型的行为。它正在注册路由。首先,将为它创建一个接口.
// Controller is an interface that can register its routes.
type Controller interface {
RegisterRoutes(mux *http.ServeMux)
}
现在我们将编写控制器并实现控制器接口.
// OrderController is a http controller for orders.
type OrderController struct {}
// NewOrderController creates a auth http controller.
func NewOrderController() *OrderController {
return &OrderController{}
}
// RegisterRoutes is a Controller interface implementation.
func (a *OrderController) RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("/orders", a.RetrieveOrders)
}
// Retrieve loads orders and writes it to the writer.
func (a *OrderController) RetrieveOrders(writer http.ResponseWriter, request *http.Request) {
// implementation
}
UserController 。
// UserController is a http endpoint for a user.
type UserController struct {}
// NewUserController creates a user http endpoint.
func NewUserController() *UserController {
return &UserController{}
}
// RegisterRoutes is a Controller interface implementation.
func (e *UserController) RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("/users", e.RetrieveUsers)
}
// Retrieve loads users and writes it using the writer.
func (e *UserController) RetrieveUsers(writer http.ResponseWriter, request *http.Request) {
// implementation
}
就像在这个接口的例子中,我们将使用inject.As()提供provide选项.
container := inject.New(
di.Provide(NewServer), // provide http server
di.Provide(NewServeMux), // provide http serve mux
// endpoints
di.Provide(NewOrderController, di.As(new(Controller))), // provide order controller
di.Provide(NewUserController, di.As(new(Controller))), // provide user controller
)
现在,我们可以在mux中使用控制器数组。参见更新后的代码
// NewServeMux creates a new http serve mux.
func NewServeMux(controllers []Controller) *http.ServeMux {
mux := &http.ServeMux{}
for _, controller := range controllers {
controller.RegisterRoutes(mux)
}
return mux
}
在某些情况下,一种类型有多个实例。例如两个数据库实例:master -用于写,slave -用于读.
// MasterDatabase provide write database access.
type MasterDatabase struct {
*Database
}
// SlaveDatabase provide read database access.
type SlaveDatabase struct {
*Database
}
第二种方法是使用带有di.WithName()提供选项的命名定义 。
// provide master database
di.Provide(NewMasterDatabase, di.WithName("master"))
// provide slave database
di.Provide(NewSlaveDatabase, di.WithName("slave"))
如果需要从容器中提取,请使用di.Name()提取选项.
var db *Database
container.Extract(&db, di.Name("master"))
如果需要在其他构造函数中提供命名定义,请使用di。参数嵌入.
// ServiceParameters
type ServiceParameters struct {
di.Parameter
// use `di` tag for the container to know that field need to be injected.
MasterDatabase *Database `di:"master"`
SlaveDatabase *Database `di:"slave"`
}
// NewService creates new service with provided parameters.
func NewService(parameters ServiceParameters) *Service {
return &Service{
MasterDatabase: parameters.MasterDatabase,
SlaveDatabase: parameters.SlaveDatabase,
}
}
// ServiceParameter
type ServiceParameter struct {
di.Parameter
StdOutLogger *Logger `di:"stdout"`
FileLogger *Logger `di:"file,optional"`
}
将依赖声明为可选的构造函数必须处理这些依赖不存在的情况.
如果需要在定义级别上指定一些参数,则可以使用 inject.ParameterBag provide option. 这是一个map[string]interface{},可以转换为di.ParameterBag类型.
// Provide server with parameter bag
di.Provide(NewServer, di.ParameterBag{
"addr": ":8080",
})
// NewServer create a server with provided parameter bag. Note: use di.ParameterBag type.
// Not inject.ParameterBag.
func NewServer(pb di.ParameterBag) *http.Server {
return &http.Server{
Addr: pb.RequireString("addr"),
}
}
如果您想在每次提取上创建一个新实例,请使用di.Prototype()提供选项.
di.Provide(NewRequestContext, di.Prototype())
如果提供程序创建了一个需要清理的值,那么它可以返回一个闭包来清理资源.
func NewFile(log Logger, path Path) (*os.File, func(), error) {
f, err := os.Open(string(path))
if err != nil {
return nil, nil, err
}
cleanup := func() {
if err := f.Close(); err != nil {
log.Log(err)
}
}
return f, cleanup, nil
}
在调用container.Cleanup()之后,它遍历实例,如果存在则调用cleanup函数.
container := di.New(
// ...
di.Provide(NewFile),
)
// do something
container.Cleanup() // file was closed
Dependency injection 是一个运行时的依赖注入框架, 它也会集成到了微服务框架 yoyogo 中. 🦄🌈 YoyoGo (Go语言框架)一个简单、轻量、快速、基于依赖注入的微服务框架( web 、grpc ),支持Nacos/Consoul/Etcd/Eureka/k8s /Apollo等 . 。
参考
yoyogo: https://github.com/yoyofx/yoyogo 。
dependencyinjection: https://github.com/yoyofxteam/dependencyinjection 。
最后此篇关于Go开源库运行时依赖注入框架Dependencyinjection的文章就讲到这里了,如果你想了解更多关于Go开源库运行时依赖注入框架Dependencyinjection的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
好的,所以我想从批处理文件运行我的整个工作环境... 我想要实现什么...... 打开新的 powershell,打开我的 API 文件夹并从该文件夹运行 VS Code 编辑器(cd c:\xy;
我正在查看 Cocoa Controls 上的示例并下载了一些演示。我遇到的问题是一些例子,比如 BCTabBarController ,不会在我的设备上构建或启动。当我打开项目时,它看起来很正常,没
我刚刚开始学习 C 语言(擅长 Java 和 Python)。 当编写 C 程序(例如 hello world)时,我在 ubuntu cmd 行上使用 gcc hello.c -o hello 编译
我在 php 脚本从 cron 开始运行到超时后注意到了这个问题,但是当它从命令行手动运行时这不是问题。 (对于 CLI,PHP 默认的 max_execution_time 是 0) 所以我尝试运行
我可以使用命令行运行测试 > ./node_modules/.bin/wdio wdio.conf.js 但是如果我尝试从 IntelliJ 的运行/调试配置运行它,我会遇到各种不同的错误。 Fea
Error occurred during initialization of VM. Could not reserve enough space for object heap. Error: C
将 Anaconda 安装到 C:\ 后,我无法打开 jupyter 笔记本。无论是在带有 jupyter notebook 的 Anaconda Prompt 中还是在导航器中。我就是无法让它工作。
我遇到一个问题,如果我双击我的脚本 (.py),或者使用 IDLE 打开它,它将正确编译并运行。但是,如果我尝试在 Windows 命令行中运行脚本,请使用 C:\> "C:\Software_Dev
情况 我正在使用 mysql 数据库。查询从 phpmyadmin 和 postman 运行 但是当我从 android 发送请求时(它返回零行) 我已经记录了从 android 发送的电子邮件是正确
所以这个有点奇怪 - 为什么从 Java 运行 .exe 文件会给出不同的输出而不是直接运行 .exe。 当 java 在下面的行执行时,它会调用我构建的可与 3CX 电话系统配合使用的 .exe 文
这行代码 Environment.Is64BitProcess 当我的应用单独运行时评估为真。 但是当它在我的 Visual Studio 单元测试中运行时,相同的表达式的计算结果为 false。 我
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我写了一个使用 libpq 连接到 PostgreSQL 数据库的演示。 我尝试通过包含将 C 文件连接到 PostgreSQL #include 在我将路径添加到系统变量 I:\Program F
如何从 Jenkins 运行 Android 模拟器来运行我的测试?当我在 Execiute Windows bath 命令中写入时,运行模拟器的命令: emulator -avd Tester 然后
我已经配置好东西,这样我就可以使用 ssl 登录和访问在 nginx 上运行的 errbit 我的问题是我不知道如何设置我的 Rails 应用程序的 errbit.rb 以便我可以运行测试 nginx
我编写了 flutter 应用程序,我通过 xcode 打开了 ios 部分并且应用程序正在运行,但是当我通过 flutter build ios 通过 vscode 运行应用程序时,我得到了这个错误
我有一个简短的 python 脚本,它使用日志记录模块和 configparser 模块。我在Win7下使用PyCharm 2.7.1和Python 3.3。 当我使用 PyCharm 运行我的脚本时
我在这里遇到了一些难题。 我的开发箱是 64 位的,windows 7。我所有的项目都编译为“任何 CPU”。该项目引用了 64 位版本的第 3 方软件 当我运行不使用任何 Web 引用的单元测试时,
当我注意到以下问题时,我正在做一些 C++ 练习。给定的代码将不会在 Visual Studio 2013 或 Qt Creator 5.4.1 中运行/编译 报错: invalid types 'd
假设我有一个 easteregg.py 文件: from airflow import DAG from dateutil import parser from datetime import tim
我是一名优秀的程序员,十分优秀!