请求 => web.xml
DispatchServlet extends HttpServlet
init() => 初始化方式,spring应该要在这里先初始化
service() =》浏览器访问url,由web容器调用
doGet/doPost =》 controller的逻辑
destory() =》 销毁servlet
综上,入口就是从xml的拦截器类开始。
1.看那些注解,拷一份到自己项目中
2.看看spring这些注解怎么写的,我们跟着怎么写
3.但是现在有样子没功能,如下:
4.既然确定了dispatchServlet是入口类,并且init是入口方法了,我们去找dispatchServlet类,然后跟着
他的继承关系一路向上,找到init方法,我们对着init方法进行一番猜测。init肯定是初始化方法,但是具体干了啥我不知道。
5.然后看到initStrategies方法,里面按照他的方法名,我们顾明思意来猜
6.好,那么到了这里我们有几个工作要干了
7.开始写代码了,我们先明确一下思路,如下图,下面是我们需要做的一些工作
开始手写源码:
首先我们要搞一个dispatchServlet,那么要学着spring里面的dispatchServlet
先从xml导入,然后初始化的时候注入参数,来提示spring需要扫描那些类
【注意,这里把整个xml文件作为初始化参数都搞进去了】
然后创建一个dispatchServlet类,继承HttpServlet,直接右键,overrider覆盖init方法,doget,dopost方法
doget -> dopost ->doDispatcher(运行阶段的分派请求方法)
doDispatcher自然就是写在dopost方法里面
init方法里面需要做下面几步操作:
doLoadConfig -> 加载配置文件,就是那个xml文件,我么要将其读入到内存中,因为他是直接存放在硬盘上面的
doScanner -> 扫描对应的类
doInstance -> 初始化扫描到的类,并放到ioc容器中
doAutoWried -> 完成依赖注入
InitHandlerMapping -> 初始化url和controoler类的对应
打印完成初始化日志。
doLoadConfig:
利用config拿到xml里面的配置项目,注意,这里拿到的只是xml文件,而不是xml文件中的内容
直接读取xml文件,把xml文件的内容都放入一个property对象中。
doScanner:
doScanner主要就是说,进入到对应的包中,进行扫描,把扫描到的类加入到一个list中。
这里有点疑问,为什么要全部扫进来呢?有必要吗
doInstance
用map来存放实例化出来的bean,要判断是controller或者是service,如果是controller,直接按类名放进去。
如果是service的,则要按类名or自定义名。直接去自定义,没有则用类名搞。
对于每个实现类,扫描之接口,如果一个接口被多个类实现,我们直接报错,也就是说,目前的版本,一个接口不能被多个
类实现。如下:
A和B都实现ABC接口
@servce(value = "ab")
Class A
Class B
注入到map为:
ab => A
ABC => A
B => B
ABC => B【这里就错了,不能给ABC都搞2个实例进去】
【这里讲道理,如果检测到,有人用ABC类型来注入,而且又没有指定要哪个实现类,这个时候才会报错】
【但是目前这个版本,我们直接在源头杜绝这种现象,检测到一个接口被多个类实现,直接报错得了】
doAutoWired
那到ioc容器里面的类,取出每个类的字段,判断每个字段上面是否加了注解
如果加了,则判断是否是对应的autoWired注解,如果是,取出来。
如果autoWired没有自动义注入的名称,则按照类名来注入。
【如果是private的话,还要setAccessible】
initHandlerMapping
处理url =》 对应的controller
依然从ioc取出对应的类,判断是不是加了controller注解
如果是,判断是否加了baseUrl,就是类上面的controller注解是否加了value
取出所有的方法,判断是否加了controller,
对加了RequestMapping的注解的,取出value,拼接上baseUrl
根据url存入handlerMapping容器,url =》Method
到这里初始化的代码都ok了,可以debug一下,看看结果。
doget=>dopost
doDispatch
获取到请求的路径 =》 进行截取 =》 映射到对应的urlMapping容器
如果映射不到,则报404
如果映射到了,则调用对应的方法
要注意invoke的方法,第一个参数要传入对应的controller实例
第二个参数对应的树方法对应的参数,可变的object数组