springmvc 父子容器的创建

本文介绍了如何使用Spring整合SpringMVC时,通过SPI机制实现自动扫描和初始化,重点剖析了SpringServletContainerInitializer的工作原理和关键方法。展示了如何利用WebApplicationInitializer接口在Tomcat启动时自动执行子类的配置过程。
摘要由CSDN通过智能技术生成

1. spring整合springmvc早期是通过配置web.xml配置前端控制器、监听器

2. 基于Java Config的方式,就是利用SPI机制

什么是SPI机制?工程演示见GitHub

① Tomcat 作为服务者,提供 javax.servlet.ServletContainerInitializer 这个接口

② 应用程序只要实现这个接口,并且在对应目录下添加配置文件。在启动Tomcat时,Tomcat就会调用实现该接口的onStartup()方法

③ spring-web 项目实现SPI机制,详见 SpringServletContainerInitializer 这个类

3.SpringServletContainerInitializer 源码分析

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

    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
        List<WebApplicationInitializer> initializers = new LinkedList();
        Iterator var4;
        if (webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
        } else {
            servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
            AnnotationAwareOrderComparator.sort(initializers);
            var4 = initializers.iterator();

            while(var4.hasNext()) {
                WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
                initializer.onStartup(servletContext);
            }

        }
    }
}

① @HandlesTypes({WebApplicationInitializer.class}),这个注解的作用会自动扫描所有实现WebApplicationInitializer接口的子类,作为onStartup()方法入参,即对应的webAppInitializerClasses

② 如果子类不是抽象类的、也不是接口,就会实例化。然后调用onStartup()方法,所以程序只要实现Spring提供的WebApplicationInitializer接口,就会在tomcat启动时,调用子类的onStartup()方法

4.onStartup方法源码分析

① 应用程序实现WebApplicationInitializer接口,如果没有重写onStartup方法,就会调用父类AbstractDispatcherServletInitializer的

② AbstractDispatcherServletInitializer的onStartup方法,源码分析

  1. 再调用它父类AbstractContextLoaderInitializer的onStartup方法:
    1. 创建spring父容器,设置扫描的配置类(应用程序重写该方法,设置父容器扫描的配置类)
    2. 创建ContextLoaderListener监听器,对父容器进行封装
    3. 将监听器设置到servletContext
  2. 调用本类的方法,注册DispatcherServlet:
    1. 创建springmvc子容器,设置扫描的配置类(应用程序重写该方法,设置子容器扫描的配置类。在配置类上添加@EnableWebMvc,利用SpringBoot自动装配机制就会自动注册springmvc的相关组件)
    2. 创建 DispatcherServlet,对子容器进行封装
    3. 将DispatcherServle设置到servletContext
    4. 设置启动时立即加载,设置DispatcherServlet的过滤器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值