1 ServletContainerInitializer
When web container starts to third-party components to provide the opportunity to do some initialization work, ServletContainerInitializer implement this feature servlet specification (JSR356) by. Each frame you want to use ServletContainerInitializer you must create a file named javax.servlet.ServletContainerInitializer in the corresponding jar package META-INF / services directory, file content to assign specific ServletContainerInitializer implementation class, then it will start when the web container run the initialization is done some initial work in the components.
(1) Create a JAVA-WEB project
(2) create the interface and interface related classes
public interface ZrsService {
}
public interface ZrsServiceExtend extends ZrsService {
}
public abstract class AbstractZrsService implements ZrsService {
}
public class ZrsServicImpl implements ZrsService {
}
(3) create ServletContainerInitializer interface class
/**
* @Description: HandlesTypes,获取当前接口所有相关的类
* @Auther: zhurongsheng
* @Date: 2020/3/5 15:14
*/
@HandlesTypes(value = {ZrsService.class})
public class ZrsServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> classs, ServletContext servletContext) throws ServletException {
System.out.println("################################");
for (Class clazz:classs){
System.out.println(clazz);
}
}
}
(4) create javax.servlet.ServletContainerInitializer in the META-INF / services
com.servlet.ZrsServletContainerInitializer
(5) engineering structures
(6) to start tomcat, found a method called ZrsServletContainerInitializer onStartup
2 SpringMVC environment ready
(1) create a maven project
(2) Delete all * .xml files in the webapp
(3) introduced dependence
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArguments>
<extdirs>${basedir}/src/main/webapp/WEB-INF/lib</extdirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
3 View spring-web package
4 Preliminary analysis SpringServletContainerInitializer
(1) source code analysis, initialization WebApplicationInitializer bean interface and call methods WebApplicationInitializer implementation class onStartup
/**
* 获取WebApplicationInitializer接口的所有类型
*/
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
//1 创建存储WebApplicationInitializer的List
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 {
//2 用反射机制创建WebApplicationInitializer实现类并且添加到List中
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);
//3 调用WebApplicationInitializerde的onStartup方法
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
(2) WebApplicationInitializer interface class analysis AbstractContextLoaderInitializer
(3) WebApplicationInitializer interface class analysis AbstractDispatcherServletInitializer
(4) WebApplicationInitializer interface class analysis AbstractAnnotationConfigDispatcherServletInitializer
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
extends AbstractDispatcherServletInitializer {
/**
* 创建RootApplicationContext
*/
@Override
@Nullable
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(configClasses);
return context;
}
else {
return null;
}
}
/**
* 创建ServletApplicationContext
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
context.register(configClasses);
}
return context;
}
/**
* 获取RootApplicationContext 配置类
*/
@Nullable
protected abstract Class<?>[] getRootConfigClasses();
/**
* 获取ServletApplicationContext配置类
*/
@Nullable
protected abstract Class<?>[] getServletConfigClasses();
}
(5) ServletApplicationContext and RootApplicationContext difference in the following figure:
ServletApplicationContext: Controller is responsible for the relevant view ...
RootApplicationContext: responsible for Service, database-related ...