SpringBoot源码解析(准备)

图1

图2

图2是传统模式下springmvc这样做的。

springboot和springmvc他们的结合点事那个,传统的springmvc 需要做的事情是初始化spring环境,读取xml,注册servlet,扫描controller,2json解析,3视图解析器,那么问题来了,springboot 没有web.xml 没有任何xml。没有办法做以上的事情,他是咋么做到的呢?他是如何内嵌tomcat呢. 

图3

图4

图5

图6

图7

springboot如何把dispatchServlet放进spring 容器。  spring官方文档推荐用这种方式。我们需要用这种方式来完成spring容器的初始化,创建DispatcherServlet 并且注册到spring容器中。换句话说我们用这种方式来代替web.xml所做的工作。 web.xml在容器启动的时候回进行spring容器初始化,DispatcherServlet注册等工作。那问题来了,我们怎么确定容器启动的时候回调 WebApplictionInitializer类的onStartup方法呢。why会调用。

图8

我们可以发现 WebApplicationInitializer类型是有spring 开发的。 难道tomcat容器在启动的时候,循环遍历所有实现 WebApplicationInitializer 类的,然后依次调用WebApplicationInitializer 的onStartUp方法吗,那么这样这个tomcat不就严重依赖WebApplicationInitializer这个类了吗,显然是不可能的。那怎么办?

图9

 图9借助于servlet的3.0规范,只要你在classpatch目录下,配置了META-INFO /services/这个目录下配置了一个类,这个类实现了ServletContainerInitializer类的onStartUp方法。tomcat(其他容器)启动的时候就会调用这个方法。

图10

我们自己的类是 WebApplicationInitializer的子类,而这个是调用SprinServletContainerInitializer的onStartup方法,两个类啊。

其实是这样 SprinServletContainerInitializer 的onStartup方法在被调用的时候,会把所有实现了WebApplicationInitializer的子类做为参数放在一个set中传进来。然后依次for循环遍历调用。 @通过HandlesTypes注解来获得WebApplicationInitializer 类。

图11

 

图12 

这个属于tomcat的方法。

图13

  spring 3.0后提供javaCofig方式。利用这种方式,springboot 完成了替代 扫描的功能。

 图14

图14标绿的完成了spring 的初始化。新问题来了如何内嵌tomcat呢。当我们启动一个tomcat。需要运行一个exe文件->main 方法(tomcat)

tomcat来启动一个线程来跑我们的tomcat。 那么我们怎么在项目中执行tomcat的main方法呢,可以通过mave依赖把tomcat依赖到我们的项目中。

依赖这个jar包。我们就可以来执行tomcat的main方法。

图15

14行为什么要await().因为要等待服务连接,如果不写tomcat回一闪 而过。

图16

我们发现tomcat已经启动了。

图17

当我们加上打印记录的时候发现tomcat启动并没有打印这段代码,证明没有调用这个类,不是吧,上面不是说可以调用吗,其实并不是tomcat只有是web项目的时候他才会使用servlet3.0的新规范调用这个onStartup方法。 但是问题来了,springboot也不是web项目啊,难道你非要让我健一个web项目才可以吗

图18

 

此时正常打印了,证明可以调用onStartup方法了。

图19

修改成这样,刚才那个异常就解决了。但是又有新的异常了。jsp的异常。如果是web项目的话默认执行一个jsp引擎。

图20

这个问题也可以解决。只是缺少一个tomcat的jsp的jar包,加上就可以了。

图21

图22

打印controller了,证明访问到controller层了。但是页面是404 这个不影响,因为没有jsp所以这样。现在很少用jsp。所以正常的情况下我们已经完成了类似springBoot的功能了。这样的内嵌tomcat已经完成了。

图23

对controller进行修改。

图24

当我们访问map的时候报不能转化map的错误信息。

图25

xml 我们是这样配置 json转化的。

springboot 类型的咋玩?

添加fastjson 包依赖。

图26

实现WebConfigurer 类,重写configureMessageConverters方法。

图27

但是我们执行完发现并没有打印======== 为什么没有执行呢,

 

加上@EnableWebMvc 就可以正常显示了。

但是现在问题虽然解决了。springboot不需要jsp啊,我也不想添加jsp的jar 包,还有其他的方法吗。本来我springboot 不是web项目,为啥一定要添加jar包,一定要按web项目运行呢,?

图28

如果我把这个再改为addContext() 这样的话,onStartup的方法就不能调用。但是jsp那个异常就不报错了。

把这个onStartup中的方法赋值到图28中就能解决这个问题。

图29

图28改成这样。那么就可以正常访问,一切正常了。jsp那个异常也解决了。map也能正常返回了,也不是web 项目了。

图29

根据官网我们发现似乎少加ac.refresh();

图30

真正核心的代码ac.refresh() 这个要加上

图31

 

图31 refresh()是核心代码。所以要加上,但是遗憾的是加上以后 加上之后会报错。

图32

 

这是为什么呢,当我们执行ac.refresh()方法时候回解析Appconfig类的@EnableWebMvc注解 ,这个过程需要解析Servlet 但是这个时候DistpatechServlet还没有创建呢,所以报这个错误。

图33

 

图34

 

所以去掉就一切正常了。那问题又来了初始化,spring的核心逻辑不执行了吗,比如在ac.refresh()方法里的 解析注解,转化bd,bean初始化等功能,显然不是。

当代码执行到32行的时候回执行DispatcherServlet的init ()方法。

 

 

图18

我们发现在dispacherServlet的父类中有init()方法。

图19

图20

图21

 

图22

 

图21

图22

代码走到这里我们终于明白了,其实spring Mvc内部也调用了refresh()方法。因为底层都是调用spring的refresh()方法。那么问题又来了,最早不是执行了两遍的refresh() 方法吗,没有问题吗,没有问题啊,因为getBean的流程了,因为spring 在new bean的时候要先get一遍的。所以不会示例化两遍。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值