dispatcher-servlet.xml
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
- <context-param>
- <param-name>contextConfigLocationparam-name>
- <param-value>/WEB-INF/applicationContext.xmlparam-value>
- context-param>
- <listener>
- <listener-class> org.springframework.web.context.ContextLoaderListenerlistener-class>
- listener>
- <servlet>
- <servlet-name>dispatcherservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
- <load-on-startup>1load-on-startup>
- servlet>
- <servlet-mapping>
- <servlet-name>dispatcherservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
- web-app>
ContextLoader.java
/**
* Name of the class path resource (relative to the ContextLoader class)
* that defines ContextLoader's default strategy names.
*/
private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
static { // Load default strategy implementations from properties file. // This is currently strictly internal and not meant to be customized // by application developers. try { ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage()); } }
ContextLoader 加载ContextLoader.properties文件,内容如下
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
通过继承关系可以看到
ContextLoaderListener 继承了ServletContextListener 因此看contextInitialized()方法如何初始化initWebApplicationContext,而initWebApplicationContext()在ContextLoader里实现。
ContextLoaderListener#contextInitialized()
- public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
-
- public ContextLoaderListener() {
- }
-
- public ContextLoaderListener(WebApplicationContext context) {
- super(context);
- }
-
- /**
- * Initialize the root web application context.
- */
- @Override
- public void contextInitialized(ServletContextEvent event) {
- initWebApplicationContext(event.getServletContext());
- }
-
- }
ContextLoader#initWebApplicationContext();
- ContextLoader.java
-
- /**
- * The root WebApplicationContext instance that this loader manages.
- */
- @Nullable
- private WebApplicationContext context;
-
-
-
- /**
- * Initialize Spring's web application context for the given servlet context,
- * using the application context provided at construction time, or creating a new one
- * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
- * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
- * @param servletContext current servlet context
- * @return the new WebApplicationContext
- * @see #ContextLoader(WebApplicationContext)
- * @see #CONTEXT_CLASS_PARAM
- * @see #CONFIG_LOCATION_PARAM
- */
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- throw new IllegalStateException(
- "Cannot initialize context because there is already a root application context present - " +
- "check whether you have multiple ContextLoader* definitions in your web.xml!");
- }
-
- servletContext.log("Initializing Spring root WebApplicationContext");
- Log logger = LogFactory.getLog(ContextLoader.class);
- if (logger.isInfoEnabled()) {
- logger.info("Root WebApplicationContext: initialization started");
- }
- long startTime = System.currentTimeMillis();
-
- try {
- // Store context in local instance variable, to guarantee that
- // it is available on ServletContext shutdown.
- if (this.context == null) {
- //根据配置文件实例化xmlwebApplicationContext
- this.context = createWebApplicationContext(servletContext);
- }
- if (this.context instanceof ConfigurableWebApplicationContext) {
- ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
- 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 ->
- // determine parent for root web application context, if any.
- ApplicationContext parent = loadParentContext(servletContext);
- cwac.setParent(parent);
- }
- //调用spring ioc容器完成初始化
- configureAndRefreshWebApplicationContext(cwac, servletContext);
- }
- }
- // 将上下文放在servletContext中
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
-
- ClassLoader ccl = Thread.currentThread().getContextClassLoader();
- if (ccl == ContextLoader.class.getClassLoader()) {
- currentContext = this.context;
- }
- else if (ccl != null) {
- currentContextPerThread.put(ccl, this.context);
- }
-
- if (logger.isInfoEnabled()) {
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
- }
-
- return this.context;
- }
- catch (RuntimeException | Error ex) {
- logger.error("Context initialization failed", ex);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
- throw ex;
- }
- }
执行完上述后,由
Tomcat服务器继续执行后续代码过滤器filterStart、然后执行配置文件的
- StandardContext.java
-
-
- /**
- * Start this component and implement the requirements
- * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
- *
- * @exception LifecycleException if this component detects a fatal error
- * that prevents this component from being used
- */
- @Override
- protected synchronized void startInternal() throws LifecycleException {
-
- ......
-
- // Configure and call application event listeners
- if (ok) {
- //执行listener
- if (!listenerStart()) {
- log.error(sm.getString("standardContext.listenerFail"));
- ok = false;
- }
- }
-
- // Check constraints for uncovered HTTP methods
- // Needs to be after SCIs and listeners as they may programmatically
- // change constraints
- if (ok) {
- checkConstraintsForUncoveredMethods(findConstraints());
- }
-
- try {
- // Start manager
- Manager manager = getManager();
- if ((manager != null) && (manager instanceof Lifecycle)) {
- ((Lifecycle) manager).start();
- }
- } catch(Exception e) {
- log.error(sm.getString("standardContext.managerFail"), e);
- ok = false;
- }
-
- // Configure and call application filters
- if (ok) {
- //执行filter
- if (!filterStart()) {
- log.error(sm.getString("standardContext.filterFail"));
- ok = false;
- }
- }
-
- // Load and initialize all "load on startup" servlets
- //执行servlet
- if (ok) {
- if (!loadOnStartup(findChildren())){
- log.error(sm.getString("standardContext.servletFail"));
- ok = false;
- }
- }
-
- ......
-
- }
执行类StandardWarpper# private synchronized void initServlet(Servlet servlet)
- private synchronized void initServlet(Servlet servlet)
- throws ServletException {
-
- if (instanceInitialized && !singleThreadModel) return;
-
- // Call the initialization method of this servlet
- try {
- instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
- servlet);
-
- if( Globals.IS_SECURITY_ENABLED) {
- boolean success = false;
- try {
- Object[] args = new Object[] { facade };
- SecurityUtil.doAsPrivilege("init",
- servlet,
- classType,
- args);
- success = true;
- } finally {
- if (!success) {
- // destroy() will not be called, thus clear the reference now
- SecurityUtil.remove(servlet);
- }
- }
- } else {
- //调用servlet.init();
- servlet.init(facade);
- }
-
- instanceInitialized = true;
-
- instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
- servlet);
- } catch (UnavailableException f) {
- instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
- servlet, f);
- unavailable(f);
- throw f;
- } catch (ServletException f) {
- instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
- servlet, f);
- // If the servlet wanted to be unavailable it would have
- // said so, so do not call unavailable(null).
- throw f;
- } catch (Throwable f) {
- ExceptionUtils.handleThrowable(f);
- getServletContext().log("StandardWrapper.Throwable", f );
- instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
- servlet, f);
- // If the servlet wanted to be unavailable it would have
- // said so, so do not call unavailable(null).
- throw new ServletException
- (sm.getString("standardWrapper.initException", getName()), f);
- }
- }
由继承图可以看到,GenericServlet的init()方法由HttpServletBean的init()实现。
- GenericServlet.java
-
- /**
- * Called by the servlet container to indicate to a servlet that the servlet
- * is being placed into service. See {@link Servlet#init}.
- *
- * This implementation stores the {@link ServletConfig} object it receives
- * from the servlet container for later use. When overriding this form of
- * the method, call
super.init(config)
. - *
- * @param config
- * the
ServletConfig
object that contains - * configuration information for this servlet
- * @exception ServletException
- * if an exception occurs that interrupts the servlet's
- * normal operation
- * @see UnavailableException
- */
- @Override
- public void init(ServletConfig config) throws ServletException {
- this.config = config;
- this.init();
- }
-
-
- /**
- * A convenience method which can be overridden so that there's no need to
- * call
super.init(config)
. - *
- * Instead of overriding {@link #init(ServletConfig)}, simply override this
- * method and it will be called by
- *
GenericServlet.init(ServletConfig config)
. The - *
ServletConfig
object can still be retrieved via - * {@link #getServletConfig}.
- *
- * @exception ServletException
- * if an exception occurs that interrupts the servlet's
- * normal operation
- */
- public void init() throws ServletException {
- // NOOP by default
- }
而GenericServlet其自身this.init()方法是空的,需要子类HttpServletBean实现init()
- HttpServletBean.java
- /**
- * Map config parameters onto bean properties of this servlet, and
- * invoke subclass initialization.
- * @throws ServletException if bean properties are invalid (or required
- * properties are missing), or if subclass initialization fails.
- */
- @Override
- 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);
- }
- catch (BeansException ex) {
- if (logger.isErrorEnabled()) {
- logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
- }
- throw ex;
- }
- }
-
- // Let subclasses do whatever initialization they like.
- initServletBean();
- }
FrameworkServlet#initServletBean()
- FrameworkServlet.java
- /**
- * Overridden method of {@link HttpServletBean}, invoked after any bean properties
- * have been set. Creates this servlet's WebApplicationContext.
- */
- @Override
- protected final void initServletBean() throws ServletException {
- getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
- if (logger.isInfoEnabled()) {
- logger.info("Initializing Servlet '" + getServletName() + "'");
- }
- long startTime = System.currentTimeMillis();
-
- try {
- //创建webApplicationContext,默认由XmlWebApplicationContext实现
- this.webApplicationContext = initWebApplicationContext();
- //空实现
- initFrameworkServlet();
- }
- catch (ServletException | RuntimeException ex) {
- logger.error("Context initialization failed", ex);
- throw ex;
- }
-
- if (logger.isDebugEnabled()) {
- String value = this.enableLoggingRequestDetails ?
- "shown which may lead to unsafe logging of potentially sensitive data" :
- "masked to prevent unsafe logging of potentially sensitive data";
- logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
- "': request parameters and headers will be " + value);
- }
-
- if (logger.isInfoEnabled()) {
- logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
- }
- }
initWebApplicationContext()方法由ContextLoader.java实现。
- ContextLoader.java
-
- /**
- * Initialize Spring's web application context for the given servlet context,
- * using the application context provided at construction time, or creating a new one
- * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
- * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
- * @param servletContext current servlet context
- * @return the new WebApplicationContext
- * @see #ContextLoader(WebApplicationContext)
- * @see #CONTEXT_CLASS_PARAM
- * @see #CONFIG_LOCATION_PARAM
- */
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
- if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
- throw new IllegalStateException(
- "Cannot initialize context because there is already a root application context present - " +
- "check whether you have multiple ContextLoader* definitions in your web.xml!");
- }
-
- servletContext.log("Initializing Spring root WebApplicationContext");
- Log logger = LogFactory.getLog(ContextLoader.class);
- if (logger.isInfoEnabled()) {
- logger.info("Root WebApplicationContext: initialization started");
- }
- long startTime = System.currentTimeMillis();
-
- try {
- // Store context in local instance variable, to guarantee that
- // it is available on ServletContext shutdown.
- if (this.context == null) {
- this.context = createWebApplicationContext(servletContext);
- }
- if (this.context instanceof ConfigurableWebApplicationContext) {
- ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
- 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 ->
- // determine parent for root web application context, if any.
- ApplicationContext parent = loadParentContext(servletContext);
- cwac.setParent(parent);
- }
- configureAndRefreshWebApplicationContext(cwac, servletContext);
- }
- }
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
-
- ClassLoader ccl = Thread.currentThread().getContextClassLoader();
- if (ccl == ContextLoader.class.getClassLoader()) {
- currentContext = this.context;
- }
- else if (ccl != null) {
- currentContextPerThread.put(ccl, this.context);
- }
-
- if (logger.isInfoEnabled()) {
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
- }
-
- return this.context;
- }
- catch (RuntimeException | Error ex) {
- logger.error("Context initialization failed", ex);
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
- throw ex;
- }
- }
this.context = createWebApplicationContext(servletContext);
- /**
- * Instantiate the root WebApplicationContext for this loader, either the
- * default context class or a custom context class if specified.
- *
This implementation expects custom contexts to implement the
- * {@link ConfigurableWebApplicationContext} interface.
- * Can be overridden in subclasses.
- *
In addition, {@link #customizeContext} gets called prior to refreshing the
- * context, allowing subclasses to perform custom modifications to the context.
- * @param sc current servlet context
- * @return the root WebApplicationContext
- * @see ConfigurableWebApplicationContext
- */
- protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
- Class> contextClass = determineContextClass(sc);
- if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
- throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
- "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
- }
- //实例化
- return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
- }
configureAndRefreshWebApplicationContext(wac);
- protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
- if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
- // The application context id is still set to its original default value
- // -> assign a more useful id based on available information
- String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
- if (idParam != null) {
- wac.setId(idParam);
- }
- else {
- // Generate default id...
- wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
- ObjectUtils.getDisplayString(sc.getContextPath()));
- }
- }
-
- wac.setServletContext(sc);
- String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
- if (configLocationParam != null) {
- wac.setConfigLocation(configLocationParam);
- }
-
- // The wac environment's #initPropertySources will be called in any case when the context
- // is refreshed; do it eagerly here to ensure servlet property sources are in place for
- // use in any post-processing or initialization that occurs below prior to #refresh
- ConfigurableEnvironment env = wac.getEnvironment();
- if (env instanceof ConfigurableWebEnvironment) {
- ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
- }
-
- customizeContext(sc, wac);
- //调用AbstractApplicationContext refresh()方法
- wac.refresh();
- }
AbstractApplicationContext#refresh()
- @Override
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- // Prepare this context for refreshing.
- prepareRefresh();
-
- // Tell the subclass to refresh the internal bean factory.
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
-
- // Prepare the bean factory for use in this context.
- prepareBeanFactory(beanFactory);
-
- try {
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
-
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors(beanFactory);
-
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors(beanFactory);
-
- // Initialize message source for this context.
- initMessageSource();
-
- // Initialize event multicaster for this context.
- initApplicationEventMulticaster();
-
- // Initialize other special beans in specific context subclasses.
- onRefresh();
-
- // Check for listener beans and register them.
- registerListeners();
-
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
-
- // Last step: publish corresponding event.
- finishRefresh();
- }
-
- catch (BeansException ex) {
- if (logger.isWarnEnabled()) {
- logger.warn("Exception encountered during context initialization - " +
- "cancelling refresh attempt: " + ex);
- }
-
- // Destroy already created singletons to avoid dangling resources.
- destroyBeans();
-
- // Reset 'active' flag.
- cancelRefresh(ex);
-
- // Propagate exception to caller.
- throw ex;
- }
-
- finally {
- // Reset common introspection caches in Spring's core, since we
- // might not ever need metadata for singleton beans anymore...
- resetCommonCaches();
- }
- }
- }
// Last step: publish corresponding event.
finishRefresh();
- AbstractApplicationContext.java
-
- /**
- * Finish the refresh of this context, invoking the LifecycleProcessor's
- * onRefresh() method and publishing the
- * {@link org.springframework.context.event.ContextRefreshedEvent}.
- */
- protected void finishRefresh() {
- // Clear context-level resource caches (such as ASM metadata from scanning).
- clearResourceCaches();
-
- // Initialize lifecycle processor for this context.
- initLifecycleProcessor();
-
- // Propagate refresh to lifecycle processor first.
- getLifecycleProcessor().onRefresh();
-
- // Publish the final event.
- publishEvent(new ContextRefreshedEvent(this));
-
- // Participate in LiveBeansView MBean, if active.
- LiveBeansView.registerApplicationContext(this);
- }
-
- /**
- * Publish the given event to all listeners.
- *
Note: Listeners get initialized after the MessageSource, to be able
- * to access it within listener implementations. Thus, MessageSource
- * implementations cannot publish events.
- * @param event the event to publish (may be application-specific or a
- * standard framework event)
- */
- @Override
- public void publishEvent(ApplicationEvent event) {
- publishEvent(event, null);
- }
-
-
- /**
- * Publish the given event to all listeners.
- * @param event the event to publish (may be an {@link ApplicationEvent}
- * or a payload object to be turned into a {@link PayloadApplicationEvent})
- * @param eventType the resolved event type, if known
- * @since 4.2
- */
- protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
- Assert.notNull(event, "Event must not be null");
-
- // Decorate event as an ApplicationEvent if necessary
- ApplicationEvent applicationEvent;
- if (event instanceof ApplicationEvent) {
- applicationEvent = (ApplicationEvent) event;
- }
- else {
- applicationEvent = new PayloadApplicationEvent<>(this, event);
- if (eventType == null) {
- eventType = ((PayloadApplicationEvent>) applicationEvent).getResolvableType();
- }
- }
-
- // Multicast right now if possible - or lazily once the multicaster is initialized
- if (this.earlyApplicationEvents != null) {
- this.earlyApplicationEvents.add(applicationEvent);
- }
- else {
- getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
- }
-
- // Publish event via parent context as well...
- if (this.parent != null) {
- if (this.parent instanceof AbstractApplicationContext) {
- ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
- }
- else {
- this.parent.publishEvent(event);
- }
- }
- }
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
SimpleApplicationEventMulticaster.java
- SimpleApplicationEventMulticaster.java
-
-
- @Override
- public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
- ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
- Executor executor = getTaskExecutor();
- for (ApplicationListener> listener : getApplicationListeners(event, type)) {
- if (executor != null) {
- executor.execute(() -> invokeListener(listener, event));
- }
- else {
- invokeListener(listener, event);
- }
- }
- }
-
- private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
- return ResolvableType.forInstance(event);
- }
else {
invokeListener(listener, event);
}
- /**
- * Invoke the given listener with the given event.
- * @param listener the ApplicationListener to invoke
- * @param event the current event to propagate
- * @since 4.1
- */
- protected void invokeListener(ApplicationListener> listener, ApplicationEvent event) {
- ErrorHandler errorHandler = getErrorHandler();
- if (errorHandler != null) {
- try {
- doInvokeListener(listener, event);
- }
- catch (Throwable err) {
- errorHandler.handleError(err);
- }
- }
- else {
- doInvokeListener(listener, event);
- }
- }
else {
doInvokeListener(listener, event);
}
- @SuppressWarnings({"rawtypes", "unchecked"})
- private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
- try {
- listener.onApplicationEvent(event);
- }
- catch (ClassCastException ex) {
- String msg = ex.getMessage();
- if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
- // Possibly a lambda-defined listener which we could not resolve the generic event type for
- // -> let's suppress the exception and just log a debug message.
- Log logger = LogFactory.getLog(getClass());
- if (logger.isTraceEnabled()) {
- logger.trace("Non-matching event type for listener: " + listener, ex);
- }
- }
- else {
- throw ex;
- }
- }
- }
try {
listener.onApplicationEvent(event);
}
SourceFilteringListener.java
- @Override
- public void onApplicationEvent(ApplicationEvent event) {
- if (event.getSource() == this.source) {
- onApplicationEventInternal(event);
- }
- }
-
-
- /**
- * Actually process the event, after having filtered according to the
- * desired event source already.
- *
The default implementation invokes the specified delegate, if any.
- * @param event the event to process (matching the specified source)
- */
- protected void onApplicationEventInternal(ApplicationEvent event) {
- if (this.delegate == null) {
- throw new IllegalStateException(
- "Must specify a delegate object or override the onApplicationEventInternal method");
- }
- //这个this.delegate又委托GenericApplicationListenerAdapter类的onApplicationEvent方法
- this.delegate.onApplicationEvent(event);
- }
- GenericApplicationListenerAdapter.java
-
-
- @Override
- public void onApplicationEvent(ApplicationEvent event) {
- //这个this.delegate又委托ContextRefreshListener类的onApplicationEvent方法
- this.delegate.onApplicationEvent(event);
- }
事件源XmlWebApplicationContext
事件ContextRefreshedEvent
监听器 ContextRefreshListener
FrameworkServlet.java
- FrameworkServlet.java
-
-
- /**
- * ApplicationListener endpoint that receives events from this servlet's WebApplicationContext
- * only, delegating to {@code onApplicationEvent} on the FrameworkServlet instance.
- */
- //内部类
- private class ContextRefreshListener implements ApplicationListener
{ -
- @Override
- public void onApplicationEvent(ContextRefreshedEvent event) {
- FrameworkServlet.this.onApplicationEvent(event);
- }
- }
- FrameworkServlet.java
-
- /**
- * Callback that receives refresh events from this servlet's WebApplicationContext.
- *
The default implementation calls {@link #onRefresh},
- * triggering a refresh of this servlet's context-dependent state.
- * @param event the incoming ApplicationContext event
- */
- public void onApplicationEvent(ContextRefreshedEvent event) {
- this.refreshEventReceived = true;
- synchronized (this.onRefreshMonitor) {
- onRefresh(event.getApplicationContext());
- }
- }
-
-
-
- /**
- * Template method which can be overridden to add servlet-specific refresh work.
- * Called after successful context refresh.
- *
This implementation is empty.
- * @param context the current WebApplicationContext
- * @see #refresh()
- */
- protected void onRefresh(ApplicationContext context) {
- // For subclasses: do nothing by default.
- }
因为DispatcherServlet extends FrameworkServlet,所以执行子类DispatcherServlet#onRefresh()
- DispatcherServlet.java
-
- /**
- * This implementation calls {@link #initStrategies}.
- */
- @Override
- protected void onRefresh(ApplicationContext context) {
- initStrategies(context);
- }
-
- /**
- * Initialize the strategy objects that this servlet uses.
- *
May be overridden in subclasses in order to initialize further strategy objects.
- */
- protected void initStrategies(ApplicationContext context) {
- initMultipartResolver(context);
- initLocaleResolver(context);
- initThemeResolver(context);
- initHandlerMappings(context);
- initHandlerAdapters(context);
- initHandlerExceptionResolvers(context);
- initRequestToViewNameTranslator(context);
- initViewResolvers(context);
- initFlashMapManager(context);
- }
initStrategies就是springmvc大家熟悉的流程了。。。