(四)Spring源码分析--SpringMVC加载原理

SpringMVC是如何与我们的Spring容器整合的?它的工作机制又是如何?下面我们将通过源码来一起揭开它的神秘面纱。

谈到SpringMVC就离不开我们的servlet,在servlet3.0规范中当容器启动时会寻找每一个jar包下的SevletContainerInitializer接口实现类,执行实现类的onStartup()方法。那么容器是如何去寻找jar包中的接口实现类的呢?它会扫描每个jar包下元数据文件META-INF下的services文件夹中有没有以接口全类名命名的文件javax.servlet.ServletContainerInitializer,如果存在此文件那么文件中的内容就是接口实现类的类名:

(四)Spring源码分析--SpringMVC加载原理_第1张图片

通过接口实现全类名找到SpringServletContainerInitializer类。

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

	@Override
	public void onStartup(@Nullable Set> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List initializers = new LinkedList<>();

		if (webAppInitializerClasses != null) {
			for (Class waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer)
								ReflectionUtils.accessibleConstructor(waiClass).newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
 		for (WebApplicationInitializer initializer : initializers) {
                       // 重点  实际调用的时WebApplicationInitializer实现类的onStartup方法
			initializer.onStartup(servletContext);
		}
	}

}

阅读上面源码时,我们首先要明白@HandlesTypes注解的作用,HandlesTypes注解用于注册我们感兴趣的接口,在onStartup()方法中就hi将此接口的所有实现类和子类都放置在Set>中传递给应用程序,在此处我们注册了感兴趣的WebApplicationInitializer接口,在调用onStarup时实际是调用WebApplicationInitializer接口实现类的onStartup方法,我们来看看接口有哪些实现类:它有一个顶层抽象类AbstractContextLoaderInitializer和两个子抽象类,我们分别来看看它们的作用

(四)Spring源码分析--SpringMVC加载原理_第2张图片

AbstactContextLoaderInitializer: 它的作用主要是创建一个监听器,然后用监听器来创建SpringMvc中的父容器

public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
    protected final Log logger = LogFactory.getLog(this.getClass());

    public AbstractContextLoaderInitializer() {
    }
    // 创建SpringMvc中的父容器
    public void onStartup(ServletContext servletContext) throws ServletException {
        this.registerContextLoaderListener(servletContext);
    }

    protected void registerContextLoaderListener(ServletContext servletContext) {
        // 通过监听器来创建父容器
        WebApplicationContext rootAppContext = this.createRootApplicationContext();
        if (rootAppContext != null) {
            ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
            listener.setContextInitializers(this.getRootApplicationContextInitializers());
            servletContext.addListener(listener);
        } else {
            this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not return an application context");
        }

    }

    protected abstract WebApplicationContext createRootApplicationContext();

    protected ApplicationContextInitializer[] getRootApplicationContextInitializers() {
        return null;
    }
}

AbstractDispatcherServletInitializer:它的作用主要是创建一个DispatcherServlet并将子类创建好的子容器添加进去,从而完成SpringMvc的整合配置

public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
    public static final String DEFAULT_SERVLET_NAME = "dispatcher";

    public AbstractDispatcherServletInitializer() {
    }

    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        // 创建DispatcherServlet
        this.registerDispatcherServlet(servletContext);
    }

    protected void registerDispatcherServlet(ServletContext servletContext) {
        String servletName = this.getServletName();
        // 创建SpringMvc中的子容器 在其子类中实现
        WebApplicationContext servletAppContext = this.createServletApplicationContext();
        FrameworkServlet dispatcherServlet = this.createDispatcherServlet(servletAppContext);
        dispatcherServlet.setContextInitializers(this.getServletApplicationContextInitializers());
        // 添加servlet
        Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
               registration.setLoadOnStartup(1);
        registration.addMapping(this.getServletMappings());
        registration.setAsyncSupported(this.isAsyncSupported());
        Filter[] filters = this.getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            Filter[] var7 = filters;
            int var8 = filters.length;

            for(int var9 = 0; var9 < var8; ++var9) {
                Filter filter = var7[var9];
                this.registerServletFilter(servletContext, filter);
            }
        }

        this.customizeRegistration(registration);
    }

 

 

你可能感兴趣的:(java基础)