热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

发布时间:2022-06-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

@TOC# 热门框架系列 记录在程序走的每一步___auth:huf


从新的篇章开始;篇章阅读需要先关注; 因为笔者想参与技文章的评选.;需要一定的粉丝量; 粉丝量达到一定数量.所有文章阅读限制将会全面放开;谢谢大家的支持
本章节为上一个章节的延续F1b;仅此一章节的延续; 先抛出一个问题;请记住这个问题;之后看完这个篇章应该可以轻松的回答出来;

SPRingBoot 既然整合了SpringMVC 那SpringBoot 有没有子容器?


我们开始这个篇章吧! 在Servlet3.x,我们可以添加 Servlet Filter Listener

我们有两种方式 一种是注解的方式; @WebServlet @WebFilter @WebListener 还有一种方式 就是 :Spi

spi 是什么

SPI 我们叫他服务接口扩展,(Service Provider Interface) 直译服务提供商接口, 不 要被这个名字唬到了, 其实很好理解的一个东西: 其实就是根据Servlet厂商(服务提供商)提供要求的一个接口, 在固定的目录 (;mETA-iNF/services)放上以接口全类名 为命名的文件, 文件中放入接口的实现的 全类名,该类由我们自己实现,按照这种约定的方式(即SPI规范),服务提供商会 调用文件中实现类的方法, 从而完成扩展。

在其规范中 我们可以看得到那么一句话:

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

也就是META-INF/services 路径下 放一个 javax.servlet.ServletContainerInITailizer 以下我们进入SPI 代码的实现:

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

准备一个maven 项目 里面三个子项目 一个Service 一个Client; 还有一个startUp 启动 我们按照上面的说法 我们在 META-INF/service 路径下放一个 接口全路径名的File 文件 文件内维护全路径类名的实现类

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

以下是测试结果:

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

SPI 机制就是这样; 现在很多第三方插件使用的都是SPI机制; 当然Spring也有这样的机制; 前置知识点 到这里 就铺垫的差不多了; 如果SPI又疑问的;可以单独私聊我;


我们细细的往下挖,IDEA创建spring mvc项目 如何创建 可以在其他博主内找到; 以下是需要注意的几点:

1: 需要配置Tomcat;

Tomcat下载下来 启动会有乱码 以下是windows解决乱码的方案

在Tomcat的config里面 LOGging.proPErties
修改:
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.encoding = GBK

2:需要配置dispatcher-servlet.XMl

<?xML version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/cache
       http://www.springframework.org/schema/cache/spring-cache.xsd">

    <context:component-scan base-package="com.huf"></context:component-scan>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>

</beans>

3:需要配置web.xml

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

如果对于这部分代码配置 或者使用idea 搭建 SpringMVC搭建 项目 过程中 遇到有什么问题 可以私聊我; 因为如果想要追溯 父子容器 那就必须要搭建这么一套东西;

我们在项目中的META-INF.services 添加 javax.servlet.ServletContainerInitializer

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

SpringMVC 我们分为2块来看 第一块 启动:

我们现在了解了SPI 也配置好了Tomcat 启动这一块 我暂时不细说; 后面有专门的文章来说Tomcat; 1:在我们的SPI中 我们有一个类放在META-INF下面:HufSpringServletContainerInitializer

tomcat启动
ServletContainerInitializer
SpringServletContainerInitializer
HufSpringServletContainerInitializer.onStartup

之后 我们进入到了AbstractContextLoaderInitializer.onStartup 方法;

	继承自AbstractAnnotationConfigDispatcherServletInitializer

以下是他们的继承关系

AbstractAnnotationConfigDispatcherServletInitializer
AbstractDispatcherServletInitializer
AbstractContextLoaderInitializer

以上的铺垫 全部都是为了引出 加载容器方法; 我们联合起来的逻辑:

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

我们知道 在子类没有onStartup方法 就会往父类中去寻找:

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

我们再AbstractDispatcherServletInitializer.onStartup方法中;我们可以发现;

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

这里 就准备开始创建我们的父容器; 点进去;

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

开始创建我们的父容器; 继续往里面看

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

开始注册我们的父容器; 只有register 没有refresh(); 这里我们就可以发现 这里仅仅是做了一个准备工作 容器并没有启动;最后返回一个容器;

创建一个监听器;

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

新创建一个监听器 然后把监听器 方到Listener里面;父容器到这里就阶段性结束了;然后回到 AbstractDispatcherServletInitializer.onStartup()方法中

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

代码部分 我就不一句一句去解释了 这里代码非常简单;如果喜欢看我博客的同学 应该都没很大问题;

这里记住 Tomcat会继续往下执行代码; 这时候会调起一个 ContextLoaderListener的contextInitialized 方法;

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

我们继续点进去看一下;

热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?

tomcat会继续往下执行 会调起 DispatcherServlet.init 方法 这里再上一篇文章中我写有写一部分;

重点关注这个方法;

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);
					}
					开始初始化容器; 再上图中 进行 refresh
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		if (wac == null) {
			wac = findWebApplicationContext();
		}
		if (wac == null) {
			wac = createWebApplicationContext(rootContext);
		}
		if (!this.refreshEventReceived) {
			synchronized (this.onRefreshMonitor) {
				开始初始化Servlet里面的 组件 
				/**
				initMultipartResolver(context);
				initLocaleResolver(context);
				initThemeResolver(context);
				initHandlerMappings(context);
				initHandlerAdapters(context);
				initHandlerExceptionResolvers(context);
				initRequestToViewNameTranslator(context);
				initViewResolvers(context);
				initFlashMapManager(context);
				**/
				onRefresh(wac);
			}
		}
		if (this.publishContext) {
			String attrName = getServletContextAttributeName();
			getServletContext().setattribute(attrName, wac);
		}

		return wac;
	}

这边 我们就已经把 SpringMVC的父子容器全部解释清楚了:

总结

1:Tomcat在启动时会通过SPI注册 ContextLoaderListener和DispatcherServlet对象,同时创建父子容器 :分别创建在ContextLoaderListener初始化时创建父 容器设置配置类;在DispatcherServlet初始化时创建子容器 即2个 ApplicationContext实例设置配置类

2: Tomcat在启动时执行ContextLoaderListener和DispatcherServlet对象的初始化方 法, 执行容器refresh进行加载

3:在子容器加载时 创建SpringMVC所需的Bean和预准备的数据;

4: 子容器需要注入父容器的Bean时(比如Controller中需要@Autowired Service的Bean); 会先从子容器中找,没找到会去父容器中找: 详情见 AbstractBeanFactory#doGetBean方法

 一般情况下,只有Spring和SpringMvc整合的时才会有父子容器的概念,
 作用:比如我们的Controller中注入Service的时候,
 发现我们依赖的是一个引用对象,
 那么他就 会调用getBean去把service找出来;
 但是当前所在的容器是web子容器,
 那么就会在这里的 先去父容器找

回到我们 文章当中的那个问题:

SpringBoot 没有父子容器;原因如下

父子容器的定义: 1.早期Spring为了划分框架边界。service、DAO层我们一般使用spring框架来管理、controller 层交给springmvc管理; 2.规范整体架构 使 父容器service无法访问子容器controller、子容器 controller可以访问父容器 service、 3.方便子容器的切换。如果现在我们想把web层从spring mvc替换成struts, 那么只需要将spring­mvc.xml替换成Struts的配置文件struts.xml即可,而 spring­core.xml不需要改变

脚本宝典总结

以上是脚本宝典为你收集整理的热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?全部内容,希望文章能够帮你解决热门框架系列 (二) -- SpringMvc的父子容器,SpringBoot是否有父子容器?所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。