1. 程式人生 > >SpringMVC原始碼分析--容器初始化(三)HttpServletBean

SpringMVC原始碼分析--容器初始化(三)HttpServletBean

在上一篇部落格 springMVC原始碼分析--容器初始化(二)DispatcherServlet中,我們隊SpringMVC整體生命週期有一個簡單的說明,並沒有進行詳細的原始碼分析,接下來我們會根據部落格中提供的springMVC的生命週期圖來詳細的對SpringMVC的相關原始碼進行分析。

在上一篇部落格中我們瞭解到,SpringMVC初始化配置是在父類HttpServletBean的init方法中,其實HttServletBean是一個比較簡單的類,在這個類中並沒有太複雜的功能,主要的函式是init函式中,原始碼如下:

主要工作就是設定我們在web.xml中配置的contextConfigLocation屬性,當然這個屬性是springMVC檔案的配置檔案地址,當然也可以不用配置,使用預設名稱載入。

initBeanWrapper 函式並沒有具體實現

initServletBean()是模板方法,是在子類FrameworkServlet中實現的,接下來我們會詳細分析,這樣HttpServletBean的主體功能就介紹完了。

        public final void init() throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing servlet '" + getServletName() + "'");
		}

		// Set bean properties from init parameters.
		try {
			//獲得web.xml中的contextConfigLocation配置屬性,就是spring MVC的配置檔案
			PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			//獲取伺服器的各種資訊
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			//模板方法,可以在子類中呼叫,做一些初始化工作,bw代表DispatcherServelt
			initBeanWrapper(bw);
			//將配置的初始化值設定到DispatcherServlet中
			bw.setPropertyValues(pvs, true);
		}
		catch (BeansException ex) {
			logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
			throw ex;
		}

		// Let subclasses do whatever initialization they like.
		//模板方法,子類初始化的入口方法
		initServletBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Servlet '" + getServletName() + "' configured successfully");
		}
	}
當然HttpServletBean還是提供了一些其他方法的,其實都是一些比較簡單的get和set方法,就不做過多介紹了,HttpServletBean的完整原始碼如下:
/**
 *HttpServlet的一個簡單擴充套件類
 */
@SuppressWarnings("serial")
public abstract class HttpServletBean extends HttpServlet
		implements EnvironmentCapable, EnvironmentAware {

	protected final Log logger = LogFactory.getLog(getClass());

	private final Set<String> requiredProperties = new HashSet<String>();

	private ConfigurableEnvironment environment;

	protected final void addRequiredProperty(String property) {
		this.requiredProperties.add(property);
	}
	@Override
	public final void init() throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing servlet '" + getServletName() + "'");
		}

		// Set bean properties from init parameters.
		try {
			//獲得web.xml中的contextConfigLocation配置屬性,就是spring MVC的配置檔案
			PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
			//獲取伺服器的各種資訊
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			//模板方法,可以在子類中呼叫,做一些初始化工作,bw代表DispatcherServelt
			initBeanWrapper(bw);
			//將配置的初始化值設定到DispatcherServlet中
			bw.setPropertyValues(pvs, true);
		}
		catch (BeansException ex) {
			logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
			throw ex;
		}

		// Let subclasses do whatever initialization they like.
		//模板方法,子類初始化的入口方法
		initServletBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Servlet '" + getServletName() + "' configured successfully");
		}
	}

	/**
	 * Initialize the BeanWrapper for this HttpServletBean,
	 * possibly with custom editors.
	 * <p>This default implementation is empty.
	 * @param bw the BeanWrapper to initialize
	 * @throws BeansException if thrown by BeanWrapper methods
	 * @see org.springframework.beans.BeanWrapper#registerCustomEditor
	 */
	protected void initBeanWrapper(BeanWrapper bw) throws BeansException {
	}
	
	//獲取servletName
	@Override
	public final String getServletName() {
		return (getServletConfig() != null ? getServletConfig().getServletName() : null);
	}
	
	//獲取ServletContext
	@Override
	public final ServletContext getServletContext() {
		return (getServletConfig() != null ? getServletConfig().getServletContext() : null);
	}


	
	protected void initServletBean() throws ServletException {
	}


	@Override
	public void setEnvironment(Environment environment) {
		Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
		this.environment = (ConfigurableEnvironment) environment;
	}

	@Override
	public ConfigurableEnvironment getEnvironment() {
		if (this.environment == null) {
			this.environment = this.createEnvironment();
		}
		return this.environment;
	}


	protected ConfigurableEnvironment createEnvironment() {
		return new StandardServletEnvironment();
	}

	private static class ServletConfigPropertyValues extends MutablePropertyValues {

		public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
			throws ServletException {

			Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ?
					new HashSet<String>(requiredProperties) : null;

			Enumeration<String> en = config.getInitParameterNames();
			while (en.hasMoreElements()) {
				String property = en.nextElement();
				Object value = config.getInitParameter(property);
				addPropertyValue(new PropertyValue(property, value));
				if (missingProps != null) {
					missingProps.remove(property);
				}
			}
			// Fail if we are still missing properties.
			if (missingProps != null && missingProps.size() > 0) {
				throw new ServletException(
					"Initialization from ServletConfig for servlet '" + config.getServletName() +
					"' failed; the following required properties were missing: " +
					StringUtils.collectionToDelimitedString(missingProps, ", "));
			}
		}
	}

}