手撕Spring框架核心功能实现与源码时序图

 

我们在使用SPring的经验中,我们见的最多的是ApplicationContext,Spring托管的所有实列Bean都可以通过调用gentBean()方法来获得。


一:DispatcherServlet的类图如下:

 

手撕Spring框架核心功能实现与源码时序图_第1张图片

DispatcherServlet 继承了FrameworkServlet,FrameworkServlet继承了HttpServletBean,HttpServletBean继承了HttpServlet。在HttpServletBean的init()方法中调用了FrameworkServlet的initServletBean()方法,

在initServletBean()方法中初始化WebApplicationContext实例,在initServletBean()方法中调用了DispatcherServlet重写的onRefresh()方法,在DispatcherServlet的onRefresh()方法中有调用了initStrategies()方法,

初始化SpringMVC的九大组件。
其实,上面复杂的调用关系,可以简单的得出结论:就是在Servlet的init()方法中初始化了IOC容器和SpringMVC所依赖的9大组件

Spring核心功能框架实现:

1:加载配置文件

2:扫描相关类

3:初始话扫描到的类,并放到Ioc容器中

4: 完成依赖注入

5:初始化Handmapping

6:调用,运行阶段

手写Spring主要流程加载顺序:

1:继承HttpServlet ;

实现初始化 init()方法;
实现doGet(), doPost()方法

2:初始化init() 方法中有以下步骤:

(1):扫描相关类
(2):初始化所有相关的类实例,并且放入到IOC容器中,主要是控制反转的过程
(3):完成依赖注入
(4):初始化HandLerMapping();
(5):等待请求,匹配URL,定位方法, 反射调用执行,调用doGet或者doPost方法

3:doPost()中实现调用


(1):获取请求的url,用正则表达式统一“/”
(2):获取要请求的方法
(3):获取方法的形参列表
(4):保存复制参数的位置
(5):根据参数位置动态赋值
(6):循环中提取方法加了注解的参数
(7):最后invoke调用,调用那个类,这类的方法有哪些实参要传;


简单加载顺序图:

 

Spring核心功能三个模块:

1:SpringIOC和DI


IOC中最重要的类


出发是从 getBean() 开始,用的是单例Bean,容器时单例,(Lazy)懒汉式加载
ApplicationContext 整个容器的主题,可以认为是一个工厂
BeanDefinitionReader 读取配置文件
BeanDefinition 保存配置信息
BeanWrapper 对象的包装类


DI部分


getBean() 调用 isntantiatBean();用反射初始化Bean对象
注入是 populateBean() 完成依赖注入,通过反射注入
完成以后会放到BeanWrapper 中

手撕Spring框架核心功能实现与源码时序图_第2张图片

  1. 调用Servlet init()方法 创建 ApplicationContext
  2. BeanDefinitionReader 读取配置文件(xml、yml、properties)
  3. 扫描相关的类,配置文件保存到了内存中的 BeanDefinition
  4. ApplicationContext.getBean() 初始化IOC容器,并且实例化对象 BeanWrapper(增强版的bean)
  5. 在getBean()中完成DI注入

循环依赖注入:

缓存解决依赖注入的问题

例:

A{ B a} 
B{ A b} 
用两个缓存,循环两次
1、把第一次读取结果为空的BeanDefinition存到第一个缓存
2、等第一次循环之后,第二次循环再检查第一次的缓存,如果是第一次不为空,再进行赋值

 

2:SpringMVC

  1. 9大组件
    
           //多文件上传的组件
            initMultipartResolver(context);
           //初始化本地语言环境
            initLocaleResolver(context);
            //初始化模板处理器
            initThemeResolver(context);
            //handlerMapping
            initHandlerMappings(context);
            //初始化参数适配器
            initHandlerAdapters(context);
            //初始化异常拦截器
            initHandlerExceptionResolvers(context);
           //初始化视图预处理器
            initRequestToViewNameTranslator(context);
            //初始化视图转换器
            initViewResolvers(context);
            //FlashMap管理器
            initFlashMapManager(context);

手撕Spring框架核心功能实现与源码时序图_第3张图片

 

2. 5个重要的类

handlerMapping 主要保存url与method的关系
handlerAdapter 动态参数适配器
ModelAndView 主要解析返回值,是Json 还是页面
ViewResolver 视图转换器,模板引擎
View 返回页面

DiapatcherServlet init() 初始化九大组件
调用initStategers() 初始化组件
View render() 渲染,读取模板文件内容,用正则替换占位符

3:SpringAOP

AOP(面向切面编程):

针对一群类,只要有共同特征的类或者方法,都可以称之为一个侧,即切面(Aspect)
底层技术用动态代理实现 ,切面的织入,主要是由SPring生成的proxy来完成的(JDK,CGLib)
主要作用:增强对象, 解耦,织入一些新的代码,生成一个新的类,要么就跟目标类实现个相同的接口,要么就是直接继承目标类,覆盖目标类的方法
真正去调用业务逻辑的时候,直接运行生成的Proxy类的代码,
Advice 通知,( 一对多 ) handler 方法 对应多个通知

 

AOP中重要的几个类

手撕Spring框架核心功能实现与源码时序图_第4张图片
AdvisedSupport 主要读去配置 解析
->AopConfig保存 Aop 配置 变成
多个Advice ,跟业务中具体method建立一对多的关系,
最后调用动态代理类,代理类中拿到所有通知,根据一个方法拿到一个通知,在代理类中执行这些通知

 

 

Spring主要核心模块加载顺序 :IOC /AOP/DI/MVC

附加面试题一道,
Sring中的Bean是线程安全的么?为什么?

源码时序图:

你可能感兴趣的:(Spring,java)