Spring MVC的初始化

初始化Spring MVC

  1. 首先到了GenericServlet#init(ServletConfig)中,而後調用this#init()方法,此處的this指向是DispatcherServlet對象
public void init(ServletConfig config) throws ServletException {
	this.config = config;
	this.init();
}
  1. DispatcherServlet對象執行init()方法,DispatcherServlet對象中的這個方法是繼承自HttpServletBean,此時會進入到HttpServletBean#init中,這裏面的重點是initServletBean()方法,調用對應的子類進行初始化
public final void init() throws ServletException {
	// Set bean properties from init parameters.
	PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
	if (!pvs.isEmpty()) {
		try {
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);
		}
		//...忽略
	}
	// Let subclasses do whatever initialization they like. 讓子類進行對應的初始化
	initServletBean();
}
  1. 進入到FrameworkServlet#initServletBean中,核心是initWebApplicationContextinitFrameworkServlet方法
protected final void initServletBean() throws ServletException {
	getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
	try {
		//
		this.webApplicationContext = initWebApplicationContext();
		//
		initFrameworkServlet();
	}
	catch (ServletException | RuntimeException ex) {
		logger.error("Context initialization failed", ex);
		throw ex;
	}
	//log..
}
  1. 首先進入到了initWebApplicationContext方法,對web項目上下文進行初始化
protected WebApplicationContext initWebApplicationContext() {
	//首先得到父容器
	WebApplicationContext rootContext =
		WebApplicationContextUtils.getWebApplicationContext(getServletContext());
	//什麼子容器
	WebApplicationContext wac = null;

	//創建父子容器關係
	if (this.webApplicationContext != null) {
		// A context instance was injected at construction time -> use it
		wac = this.webApplicationContext;
		if (wac instanceof ConfigurableWebApplicationContext) {
			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
			if (!cwac.isActive()) {
				// The context has not yet been refreshed -> provide services such as
				// setting the parent context, setting the application context id, etc
				if (cwac.getParent() == null) {
					// The context instance was injected without an explicit parent -> set
					// the root application context (if any; may be null) as the parent
					cwac.setParent(rootContext);
				}
				configureAndRefreshWebApplicationContext(cwac);
			}
		}
	}
	//查找web容器的引用是否存在, 並建立好空ioc容器
	if (wac == null) {
		// No context instance was injected at construction time -> see if one
		// has been registered in the servlet context. If one exists, it is assumed
		// that the parent context (if any) has already been set and that the
		// user has performed any initialization such as setting the context id
		wac = findWebApplicationContext();
	}
	//給建好的IOC容器賦值
	if (wac == null) {
		// No context instance is defined for this servlet -> create a local one
		wac = createWebApplicationContext(rootContext);
	}
	//觸發刷新方法
	if (!this.refreshEventReceived) {
		// Either the context is not a ConfigurableApplicationContext with refresh
		// support or the context injected at construction time had already been
		// refreshed -> trigger initial onRefresh manually here.
		synchronized (this.onRefreshMonitor) {
			onRefresh(wac);
		}
	}

	if (this.publishContext) {
		// Publish the context as a servlet context attribute.
		String attrName = getServletContextAttributeName();
		getServletContext().setAttribute(attrName, wac);
	}

	return wac;
}
  1. IOC容器初始化之後,調用了DispatcherServletonRefresh,在onRefresh中又調用了initStrategies方法,初始化SpringMVC的九大組件
@Override
protected void onRefresh(ApplicationContext context) {
	initStrategies(context);
}

/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {
	//多文件上傳組件
	initMultipartResolver(context);
	//本地語言環境
	initLocaleResolver(context);
	//模板處理器
	initThemeResolver(context);
	//HandlerMapping
	initHandlerMappings(context);
	//適配器
	initHandlerAdapters(context);
	//異常攔截器
	initHandlerExceptionResolvers(context);
	//視圖預處理器
	initRequestToViewNameTranslator(context);
	//視圖轉換器
	initViewResolvers(context);
	//FlashMap
	initFlashMapManager(context);
}

附錄: 九大組件

  1. HandlerMapping 根據request找到相應的處理器。由於Handler(Controller)有兩種形式,一種是基於類的Handler,另外一種是基於Method的Handler(也就是咱們經常使用的)css

  2. HandlerAdapter 調用Handler的適配器。若是把Handler(Controller)當作工具的話,那麼HandlerAdapter就至關於幹活的工人java

  3. HandlerExceptionResolver 對異常的處理web

  4. ViewResolver 用來將String類型的視圖名和Locale解析爲View類型的視圖app

  5. RequestToViewNameTranslator 有的Handler(Controller)處理完後沒有設置返回類型,好比是void方法,這是就須要從request中獲取viewNameide

  6. LocaleResolver 從request中解析出Locale。Locale表示一個區域,好比zh-cn,對不一樣的區域的用戶,顯示不一樣的結果,這就是i18n(SpringMVC中有具體的攔截器LocaleChangeInterceptor)工具

  7. ThemeResolver 主題解析,這種相似於咱們手機更換主題,不一樣的UI,css等ui

  8. MultipartResolver 處理上傳請求,將普通的request封裝成MultipartHttpServletRequestthis

  9. FlashMapManager 用於管理FlashMap,FlashMap用於在redirect重定向中傳遞參數spa

相關文章
相關標籤/搜索