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

  

 

posted @ 2020-05-09 22:39  莫西123  阅读(231)  评论(0)    收藏  举报