1.初始化流程:
1.1 包的导入过程
首先我们从整体来审视beego包的初始化过程,然后再来逐步分析每一步的详细内容。
根据go包的导入过程,我们先来分析一下beego的初始化。包的导入过程如下图:
1) 在我们自己项目的main包中首先会导入:
import "github.com/astaxie/beego",
然后go编译器开始从beego这个目录中的第一个文件admin.go开始读取,
(注:之所以说是beego目录而不是包,请参考
https://tonybai.com/2015/03/09/understanding-import-packages/这篇博文的详解)
然后发现,admin.go中又分别导入了
"github.com/astaxie/beego/grace"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/toolbox"
"github.com/astaxie/beego/utils"
四个目录,于是编译器继续从上往下依次读取引入的目录。
首先,我们进入引入的第一个目录,grace目录中。
在grace目录中,我们发现有四个文件,分别是:
conn.go, grace.go, listener.go,server.go。进入这四个文件中发现,它们引入的都是go内置的包。(注:由于打算只分析beego框架的内容,所以不打算继续跟踪go内置包的引入。后期分析go源码的时候再继续追踪。)
进入到grace目录中,根据包的导入过程规则,编译器首先会依次初始化该目录下所有文件的const常量,然后是该目录下所有文件的var变量,最后是所有文件的init()函数。由于grace目录下只有grace.go文件中有var变量和init()函数,而其他三个文件没有const常量和var变量,也没有init()函数,所以在编译运行我们自己的App时,首先会从grace目录下的grace.go中初始化变量和执行grace.init()函数。接着,按照上述规则依次加载logs目录,toolbox目录,utils目录。(注:如果在引入时,把logs和toolbox位置互换,你会发现,依次加载的目录是toolbox=>logs=>utils。由此可知,go引入目录是按照从上到下依次加载的)。
1.2 grace目录下的初始化,主要在grace.go
1.2.1 声明一些信号常量:
const (
// PreSignal is the position to add filter before signal
PreSignal = iota
// PostSignal is the position to add filter after signal
PostSignal
// StateInit represent the application inited
StateInit
// StateRunning represent the application is running
StateRunning
// StateShuttingDown represent the application is shutting down
StateShuttingDown
// StateTerminate represent the application is killed
StateTerminate
)
1.2.2 声明Server相关的变量和http请求需要的一些参数
var (
regLock *sync.Mutex
runningServers
map[string]*Server
runningServersOrder []
string
socketPtrOffsetMap map[string]uint
runningServersForked bool
// DefaultReadTimeOut is the HTTP read timeout
DefaultReadTimeOut time.Duration
// DefaultWriteTimeOut is the HTTP Write timeout
DefaultWriteTimeOut time.Duration
// DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit
DefaultMaxHeaderBytes int
// DefaultTimeout is the shutdown server's timeout. default is 60s
DefaultTimeout = 60 * time.Second
isChild bool
socketOrder string
hookableSignals []os.Signal
)
1.2.3 初始化1.2.2中的变量
func init() {
flag.
BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
flag.
StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
regLock = &sync.Mutex{}
runningServers =
make(map[string]*Server)
runningServersOrder = []
string{}
socketPtrOffsetMap =
make(map[string]uint)
hookableSignals = []os.Signal{
syscall.
SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
}
}
1.3 [endif]logs目录下的初始化
1) 调用conn.go中的init(),注册网络日志logger。
2) 调用console.go中的init(),注册打印到terminal窗口的logger
3 ) 调用file.go中的init(),注册将日志传输到文件中的logger
4 ) 调用jianliao.go中的init(),注册jianliao日志(不知道jianliao是什么鬼东西)
5 ) 调用multile.go中的init(),注册multifilelog 日志打印器
6 ) 调用slack.go中的init(),注册SLACKWriter日志打印器
7 ) 调用smtp.go中的init(),注册SMTPWriter日志打印器
1.4 [endif]toolbox目录下的初始化
1)调用healthcheck.go中的init(),初始化健康检查器(HealthChecker)的容器AdminCheckList
func init() {
AdminCheckList =
make(map[string]HealthChecker)
}
2)调用profile.go中的init(),获取当前进程的pid,并将值复制给toolbox包内变量pid
func init() {
pid = os.
Getpid()
}
3)调用statistics.go中的init(),初始化Statistics,主要是用来统计请求的url和method的时间
4) 调用Tasker.go中的init(),初始化Tasker
1.5 config目录下的初始化,config目录是由beego目录下config.go引入的
1)调用ini.go中的init(),注册ini格式的IniConfig
2)调用json.go中的init(),注册json格式的JsonConfig
1.6 context目录下的初始化
由于context目录下文件中没有init()方法,所以在此不做分析了
1.7 [endif]session目录下的初始化
1)调用sess_cookie.go中的init(),注册CookieProvider
2)调用sess_file.go中的init(),注册FileProvider
3 )调用sess_mem.go中的init(),注册MemProvider
4) 调用sess_utils.go中的init(),注册存储session值可以序列化的数据类型
1.8 [endif]beego目录下的初始化
1)调用admin.go中的init(),注册一些beego默认路由:qps,prof,healthcheck,listconf等
2)调用app.go中的init(),初始化一个Beego的App,BeeApp。
func init() {
// create beego application
BeeApp = NewApp()
}
在NewApp函数中主要是:1,生成了一个ControllerRegister结构体(注意这里主要是使用为了ControllerRegister中实现的ServeHttp方法),2,然后生成一个App结构体,并将1中生成的ControllerRegister和go内置的默认的http.Server作为参数赋给App。
// NewApp returns a new beego application.
func NewApp() *App {
cr :=
NewControllerRegister()
app := &App{Handlers: cr
, Server: &http.Server{}}
return app
}
3 )调用config.go的init(),初始化配置文件的默认值,以及读取项目中conf目录中的app.conf配置文件,并将其值赋值给配置结构体beegoAppConfig
4 )调用parser.go中的init()
5 ) 调用template.go中的init(),
1.9 项目根目录/routers目录下的初始化
1) 调用router.go中的init(),该处主要是注册路由和过滤器
1.10 项目根目录下的初始化
1) 调用main.go中的init(),
至此项目所有的初始化流程就走完了。