在Spring配置Servlet标簽一文中介紹了Servlet的調用以及初始化過程,在一系列的初始化過程init中加載bean的模式都是先從bean工廠得到,如果沒有那麼就加載Spring屬性檔案DispatcherServlet.properties中預設的,那麼在bean工廠中的bean是什麼時候設定進工廠的,很簡單,往下看。
先貼上繼承關系圖,好說話。
在FrameworkServlet類中有方法代碼
protected final void initServletBean() throws ServletException {
………………
protected final void initServletBean() throws ServletException {
………………
protected WebApplicationContext initWebApplicationContext() {
// A context instance was injected at construction time -> use it
//一個context在初始化的時候被注入
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
………………
configureAndRefreshWebApplicationContext(cwac);
………………
////等于空,加載配置檔案然後重新整理
if (wac == null) {
// No context instance is defined for this servlet ->
//就是說下面的代碼是一定會初始化一個的,并且加載配置檔案
wac = createWebApplicationContext(rootContext);
………………
下面看createWebApplicationContext()中的代碼。
………………
//用反射執行個體化一個
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
//重新設定配置檔案路徑,然後會重新整理。在listener中其實已經設定一次了,那時候已經重新整理路徑了加載bean了
//相當于每次該配置都要重新啟動工程
wac.setConfigLocation(getContextConfigLocation());//參數配置的xml路徑
configureAndRefreshWebApplicationContext(wac);
………………
注意上面的代碼
wac.setConfigLocation(getContextConfigLocation());
這回加載你的配置檔案,一般都是類似xxx-servlet.xml的檔案,在檔案中你既可以用傳統過的标簽定義bean,也可以簡單的聲明幾行代碼告訴Spring用的是注解的方式。
通過上面的代碼,很自然的我們轉到configureAndRefreshWebApplicationContext方法。關鍵代碼如下:
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//添加監聽器,org.springframework.context.event.SourceFilteringListener
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
postProcessWebApplicationContext(wac);
applyInitializers(wac);
wac.refresh();
好了,終于見到這行代碼了
wac.refresh();
,為什麼這麼說那,因為這行代碼就是WebApplicationContext的更新過程,這個更新過程的背景有一系列的複雜的但是很有調理的bean的裝配、加載以及部分bean的初始化過程。
詳細的介紹在《Spring IOC-WebApplicationContext重新整理》