使用java config 配置的spring mvc 启动过程分析

需要了解spring 3.0 的一些新特性

  1. 新特性
    可插拔的Web框架,几乎所有基于Java的web框架都建立在servlet之上。现今大多数web框架要么通过servlet、要么通过Web.xml插入。利用标注(Annotation)来定义servlet、listener、filter将使之(可插拔)成为可能程序访问web.xml和动态改变web应用配置是所期望的特性。该JSR将致力于提供把不同web框架无缝地插入到web应用的能力。
  1. web-fragment.xml
http://jinnianshilongnian.iteye.com/blog/1750736
  1. 共享库 / 运行时可插拔性
    在容器/应用启动时,由容器通过jar services API查找一个ServletContainerInitializer实例。框架提供的ServletContainerInitializer实现必须绑定在jar包的META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer的文件中,根据每个jar services API,指定ServletContainerInitializer的实现类。
  1. @HandlesTypes(WebApplicationInitializer.class)
HandlesTypes注解作用:
    在容器/应用启动时,由容器通过jar services API查找一个ServletContainerInitializer实例。框架提供的ServletContainerInitializer实现必须绑定在jar包的META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer的文件,根据jar services API,指定ServletContainerInitializer的实现。除ServletContainerInitializer外,我们还有一个注解—HandlesTypes。在ServletContainerInitializer 实现上的HandlesTypes注解用于表示感兴趣的一些类,它们可能指定了HandlesTypes的value中的注解(类型、方法或自动级别的注解),或者是其类型的超类继承/实现了这些类之一。
    容器使用HandlesTypes注解决定什么时候调用initializer的onStartup方法。当检测一个应用的类看是否它们匹配ServletContainerInitializer的HandlesTypes指定的条件时,
    如果应用的一个或多个可选的JAR包缺失,容器可能遇到类装载问题。由于容器不能决定是否这些类型的类装载失败将阻止应用正常工作,它必须忽略它们,同时也提供一个将记录它们的配置选项。
  1. SpringServletContainerInitializer
org/springframework/spring-web/4.3.12.RELEASE/spring-web-4.3.12.RELEASE.jar!/META-INF/services/javax.servlet.ServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)//感兴趣的类 
public class SpringServletContainerInitializer implements ServletContainerInitializer {

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

        //WebApplicationInitializer 所有的子类集合
        List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

        //只把自定义的配置类继承自 AbstractAnnotationConfigDispatcherServletInitializer 添加到集合中去
        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) 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);//WebApplicationInitializer.onStartup() 开始spring 框架的加载
        }
    }

}

http://blog.csdn.net/wangyangzhizhou/article/details/52013779
  1. AbstractDispatcherServletInitializer.java

关键类:
AbstractDispatcherServletInitializer.java

    //关键方法
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
         //首先注册根容器
        super.onStartup(servletContext);
        //注册 spring mvc 的 DispatcherServlet
        registerDispatcherServlet(servletContext);
    }
super.onStartup(servletContext);父类的启动方法做了什么
  1. AbstractContextLoaderInitializer.java

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        registerContextLoaderListener(servletContext);
    }


    protected void registerContextLoaderListener(ServletContext servletContext) {
        WebApplicationContext rootAppContext = createRootApplicationContext();
        if (rootAppContext != null) {
            ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
            //监听器注册
            listener.setContextInitializers(getRootApplicationContextInitializers());
            servletContext.addListener(listener);
        }
        else {
            logger.debug("No ContextLoaderListener registered, as " +
                    "createRootApplicationContext() did not return an application context");
        }
    }
  1. 到此以上的过程都是为了spring 容器启动做的一些配置(可以理解为替代wem.xml 的所使用的 java config)
//ContextLoaderListener 监听器上场
监听器:
EventListener.java
    https://www.cnblogs.com/atyou/archive/2013/01/07/2850321.html 使用,serlvet使用的这种机制来实现事件触发对listener的通知

ServletContextListener.java
    这个接口接收事件通知,关于ServletContext 生命周期的变化,servlet filter 等监听

ContextLoaderListener.java
    spring mvc Bootstrap listener to start up and shut down Spring's root

//启动类监听到serlvet上下文启动然后开始初始化上spring下文

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) {
        //初始化spring容器
        initWebApplicationContext(event.getServletContext());
    }

    // Close the root web application context.     
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        //销毁spring容器 ( 就是当DispatcherServlet销毁的时候 )
        closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }

}

至此就开始初始化spring 父(根)容器和spring mvc 子容器

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值