1.IOC和DI的实现流程
流程:
- 在调用Servlet init()方法时,初始化ApplicationContext;
ApplicationContext 简单的理解为他就是工厂类
在Spring中bean默认都是单例的,而且是延时加载(Lazy)的
DI是在bean初始化以后发生的 - BeanDefinitionReader读取配置文件(properties、xml、yml等)
- 扫描相关的类。配置文件保存到了内存中BeanDefinition
- ApplicationContext.getBean() 初始化IOC容器,并且实例化对象 Beanwrapper 装饰器模式.IOC容器中存储的是Beanwrapper对象
- spring中发生DI由getBean()触发
- 调用getBean()创建对象
- 立即发生DI
面试题:
Spring IOC的基本流程
- 读取配置文件
- 解析配置文件,并封装成BeanDefinition对象
- 把BeanDefinition对应的实例放入容器中缓存
Spring DI基本流程
- 循环读取BeanDefinition 缓存信息(从BeanDefinitionMap中获取)
- 调用getBean()方法创建对象实例(调用instantiateBean() 方法创建)
- 将创建好的实例对象包装为BeanWrapper对象
- 将BeanWrapper对象缓存到IOC容器(factoryBeanInstanceCache)
- 循环IOC容器执行依赖注入 (由populateBean() 类发起依赖注入的动作)
面试题:
一、DI是从哪里开始?
ApplicationContext.getBean(); 为什么?
因为Spring默认是懒加载
二、 实例化有两种情况?
1 目标类配置了AOP,实例化的是对象代理类
2 目标类没有配置aop,实例化的是原生对象
最后都封装为beanWrapper对象(统一一个对外访问对象的入口,可以拓展一些功能,缓存一些信息)
基于XML 的 IOC容器初始化三部曲
基于XML 的IOC容器初始化 细化以后的流程:
2.MVC的流程
流程说明(重要):
(1)客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
(2)DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
(3)解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由 HandlerAdapter 适配器处理。
(4)HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
(5)处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
(6)ViewResolver 会根据逻辑 View 查找实际的 View。
(7)DispaterServlet 把返回的 Model 传给 View(视图渲染)。
(8)把 View 返回给请求者(浏览器)
9大组件
序号 | 组件名 | 解释 |
---|---|---|
1 | HandlerMapping | 保存UrIl映射关系 |
2 | HandlerAdapter | 动态参数适配器,获取形参,封装参数 |
3 | ViewResolvers | 视图转换器,模板引擎 |
4 | MultipartResolver | 多文件上传的组件 |
5 | LocaleResolver | 本地语言环境 |
6 | ThemeResolver | 主题模板处理器 |
7 | HandlerExceptionResolver | 异常拦截器 |
8 | RequestToViewNameTranslator | 视图提取器,从request中获取viewName |
9 | FlashMapManager | 参数缓存器 |
initStrategies() 初始化9大组件
SpringMVC 源码流程
DispacherServlet init() 方法 初始化九大组件
DispatchServlet doService() 方法
getHandler 拿到 HandlerMapping chain
getHandlerAdapter(handleMapping)
adpter.hanlder() ModelAndView
processDispathResult() view.render();
redirect 重定向 ,request参数会丢失
forward 转发,自动把request参数携带到下一个请求
FlashMap valueStrack 值栈, 为了解决请求转发过程中参数丢失的问题
request < page < session < application
3.AOP的流程(面向切面编程)
aop的底层是用动态代理实现
AOP的一些概念
1 切面(Aspect):面向规则,具有相同规则的方法的集合体
2 通知(Advice):回调函数
3 切入点(Pointcut):需要代理的具体方法
4 目标对象(Target Object):被代理的对象
5 AOP(代理):主要两种方式:JDK(如果是接口就用JDKproxy否则用CGLib)、CGLib
6 前置通知(Before Advice)在invoke Pointcut之前调用,织入的方法
7 后置通知(After Advice)在pointcut之后调用,织入的方法
8 返回后通知(After Return Advice)返回值为非Void 织入的方法
9 环绕通知(Around Advice) 只要触发调用,织入的方法
10 异常通知(After Throwing Advice)Pointcut抛出异常,织入的方法
增强、解耦
织入一些新的代码 生成一个新的类,要么就跟目标类实现一个相同的接口,要么就是直接继承目标类,覆盖目标类的方法。真正去调用代码逻辑的时候,直接运行生成的proxy类的代码。切面的织入是有spring生成的proxy类来完成的
主要流程:
在AOP中拿到代理对象后怎么调用Advice呢?(责任链模式)这里涉及到两个类
1 Intercept 拦截器 责任链的组件 invoke()
2 ReflectiveMethodInvocation 调用器(相当于责任链的上下文),调用通知回调的组件 proceed()
4.整体的顺序
IOC->AOP->DI->MVC