这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
1、SpringMVC核心6大组件简介
1.1 Dispatcher 前端控制器
用于请求达到前端处理器之后,交由此处理器进行请求的分发逻辑,是SpringMVC中的C, 是整个调用流程的控制中心,由此组件来发起对其他组件的调用请求,此组件极大降低了各个组件之间的强耦合。
1.2 HandlerMapping 处理器映射器
处理器映射器,此组件负责根据请求来找到对应的处理器,常用的映射器有BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、RequestMappinghandlerMappping三类,分别对应不同的映射器实现,如:XML配置文件方式、接口实现方式、注解实现方式。
1.3 Handler 核心处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下 Handler对具体的用户请求进行处理。 由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
1.4 HandlerAdapter 处理器适配器
处理器适配器,通过不同的适配逻辑,来返回不同类型的处理器适配器,来调用处理器的具体实现方法。通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的 处理器进行执行。
1.5 ViewResolver 视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。最终一般返回ModelAndView给用户。
1.6 View 视图控制器
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、 pdfView等。我们最常用的视图就是JSP。 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
2、核心入口源码分析
2.1 容器初始化流程
2.1.1 HttpServletBean#init
DispatcherServlet继承FrameworkServlet,后者继承HttpServletBean, 此对象继承了HttpServlet,最终定位方法为重写的init方法
public final void init() throws ServletException {
// Set bean properties from init parameters.
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),
this.requiredProperties);
if (!pvs.isEmpty()) {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new
ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader,
getEnvironment()));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
}
// Let subclasses do whatever initialization they like.
initServletBean();
}
2.1.2 调用 initServletBean()
不过该方法需要去 HttpServletBean 的子类FrameworkServlet 中去看
protected final void initServletBean() throws ServletException {
long startTime = System.currentTimeMillis();
try {
// 初始化web环境中的spring容器WebApplicationContext
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
}
2.1.3 创建Spring Web容器
以下是根据 springmvc.xml 配置文件创建 spring 容器, onRefresh() 方法是初始化一些默认组件,比如 HandlerMapping 组件中的( BeanNameURLHandlerMapping )
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)
wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
wac = findWebApplicationContext();
}
if (wac == null) {
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// 刷新容器中的策略
onRefresh(wac);
}
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
// 将spring容器存入到ServletContext上下文
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
2.2 核心组件初始化流程
onRefresh(wac)刷新容器方法,最终实现在DispatcherServlet
protected void onRefresh(ApplicationContext context) {
// 初始化策略容器
initStrategies(context);
}
下面看实现,初始化了一系列解析器, 里面包含处理器适配器Aadapter和处理器映射器HandlerMapping
protected void initStrategies(ApplicationContext context) {
// 初始化多部件解析器
initMultipartResolver(context);
// 初始化国际化解析器
initLocaleResolver(context);
// 初始化主题解析器
initThemeResolver(context);
// 初始化处理器映射器
initHandlerMappings(context);
// 初始化处理器适配器
initHandlerAdapters(context);
// 初始化异常解析器
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
// 初始会视图解析器
initViewResolvers(context);
initFlashMapManager(context);
}
2.2.1 查找并创建处理器映射器
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// 从当前spring容器和其祖先容器中,查找到所有的处理器映射器
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME,
HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
}
if (this.handlerMappings == null) {
// 如果没有从spring容器中获取到HandlerMapping,
// 则从默认DispatcherServlet.properties文件中加载默认策略
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}
}
上下文都不存在具体的映射器实现策略时,常见默认的策略定义, 从DispatcherServlet.properties文件中加载默认策略
static {
try {
// 加载 DispatcherServlet.properties配置文件
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
// 加载默认策略(包括处理器适配器、处理器映射器、视图解析器这三大组件的默认策略)
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 获取策略接口的名称
String key = strategyInterface.getName();
// 获取具体策略类的名称
String value = defaultStrategies.getProperty(key);
if (value != null) {
// 获取所有具体策略类的名称集合
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
Class<?> clazz = ClassUtils.forName(className,
DispatcherServlet.class.getClassLoader());
// 创建具体的策略实例
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
}
return strategies;
}
else {
return new LinkedList<>();
}
}
具体试下类图说明如下:
2.2.2 查找并创建处理器适配器
其中代码实现和处理器映射器实现非常类似,见代码核心注释就好
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// 从当前spring容器和其祖先容器中,查找到所有的处理器适配器
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME,
HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
}
if (this.handlerAdapters == null) {
// 如果没有从spring容器中获取到HandlerAdapter,
// 则从默认DispatcherServlet.properties文件中加载默认策略
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
}
}
具体实现类图说明如下: