SpringMVC的IOC容器的初始化

本文详细介绍了SpringMVC的IOC容器初始化过程,从Servlet3.0的WebApplicationInitializer开始,逐步解析父容器和子容器的加载,包括ContextLoaderListener的配置、DispatcherServlet的注册与初始化,以及Servlet的四个初始化步骤。文章强调了ContextLoader和FrameworkServlet在SpringMVC中的关键作用和设计模式的应用。
摘要由CSDN通过智能技术生成

SpringMVC的IOC容器的初始化

1.引导spring应用加载

首先,Servlet3.0的Web应用服务器中,例如Tomcat7或更高版本,服务器会在启动的时候在类路径下查找javax.servlet.ServletContainerInitializer接口的实现类(利用SPI原理),引导spring应用启动。执行实现WebApplicationInitializer类的onStartup方法

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

   /**
    * Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
    * implementations present on the application classpath.
    * <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
    * Servlet 3.0+ containers will automatically scan the classpath for implementations
    * of Spring's {@code WebApplicationInitializer} interface and provide the set of all
    * such types to the {@code webAppInitializerClasses} parameter of this method.
    * <p>If no {@code WebApplicationInitializer} implementations are found on the classpath,
    * this method is effectively a no-op. An INFO-level log message will be issued notifying
    * the user that the {@code ServletContainerInitializer} has indeed been invoked but that
    * no {@code WebApplicationInitializer} implementations were found.
    * <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
    * they will be instantiated (and <em>sorted</em> if the @{@link
    * org.springframework.core.annotation.Order @Order} annotation is present or
    * the {@link org.springframework.core.Ordered Ordered} interface has been
    * implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
    * method will be invoked on each instance, delegating the {@code ServletContext} such
    * that each instance may register and configure servlets such as Spring's
    * {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
    * or any other Servlet API componentry such as filters.
    * @param webAppInitializerClasses all implementations of
    * {@link WebApplicationInitializer} found on the application classpath
    * @param servletContext the servlet context to be initialized
    * @see WebApplicationInitializer#onStartup(ServletContext)
    * @see AnnotationAwareOrderComparator
    *
    */
   @Override
   public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
         throws ServletException {
   

      List<WebApplicationInitializer> 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 {
   
                  //实例化WebApplicationInitializer子类
                  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) {
   
         initializer.onStartup(servletContext);
      }
   }

}

可以看到onStartup方法有两个参数,Set webAppInitializerClasses 和 ServletContext ctx。

  • 如果ServletContainerInitializer接口的实现类使用@HandlesTypes注解声明了感兴趣的类或接口,那么这个感兴趣的类及其子类或接口的实现类就会被设置到webAppInitializerClasses参数中。
  • ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。由服务器创建

webAppInitializerClasses 中包括了WebApplicationInitializer类所有的子类。但是在代码中只有实体类才会进行处理并调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ctJ96pqd-1646276328504)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220303104905952.png)]
排序后进行实例化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybe8f0PA-1646276328505)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220303105038355.png)]

2.WebApplicationInitializer子类的实例化

WebApplicationInitializer类的作用用于配置Servlet容器,例如注册Servlet、Filter或Listener以取代以取代通过web.xml配置注册。这样就利于开发内聚的web应用框架.

WebApplicationInitializer下有两个子类分别为AbstractContextLoaderInitializer和AbstractDispatcherServletInitializer前者用于根容器的加载。后者用于子容器的加载。
在这里插入图片描述
看AbstractDispatcherServletInitializer#onStartup的实现

public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {
   

   /**
    * The default servlet name. Can be customized by overriding {@link #getServletName}.
    */
   public static final String DEFAULT_SERVLET_NAME = "dispatcher";


   @Override
   public void onStartup(ServletContext servletContext) throws ServletException {
   
      //注册ContextLoaderListener监听器,让它去初始化Spring父容器
      super.onStartup(servletContext);
      //注册DispatcherServlet,让它去初始化Spring MVC的子容器
      registerDispatcherServlet(servletContext);
   }
  }

3.父容器的加载

super的onStartup主要负责父容器的初始化

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
   
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值