当前位置: 首页 > news >正文

网站建设和管理情况查网站域名

网站建设和管理情况,查网站域名,网页制作网站首页设计,广告推广的好处服务容器的实现 一个服务容器主要的功能是:为服务提供注册绑定、提供获取服务实例,所以服务容器至少有两个方法:注册方法 Bind、获取实例方法 Make。 对于注册的方法,直接将一个服务提供者注册到容器中,参数是之前定…

服务容器的实现

一个服务容器主要的功能是:为服务提供注册绑定、提供获取服务实例,所以服务容器至少有两个方法:注册方法 Bind、获取实例方法 Make。

  • 对于注册的方法,直接将一个服务提供者注册到容器中,参数是之前定义的服务提供者,返回值则是 error 是否注册成功。
// Bind 绑定一个服务提供者,如果关键字凭证已经存在,会进行替换操作,不返回 error
Bind(provider ServiceProvider) error
  • 获取实例的方法是 Make,它会根据一个关键字凭证,来获取容器中已经实例化好的服务。所以参数是一个关键字凭证 string,返回值是实例化好的服务 interface 和是否有错误的 error 信息。
// Make 根据关键字凭证获取一个服务,
Make(key string) (interface{}, error)

除了这两个,再考虑在注册绑定及获取服务实例过程中,有什么方面可以扩展。

  • 是否已绑定: IsBind, 参数为关键字凭证,返回为 bool 表示是否已经绑定
  • 不关心Make方法的error: MustMake, 它的参数和 Make 方法一样,为关键字凭证,返回值为实例化服务,但是不返回 error
  • 根据参数获取不同初始化实例: MakeNew

// Container 是一个服务容器,提供绑定服务和获取服务的功能
type Container interface {// Bind 绑定一个服务提供者,如果关键字凭证已经存在,会进行替换操作,返回 errorBind(provider ServiceProvider) error// IsBind 关键字凭证是否已经绑定服务提供者IsBind(key string) bool// Make 根据关键字凭证获取一个服务,Make(key string) (interface{}, error)// MustMake 根据关键字凭证获取一个服务,如果这个关键字凭证未绑定服务提供者,那么会 panic。// 所以在使用这个接口的时候请保证服务容器已经为这个关键字凭证绑定了服务提供者。MustMake(key string) interface{}// MakeNew 根据关键字凭证获取一个服务,只是这个服务并不是单例模式的// 它是根据服务提供者注册的启动函数和传递的 params 参数实例化出来的// 这个函数在需要为不同参数启动不同实例的时候非常有用MakeNew(key string, params []interface{}) (interface{}, error)
}

具体实现

在 framework/container.go 中 定义HadeContainer, 表示容器的具体实现:


// HadeContainer 是服务容器的具体实现
type HadeContainer struct {Container // 强制要求 HadeContainer 实现 Container 接口// providers 存储注册的服务提供者,key 为字符串凭证providers map[string]ServiceProvider// instance 存储具体的实例,key 为字符串凭证instances map[string]interface{}// lock 用于锁住对容器的变更操作lock sync.RWMutex
}

// Bind 将服务容器和关键字做了绑定
func (hade *HadeContainer) Bind(provider ServiceProvider) error {hade.lock.Lock()defer hade.lock.Unlock()key := provider.Name()hade.providers[key] = provider// if provider is not deferif provider.IsDefer() == false {if err := provider.Boot(hade); err != nil {return err}// 实例化方法params := provider.Params(hade)method := provider.Register(hade)instance, err := method(params...)if err != nil {return errors.New(err.Error())}hade.instances[key] = instance}return nil
}// Make 方式调用内部的 make 实现
func (hade *HadeContainer) Make(key string) (interface{}, error) {return hade.make(key, nil, false)
}// MakeNew 方式使用内部的 make 初始化
func (hade *HadeContainer) MakeNew(key string, params []interface{}) (interface{}, error) {return hade.make(key, params, true)
}// 真正的实例化一个服务
func (hade *HadeContainer) make(key string, params []interface{}, forceNew bool) (interface{}, error) {hade.lock.RLock()defer hade.lock.RUnlock()// 查询是否已经注册了这个服务提供者,如果没有注册,则返回错误sp := hade.findServiceProvider(key)if sp == nil {return nil, errors.New("contract " + key + " have not register")}if forceNew {return hade.newInstance(sp, params)}// 不需要强制重新实例化,如果容器中已经实例化了,那么就直接使用容器中的实例if ins, ok := hade.instances[key]; ok {return ins, nil}// 容器中还未实例化,则进行一次实例化inst, err := hade.newInstance(sp, nil)if err != nil {return nil, err}hade.instances[key] = instreturn inst, nil
}

容器和框架的结合

hade 框架中最核心的两个数据结构 Engine 和 Context。

  • Engine 就是 Core 数据结构,这个数据结构是整个框架的入口,也承担了整个框架最核心的路由、中间件等部分。
  • Context 对应封装request和response的ctx,它为每个请求创建一个 Context,其中封装了各种对请求操作的方法。

对应来看我们的服务容器,它提供了两类方法,绑定操作和获取操作。绑定操作是全局的操作,而获取操作是在单个请求中使用的。所以在全局,我们为服务容器绑定了服务提供方,就能在单个请求中获取这个服务。

那么对应到框架中,可以将服务容器存放在 Engine 中,并且在 Engine 初始化 Context 的时候,将服务容器传递进入 Context

  • 修改framework/gin/gin.go中Engine 的数据结构, 添加container字段

type Engine struct {// 容器container framework.Container...
}func New() *Engine {debugPrintWARNINGNew()engine := &Engine{...// 这里注入了 containercontainer:              framework.NewHadeContainer(),...}...return engine
}
  • 在 Engine 创建 context 的时候, 将容器注入到ctx中

// engine 创建 context
func (engine *Engine) allocateContext() *Context {v := make(Params, 0, engine.maxParams)// 在分配新的 Context 的时候,注入了 containerreturn &Context{engine: engine, params: &v, container: engine.container}
}

这样就完成了服务容器的创建和传递,接下来完成服务容器方法的封装。

根据上面描述的,Engine 中负责绑定,Context 中负责获取,所以我们将 container 的五个能力拆分到 Engine 和 Context 数据结构中。Engine 封装 Bind 和 IsBind 方法,Context 封装 Make、MakeNew、MustMake 方法。

将这些为 Engine 和 Context 增加的新的方法单独存放在一个新的文件 framework/gin/hade_context.go 中。


// engine 实现 container 的绑定封装
func (engine *Engine) Bind(provider framework.ServiceProvider) error {return engine.container.Bind(provider)
}// IsBind 关键字凭证是否已经绑定服务提供者
func (engine *Engine) IsBind(key string) bool {return engine.container.IsBind(key)
}// context 实现 container 的几个封装
// 实现 make 的封装
func (ctx *Context) Make(key string) (interface{}, error) {return ctx.container.Make(key)
}// 实现 mustMake 的封装
func (ctx *Context) MustMake(key string) interface{} {return ctx.container.MustMake(key)
}// 实现 makenew 的封装
func (ctx *Context) MakeNew(key string, params []interface{}) (interface{}, error) {return ctx.container.MakeNew(key, params)
}

创建一个服务提供方

下面我们来创建一个服务 DemoService,为这个服务创建一个服务提供方 DemoServiceProvider,并注入到服务容器中。在业务目录中创建一个目录 provider/demo 存放这个服务。

先搞清楚需要为这个服务设计几个文件。

  • 要有一个服务接口文件 contract.go,存放服务的接口文件和服务凭证。
  • 需要设计一个 provider.go,这个文件存放服务提供方 ServiceProvider 的实现。
  • 最后在 service.go 文件中实现具体的服务实例。

如何通过服务提供方创建服务

这里实现非常简单,我们需要做两个操作,绑定服务提供方、获取服务。

首先是在业务文件夹的 main.go 中绑定操作,在 main 函数中,完成 engine 的创建之后,用在 engine 中封装的 Bind 方法做一次绑定操作。


func main() {// 创建 engine 结构core := gin.New()// 绑定具体的服务core.Bind(&demo.DemoServiceProvider{})...
}

然后就是服务的获取了。在具体的业务逻辑控制器中,我们选择路由 /subject/list/all 对应的控制器 SubjectListController,使用为 context 封装的 MustMake 方法来获取 demo 服务实例。

MustMake 的参数为 demo 的服务凭证 demo.Key,返回的是一个 interface 结构,这个 interface 结构实际上是实现了 demo.Service 接口的一个服务实例。

而在接口的具体输出中,输出的是这个接口定义的 GetFoo() 方法的输出,也就是最终会从服务容器中获取到 DemoService 的 GetFoo() 方法的返回值 Foo 结构,带有字段 Name: “i am foo”输出在页面上。


// 对应路由 /subject/list/all
func SubjectListController(c *gin.Context) {// 获取 demo 服务实例demoService := c.MustMake(demo.Key).(demo.Service)// 调用服务实例的方法foo := demoService.GetFoo()// 输出结果c.ISetOkStatus().IJson(foo)
}

最后验证一下,在浏览器中,我们访问这个路由 /subject/list/all,获取到了 Foo 数据结构 Json 化出来的结果。

【小结】

  1. 将框架作为一个容器,服务注入到框架的engine和ctx中
  2. 注册时为全局,因此用engine
  3. 使用服务时为请求独自使用,因此用ctx来获取服务
  4. 注意获取服务时是否有并发竞争问题
http://www.zhongyajixie.com/news/26756.html

相关文章:

  • 广州市网站建设制作费用网店营销策略有哪些
  • wordpress修改样式seo怎么优化步骤
  • 襄阳手机网站建设深圳最好seo
  • 鹤壁做网站价格竞价
  • 校园微网站建设方案百家号排名
  • 搭建网站用什么语言关键词优化一年多少钱
  • 网站建设与推广合肥邵阳seo排名
  • aspnet网站开发南京seo排名优化
  • 自助建站系统源源码市场调研报告总结
  • 安庆网站建设电话seo是指搜索引擎优化
  • 网站备案需要的资料石家庄市人民政府官网
  • 织梦 电影网站 模板建网站需要什么
  • 老鹰主机做的网站线上培训
  • 网站规划的原则有网页设计与制作软件有哪些
  • oa系统网站建设方案十大小说网站排名
  • 公司网站做的好的网络销售管理条例
  • 电子商务网站建设的背景惠州百度seo在哪
  • 网站开发名片企业营销平台
  • 有保障的广州网站建设登封网络推广
  • 企业邮箱注册域名武汉seo技术
  • 企业网站建设常见问题百度的电话人工客服电话
  • 网站推广合同模板湖南优化公司
  • 青岛网站建设百度帐号申请注册
  • 黑龙江建设网官方网站特种作业证北京seo公司华网白帽
  • 环保网站 怎么做站内营销推广方式
  • beego框架做的网站seo案例分析
  • 关于做一动物网站的界面个发布软文的平台有哪些
  • 哈尔滨优化网站方法收录网
  • 网页制作个人简介页面模板排名优化网站建设
  • 旅游分析 网站谷歌推广优化