SpringMVC源码解读
·springMVC中取消了web.xml文件,那么web容器的组件应该怎么加到容器中呢?

在src同级目录下建立META-INF文件夹,里面还有个services文件夹,中间有个javax.servlet.ServletContainerInitializer文件,其中定义了自定义的ServletContainerInitializer的全路径。
这个自定义的入口应该怎么定义呢?

首先要实现ServletContainerInitializer方法,实现其中的onStartup方法,
arg0:感兴趣的类的子类型(一个接口的所有实现)
ServletContext:代表当前web应用,可以注册三大组件
那么这些参数怎么传入呢?
在自定义类上面加上@HandlesTypes注解里面有values,写入接口,这就是arg0
获取到arg0之后需要通过反射机制来创建想要的对象
·········此时tomcat还没有启动,可以在这里做一些校验工作
·用ServletContext来注册我们的组件
arg1.addServlet('OrderServlet', new OrderServlet());//注册servlet组件

后续还会加上url

接下来注册Listener、Filter


·SpringMVC和IOC容器都不能在运行时加新的bean
SPRING-MVC源码解读
首先在pom文件中加入我们需要的依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
在外部jar中

由前所述,里面的内容是
org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)//指定我们需要加载的类型
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// 判断是不是接口,如果是接口时不可行的,因为接口不能被实例化
//再判断是不是抽象的
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
//通过newInstance来实例化类放进容器
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);
}
}
}
我们来看一下核心类:
WebApplicationInitializer.class
实现类1:
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {
protected final Log logger = LogFactory.getLog(getClass());
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//看名字就知道是用来注册监听器的
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
//这里新建Web的根容器,主要处理和web相关的bean

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");
}
}
实现类2:顾名思义,用来注册DispatcherServlet

通过一般servlet注册方法注册
·实现类3:

自己实例了一个容器:AnnotationConfigWebApplicationContext

Root容器和Servlet容器实例化代码:
自定义继承AbstractAnnotationConfigDispatcherServletInitializer的类:

自定义的Config,注意
useDefaultFilters = false

·接管application-mvc.xml

浙公网安备 33010602011771号