一、web應用環境
1.ServletContext
對於一個web應用,其部署在web容器(比如:tomcat)中,web容器提供其一個全局的上下文環境,這個上下文就是ServletContext,它由web容器負責初始化,其為后面的spring容器提供宿主環境。
ServletContext是一個全局的儲存信息的空間,服務器開始,其就存在,服務器關閉,其才釋放。ServletContext提供對應用程序中所有Servlet所共有的各種資源和功能的訪問。Servlet上下文API用於設置應用程序中所有Servlet共有的信息,Servlet可能需要共享他們之間的共有信息。運行於同一服務器的Servlet有時會共享資源,如JSP頁面、文件和其它Servlet。request,一個用戶可有多個;session,一個用戶一個;而servletContext在整個web應用中只有一個,所有用戶也只共用一個。所以,為了節省空間,提高效率,ServletContext中,要放必須的、重要的、所有用戶需要共享的線程又是安全的一些信息。
換一種方式說吧,運行在Java虛擬機中的每一個Web應用程序都有一個與之相關的Servlet上下文。ServletContext對象是Web服務器中的一個已知路徑的根,Servlet上下文被定位於http://localhost:8080/項目名. 以 /項目名 請求路徑(稱為上下文路徑)開始的所有請求被發送到與此ServletContext關聯的Web應用程序。一個ServletContext對象表示了一個Web應用程序的上下文。
舉例:做一個購物類的網站,要從數據庫中提取物品信息,如果用session保存這些物品信息,每個用戶都訪問一便數據庫,效率就太低了;所以要用來Servlet上下文來保存,在服務器開始時,就訪問數據庫,將物品信息存入Servlet上下文中,這樣,每個用戶只用從上下文中讀入物品信息就行了。
2. RootWebApplicationContext和DispatcherServletWebApplicationContext
以下簡稱RootWebApplicationContext為:RootContext,DispatcherServletWebApplicationContext為:DispatcherServletContext。
WebApplicationContext擴展了ApplicationContext,代表的Spring Web的應用上下文,RootContext由ContextLoaderListener創建,其中存放了各種注冊到Spring的非Web組件的bean(比如service)。RootContext初始化完成后將其存儲到ServletContext中,便於獲取。在源碼中你可以看到這樣的代碼:servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);//this.context就是RootContext
接着是DispatcherServletContext的初始化,它會以RootContext為父上下文(在DispatcherServletContext中可以引用RootContext中的非web組件,而反過來不行。),然后初始化Web相關組件,比如控制器,視圖解析器等。DispatcherServletContext初始化完畢后將自身存入ServletContext.
相關源碼:在初始化DispatherServlet中,org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext()
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());//獲取RootContext(非web組件,比如service) WebApplicationContext dispatcherServletContext = this.webApplicationContext; dispatcherServletContext.setParent(rootContext);//以RootContext為父上下文 getServletContext().setAttribute(attrName, dispatcherServletContext);//將dispatcherServletContext存入ServletContext
繼承結構圖:

log4j日志軌跡:

3. WebApplicationContext和DispatcherServlet上下文初始化方式
初始化方式有兩種:Java配置和在web.xml配置,不管是哪種配置方式,所做的工作差別不大。
java配置:在servlet 3.0環境中,web容器會在類路徑中查找實現了javax.servlet.ServletContainerInitializer接口的類,如果能找到此類就會用它來配置Servlet容器。Spring提供了這個接口的實現,名為SpringServletContainerInitializer,這個實現又查找實現了WebApplicationInitializer接口的類。Spring 3.2引入了一個WebApplicationInitializer的一個便利的基礎實現類:AbstractAnnotationConfigDispatcherServletInitializer。它會創建DispatcherServleContext和RootContext,現在只需擴展它即可。
(1) SsmContextInitializer.java

(2) RootConfig.java

(3) WebConfig.java

來看看DispatcherServletContext和它的父上下文RootContext存儲的核心Bean:
1.DispatcherServletContext:

從圖中可以看出:DispatcherServletContext中存儲的Bean是與web相關的組件,比如視圖解析器,處理器映射等。
2.RootContext(在DispatcherServletContext可以看到它的父上下文Root):

從圖中可以看出:RootContext中存儲的Bean是非web組件,比如Service。
二、Mybatis
1.在獨立的Mybatis中的核心組件:
1.SqlSessionFactory:生成SqlSession(會話),由SqlSessionFactoryBuilder根據配置信息創建。
2.SqlSession:一個既可以發送SQL去執行並返回結果,也可以獲取Mapper的接口。
3.SQL Mapper:由mapper配置文件(也可以是注解配置)和java接口構成,根據給出的mapper配置文件來發送SQL去執行並返回結構
核心編程代碼:
(1). MybatisConfig.xml
(2) UserMapper.xml

(3) Demo.java

2.在MyBatis-Spring中的核心組件:
為了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 編寫數據訪問對象 (DAO)的代碼,MyBatis-Spring 提供了一個動態代理的實現:MapperFactoryBean。這個類 可以讓你直接注入數據映射器接口到你的 service 層 bean 中。當使用映射器時,你僅僅如調 用你的 DAO 一樣調用它們就可以了,但是你不需要編寫任何 DAO 實現的代碼,因為 MyBatis-Spring 將會為你創建代理。MapperFactoryBean 創建的代理類實現了 UserMapper 接口,並且注入到應用程序中。 因為代理創建在運行時環境中,那么指定的映射器必須是一個接口,而 不是一個具體的實現類。
注意:如果 UserMapper 有一個對應的 MyBatis 的 XML 映射器文件, 如果 XML 文件在類路徑的 位置和映射器類相同時, 沒有必要在去指定映射器,它會被 MapperFactoryBean 自動解析,反之亦然。我們一般會將Mapper接口的類完全限定名和Mapper.xml配置文件的命名空間寫成一致。
核心bean的創建:配置在非web組件(上文的RootConfig.java)中
1.javax.sql.DataSource:創建它的實現類即可,比如org.apache.ibatis.datasource.pooled.PooledDataSource;
解釋:配置url,driver,userName,password;

2.org.mybatis.spring.SqlSessionFactoryBean
解釋:配置SqlSessionFactory,主要提供數據源和mapper配置文件

3.org.mybatis.spring.mapper.MapperFactoryBean
解釋:為對應的Mapper接口創建代理

注意:在實際應用中肯定會有多個Dao,一個個去配置過於繁瑣,所以我們一般采用MapperScannerConfigurer,它將會查找指定類路徑下的映射器並自動將它們創建成MapperFactoryBean。
3.org.mybatis.spring.mapper.MapperScannerConfigurer
解釋:配置mapper接口的掃描器,提供mapper接口所在的包名(必須的)

MapperScannerConfigurer中還有幾個常用到的屬性配置:
1.private Class<? extends Annotation> annotationClass:指定包中的接口若有指定的注解則掃描(認為它是Mapper)
例子:scannerConfigurer.setAnnotationClass(Repository.class);//若有此配置,Mapper掃描器會只掃描帶有@Repository注解的接口
2.private Class<?> markerInterface:指定包中的接口若實現了指定的接口則掃描(認為它是Mapper)
例子:scannerConfigurer.setmarkerInterface(IUserDao.class);//若有此配置,Mapper掃描器會只掃描帶有實現了IUserDao的接口
3個組件配置完畢后,你只需要直接注入數據映射器接口到你的 service 層 bean 中。直接調用數據映射器接口的方法即可:
service層代碼:IUserDao接口沒有任何手動實現類,其實現由MapperFactoryBean創建並注入到程序中。
最后在web組件中創建Controller即可運行。
PS:本文不定期更新,有錯誤的地方歡迎評論告訴我,謝謝。
