# Baa 依賴注入
依賴注入(dependency injection)簡稱 DI,是 baa 實現的核心,baa 所有組件基于DI組裝起來的。
默認的 日志、路由、模板 都是通過 DI 注冊進來的,在 [Baa核心#更換內置引擎](https://github.com/go-baa/doc/blob/master/zh-CN/baa.md#更換內置引擎)一節也介紹過。
Baa的初始化函數是這樣寫的:
```
// New create a baa application without any config.
func New() *Baa {
b := new(Baa)
b.middleware = make([]HandlerFunc, 0)
b.pool = sync.Pool{
New: func() interface{} {
return NewContext(nil, nil, b)
},
}
if Env != PROD {
b.debug = true
}
b.SetDIer(NewDI())
b.SetDI("router", NewTree(b))
b.SetDI("logger", log.New(os.Stderr, "[Baa] ", log.LstdFlags))
b.SetDI("render", newRender())
b.SetNotFound(b.DefaultNotFoundHandler)
return b
}
```
代碼出處,[baa.go](https://github.com/go-baa/baa/blob/master/baa.go)
## 注冊
`func (b *Baa) SetDI(name string, h interface{})`
DI 的注冊和使用都依賴于注冊的名稱,比如要更換內置組件必須注冊為指定的名稱。
### name string
依賴的名稱
### h interface{}
依賴的實例,可以是任意類型
使用示例:
```
package main
import (
"log"
"os"
"gopkg.in/baa.v1"
)
func main() {
app := baa.Default()
app.SetDI("logger", log.New(os.Stderr, "[BaaDI] ", log.LstdFlags))
app.Get("/", func(c *baa.Context) {
c.String(200, "Hello, 世界")
})
app.Run(":1323")
}
```
## 使用
`func (b *Baa) GetDI(name string) interface{}`
`func (c *Context) DI(name string) interface{}`
可以通過 `baa.GetDI` 或者 `c.DI` 來獲取已經注冊的依賴,如果未注冊,返回 `nil`
由于注冊的依賴可能是任意類型,故返回類型為 `interface{}`,所以獲取后,需要做一次類型斷言再使用。
使用示例:
```
package main
import (
"log"
"os"
"gopkg.in/baa.v1"
)
func main() {
app := baa.Default()
app.SetDI("logger", log.New(os.Stderr, "[BaaDI] ", log.LstdFlags))
app.Get("/", func(c *baa.Context) {
// use di
logger := c.DI("logger").(*log.Logger)
logger.Println("i am use logger di")
c.String(200, "Hello, 世界")
})
app.Run(":1323")
}
```
### 日志
baa 將日志抽象為 `baa.Logger` 接口,只要實現了該接口,就可以注冊為全局日志器。
baa 內置的日志器使用的是標準包的 `log` 實例。
更換全局日志器:
```
app := baa.New()
baa.SetDI("logger", newLogger)
```
> logger 是內置名稱,該命名被用于全局日志器。
>
> 如果不是要更換全局日志,而是注冊一個新的日志器用于其他用途,只需更改注冊名稱即可,而且也不需要實現 `baa.Logger` 接口。
### 路由
只要實現接口 `baa.Router` 接口即可。
```
app := baa.New()
baa.SetDI("router", newRender)
```
> router 是內置名稱,,該命名被用于全局路由器。
baa 除了內置的 tree路由,還新增了兩個路由器可用,見 [router](https://github.com/go-baa/router)
```
package main
import (
"github.com/go-baa/router/regtree"
"gopkg.in/baa.v1"
)
func main() {
app := baa.Default()
app.SetDI("router", regtree.New(app))
app.Get("/view-:id(\\d+)", func(c *baa.Context) {
c.String(200, c.Param("id"))
})
app.Get("/view-:id(\\d+)/project", func(c *baa.Context) {
c.String(200, c.Param("id")+"/project")
})
app.Run(":1323")
}
```
### 模板
只要實現接口 `baa.Renderer` 接口即可。
```
app := baa.New()
baa.SetDI("render", newRender)
```
> render 是內置名稱,該命名被用于模板渲染。
baa 除了內置的 render簡單模板渲染,還新增了兩個模板渲染引擎:
* [render](https://github.com/go-baa/doc/tree/master/zh-CN/component/render.md)
* [pongo2](https://github.com/go-baa/doc/tree/master/zh-CN/component/pongo2.md)
### 緩存
緩存不是 baa內置依賴,作為一個常用組件實現,具體見:
[baa組件/緩存](https://github.com/go-baa/doc/tree/master/zh-CN/component/cache.md)