使用java config 配置的spring mvc 启动过程分析
2018-01-13 19:00
561 查看
需要了解spring 3.0 的一些新特性
新特性可插拔的Web框架,几乎所有基于Java的web框架都建立在servlet之上。现今大多数web框架要么通过servlet、要么通过Web.xml插入。利用标注(Annotation)来定义servlet、listener、filter将使之(可插拔)成为可能程序访问web.xml和动态改变web应用配置是所期望的特性。该JSR将致力于提供把不同web框架无缝地插入到web应用的能力。
web-fragment.xml
http://jinnianshilongnian.iteye.com/blog/1750736
共享库 / 运行时可插拔性
在容器/应用启动时,由容器通过jar services API查找一个ServletContainerInitializer实例。框架提供的ServletContainerInitializer实现必须绑定在jar包的META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer的文件中,根据每个jar services API,指定ServletContainerInitializer的实现类。
@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包缺失,容器可能遇到类装载问题。由于容器不能决定是否这些类型的类装载失败将阻止应用正常工作,它必须忽略它们,同时也提供一个将记录它们的配置选项。
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
AbstractDispatcherServletInitializer.java
关键类: AbstractDispatcherServletInitializer.java //关键方法 @Override public void onStartup(ServletContext servletContext) throws ServletException { //首先注册根容器 super.onStartup(servletContext); //注册 spring mvc 的 DispatcherServlet registerDispatcherServlet(servletContext); } super.onStartup(servletContext);父类的启动方法做了什么
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"); } }
到此以上的过程都是为了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 子容器
相关文章推荐
- 如何使用纯java config来配置spring mvc
- spring mvc应用基于Java config配置是怎么启动的
- 使用JavaConfig来配置Spring MVC中的DispatcherServlet
- 使用java config 配置spring 和spring mvc
- Spring(三):使用java config配置spring mvc
- Spring Web工程web.xml零配置即使用Java Config + Annotation
- 使用java配置类实现spring mvc的拦截器
- .嵌入式jetty启动spring(java配置方式),junit测试用.标准spring 配置(java config) 嵌入式jetty9启动
- Spring MVC 菜鸟教程 7 标签mvc:interceptors和java config配置拦截器
- Spring MVC 零配置 / Spring MVC JavaConfig
- Servlet(8)Servlet配置细节(包括web应用启动即加载Servlet类)及ServletConfig使用
- Spring MVC 零配置 / Spring MVC JavaConfig
- java学习笔记9 - Spring mvc中log4j的配置与使用
- Spring MVC 笔记--配置基于JavaConfig
- Java使用JNA或者JNative调C++的DLL报DLL NOT FOUND或者应用程序无法启动因为并行配置不正确
- Java opencsv--使用 Spring 的 PostConstruct机制,项目启动时,将CSV配置文件读取到内存 map 中
- 译--Spring中 bean定义profiles的使用 javaConfig 和XML配置
- 考虑使用JavaConfig替代XML配置
- Spring MVC 零配置 / Spring MVC JavaConfig
- CAS client客户端的配置,使用java config的方式