烟台网站seo,傻瓜式网站制作,重新wordpress默认,美工培训班线上前面的文章介绍了用 WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 来代替 web.xml 。 我们学 java web 的时候就知道#xff0c;servlet 容器会自动加载 web.xml。 那么#xff0c;疑问就来了#xff0c;WebApplicationInitialize…前面的文章介绍了用 WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 来代替 web.xml 。 我们学 java web 的时候就知道servlet 容器会自动加载 web.xml。 那么疑问就来了WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 既然替代了 web.xml那应该也会被 servlet 容器加载是不是这样呢答案是是的。 而完成这个加载工作的是 SpringServletContainerInitializer 类。看下它的源码
package org.springframework.web; import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils; /**
* 本类继承了 servlet 3.0 的 ServletContainerInitializer 接口。
* 下面这段话的意思是
* servlet 3.0 的 ServletContainerInitializer 接口是用来让 servlet 容器支持基于编码的配置。
* 在这个过程中要结合 spring 的 WebApplicationInitializer。
* 而 spring 的 WebApplicationInitializer 可以替换 web.xml 也可以结合 web.xml 一起使用。
*
* Servlet 3.0 {link ServletContainerInitializer} designed to support code-based
* configuration of the servlet container using Springs {link WebApplicationInitializer}
* SPI as opposed to (or possibly in combination with) the traditional
* {code web.xml}-based approach.
*
* 当 servlet 容器启动的时候如果累路径下有 spring-web 的话这个类会被加载并且 onStartup 方法会被调用。
* 这背后的原理在于 java 的 SPI 机制。
* spring-web 模块下有个 META-INF/services/javax.servlet.ServletContainerInitializer 文件
* 其内容就是当前类的完全限定名。
*
* h2Mechanism of Operation/h2
* This class will be loaded and instantiated and have its {link #onStartup}
* method invoked by any Servlet 3.0-compliant container during container startup assuming
* that the {code spring-web} module JAR is present on the classpath. This occurs through
* the JAR Services API {link ServiceLoader#load(Class)} method detecting the
* {code spring-web} modules {code META-INF/services/javax.servlet.ServletContainerInitializer}
* service provider configuration file. See the
* a hrefhttp://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
* JAR Services API documentation/a as well as section em8.2.4/em of the Servlet 3.0
* Final Draft specification for complete details.
*
* h3In combination with {code web.xml}/h3
* A web application can choose to limit the amount of classpath scanning the Servlet
* container does at startup either through the {code metadata-complete} attribute in
* {code web.xml}, which controls scanning for Servlet annotations or through an
* {code absolute-ordering} element also in {code web.xml}, which controls which
* web fragments (i.e. jars) are allowed to perform a {code ServletContainerInitializer}
* scan. When using this feature, the {link SpringServletContainerInitializer}
* can be enabled by adding spring_web to the list of named web fragments in
* {code web.xml} as follows:
*
* pre classcode
* {code
* absolute-ordering
* namesome_web_fragment/name
* namespring_web/name
* /absolute-ordering
* }/pre
*
* SpringServletContainerInitializer 可以看做一个简单的代理真正的工作还是交给了 WebApplicationInitializer 。
*
* h2Relationship to Springs {code WebApplicationInitializer}/h2
* Springs {code WebApplicationInitializer} SPI consists of just one method:
* {link WebApplicationInitializer#onStartup(ServletContext)}. The signature is intentionally
* quite similar to {link ServletContainerInitializer#onStartup(Set, ServletContext)}:
* simply put, {code SpringServletContainerInitializer} is responsible for instantiating
* and delegating the {code ServletContext} to any user-defined
* {code WebApplicationInitializer} implementations. It is then the responsibility of
* each {code WebApplicationInitializer} to do the actual work of initializing the
* {code ServletContext}. The exact process of delegation is described in detail in the
* {link #onStartup onStartup} documentation below.
*
* h2General Notes/h2
* In general, this class should be viewed as emsupporting infrastructure/em for
* the more important and user-facing {code WebApplicationInitializer} SPI. Taking
* advantage of this container initializer is also completely emoptional/em: while
* it is true that this initializer will be loaded and invoked under all Servlet 3.0
* runtimes, it remains the users choice whether to make any
* {code WebApplicationInitializer} implementations available on the classpath. If no
* {code WebApplicationInitializer} types are detected, this container initializer will
* have no effect.
*
* pNote that use of this container initializer and of {code WebApplicationInitializer}
* is not in any way tied to Spring MVC other than the fact that the types are shipped
* in the {code spring-web} module JAR. Rather, they can be considered general-purpose
* in their ability to facilitate convenient code-based configuration of the
* {code ServletContext}. In other words, any servlet, listener, or filter may be
* registered within a {code WebApplicationInitializer}, not just Spring MVC-specific
* components.
*
* 注意不要扩展这个类也不要继承这个类。
* 这个类应该被视为内部类型不对外。
* 对外的是 WebApplicationInitializer。
*
* pThis class is neither designed for extension nor intended to be extended.
* It should be considered an internal type, with {code WebApplicationInitializer}
* being the public-facing SPI.
*
* h2See Also/h2
* See {link WebApplicationInitializer} Javadoc for examples and detailed usage
* recommendations.p
*
* author Chris Beams
* author Juergen Hoeller
* author Rossen Stoyanchev
* since 3.1
* see #onStartup(Set, ServletContext)
* see WebApplicationInitializer
*/
HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer { { System.out.println(HandlesTypes(WebApplicationInitializer.class) 这个注解表明了当前类 SpringServletContainerInitializer 需要处理的类型是 WebApplicationInitializer );
} /**
* Delegate the {code ServletContext} to any {link WebApplicationInitializer}
* implementations present on the application classpath.
*
* pBecause this class declares {code HandlesTypes(WebApplicationInitializer.class)},
* Servlet 3.0 containers will automatically scan the classpath for implementations
* of Springs {code WebApplicationInitializer} interface and provide the set of all
* such types to the {code webAppInitializerClasses} parameter of this method.
* pIf 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.
* pAssuming that one or more {code WebApplicationInitializer} types are detected,
* they will be instantiated (and emsorted/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 Springs
* {code DispatcherServlet}, listeners such as Springs {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 SetClass? webAppInitializerClasses, ServletContext servletContext)
throws ServletException { servletContext.log(SpringServletContainerInitializer 利用了 java 的 SPI 机制); ListWebApplicationInitializer 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);
}
}
}
} System.out.println(SpringServletContainerInitializer 在其 onStartup 方法中检测类路径下的 WebApplicationInitializerspring的 ); if (initializers.isEmpty()) {
servletContext.log(在类路径下没有检测到 spring 的 WebApplicationInitializer。------- No Spring WebApplicationInitializer types detected on classpath);
return;
} System.out.println(在类路径下检测到了 initializers.size() 个 spring 的 WebApplicationInitializer。); servletContext.log(initializers.size() Spring WebApplicationInitializers detected on classpath); AnnotationAwareOrderComparator.sort(initializers); System.out.println(依次调用 WebApplicationInitializer 的 onStartup 方法); for (WebApplicationInitializer initializer : initializers) { System.out.println(调用 initializer.getClass().getName() 的 onStartup 方法); initializer.onStartup(servletContext);
} System.out.println(至此通过 servlet、java spi 成功引导了 spring ); } }关于这个类有几个需要注意的点
它实现了 servlet 3.0 的 javax.servlet.ServletContainerInitializer 接口它加了个 HandlesTypes(WebApplicationInitializer.class) 注解它实现了 javax.servlet.ServletContainerInitializer 接口中定义的 onStartup 方法
总结下来。SpringServletContainerInitializer 这个类实现了 servlet 3.0 的 javax.servlet.ServletContainerInitializer 接口这就决定了在 servlet 容器启动的时候 onStartUp 方法会被自动触发而在 onStartUp 方法内部 WebApplicationInitializer 的 onStartUp 方法被调用。这就是 WebApplicationInitializer 被容器带起来的过程。
这里只是说了个大概要想非常清楚还请自己研究下 servlet 3.0 的 javax.servlet.ServletContainerInitializer 接口。