1. 程式人生 > 實用技巧 >系列文章:spring的xml配置是如何對應註解配置的之ContextLoaderListener

系列文章:spring的xml配置是如何對應註解配置的之ContextLoaderListener

何時載入ContextLoaderListener?

ContextLoaderListener:繼承ContextLoader,實現ServletContextListener,接收web應用ServletContext變化的通知,將監聽器配置在web.xml中。我們一般會在xml中做如下配置:

  <!-- 預設的spring配置檔案是在WEB-INF下的applicationContext.xml -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      classpath:bean.xml
    </param-value>
  </context-param>

以spring boot啟動為例

  1. 由子類實現的onRefresh
ServletWebServerApplicationContext
@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}
  1. 建立web容器
private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			ServletWebServerFactory factory = getWebServerFactory();
			this.webServer = factory.getWebServer(getSelfInitializer());
		}
		else if (servletContext != null) {
			try {
				getSelfInitializer().onStartup(servletContext);
			}
			catch (ServletException ex) {
				throw new ApplicationContextException("Cannot initialize servlet context", ex);
			}
		}
		initPropertySources();
	}
  1. 初始化器
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
		return this::selfInitialize;
	}

	private void selfInitialize(ServletContext servletContext) throws ServletException {
		prepareWebApplicationContext(servletContext);
		registerApplicationScope(servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
		//遍歷獲取到的初始化器,並啟動
		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
			beans.onStartup(servletContext);
		}
	}
  1. 獲取了哪些初始化器
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
		return new ServletContextInitializerBeans(getBeanFactory());
}

@SafeVarargs
public ServletContextInitializerBeans(ListableBeanFactory beanFactory,
		Class<? extends ServletContextInitializer>... initializerTypes) {
	this.initializers = new LinkedMultiValueMap<>();
	this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes)
			: Collections.singletonList(ServletContextInitializer.class);
	addServletContextInitializerBeans(beanFactory);
	addAdaptableBeans(beanFactory);
	List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
			.flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
			.collect(Collectors.toList());
	this.sortedList = Collections.unmodifiableList(sortedInitializers);
	logMappings(this.initializers);
}

protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
		MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
		addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
		addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
		//通過ServletListenerRegistrationBean.getSupportedTypes()獲取
		for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
			addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,
					new ServletListenerRegistrationBeanAdapter());
		}
}

private static final Set<Class<?>> SUPPORTED_TYPES;
static {
		Set<Class<?>> types = new HashSet<>();
		types.add(ServletContextAttributeListener.class);
		types.add(ServletRequestListener.class);
		types.add(ServletRequestAttributeListener.class);
		types.add(HttpSessionAttributeListener.class);
		types.add(HttpSessionListener.class);
		types.add(ServletContextListener.class);
		SUPPORTED_TYPES = Collections.unmodifiableSet(types);
	}