我们在使用SPring的经验中,我们见的最多的是ApplicationContext,Spring托管的所有实列Bean都可以通过调用gentBean()方法来获得。
DispatcherServlet 继承了FrameworkServlet,FrameworkServlet继承了HttpServletBean,HttpServletBean继承了HttpServlet。在HttpServletBean的init()方法中调用了FrameworkServlet的initServletBean()方法,
在initServletBean()方法中初始化WebApplicationContext实例,在initServletBean()方法中调用了DispatcherServlet重写的onRefresh()方法,在DispatcherServlet的onRefresh()方法中有调用了initStrategies()方法,
初始化SpringMVC的九大组件。
其实,上面复杂的调用关系,可以简单的得出结论:就是在Servlet的init()方法中初始化了IOC容器和SpringMVC所依赖的9大组件
1:加载配置文件
2:扫描相关类
3:初始话扫描到的类,并放到Ioc容器中
4: 完成依赖注入
5:初始化Handmapping
6:调用,运行阶段
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调用,调用那个类,这类的方法有哪些实参要传;
简单加载顺序图:
IOC中最重要的类
出发是从 getBean() 开始,用的是单例Bean,容器时单例,(Lazy)懒汉式加载
ApplicationContext 整个容器的主题,可以认为是一个工厂
BeanDefinitionReader 读取配置文件
BeanDefinition 保存配置信息
BeanWrapper 对象的包装类
DI部分
getBean() 调用 isntantiatBean();用反射初始化Bean对象
注入是 populateBean() 完成依赖注入,通过反射注入
完成以后会放到BeanWrapper 中
循环依赖注入:
缓存解决依赖注入的问题
例:
A{ B a}
B{ A b}
用两个缓存,循环两次
1、把第一次读取结果为空的BeanDefinition存到第一个缓存
2、等第一次循环之后,第二次循环再检查第一次的缓存,如果是第一次不为空,再进行赋值
9大组件 //多文件上传的组件 initMultipartResolver(context); //初始化本地语言环境 initLocaleResolver(context); //初始化模板处理器 initThemeResolver(context); //handlerMapping initHandlerMappings(context); //初始化参数适配器 initHandlerAdapters(context); //初始化异常拦截器 initHandlerExceptionResolvers(context); //初始化视图预处理器 initRequestToViewNameTranslator(context); //初始化视图转换器 initViewResolvers(context); //FlashMap管理器 initFlashMapManager(context);
2. 5个重要的类
handlerMapping 主要保存url与method的关系
handlerAdapter 动态参数适配器
ModelAndView 主要解析返回值,是Json 还是页面
ViewResolver 视图转换器,模板引擎
View 返回页面
DiapatcherServlet init() 初始化九大组件
调用initStategers() 初始化组件
View render() 渲染,读取模板文件内容,用正则替换占位符
AOP(面向切面编程):
针对一群类,只要有共同特征的类或者方法,都可以称之为一个侧,即切面(Aspect)
底层技术用动态代理实现 ,切面的织入,主要是由SPring生成的proxy来完成的(JDK,CGLib)
主要作用:增强对象, 解耦,织入一些新的代码,生成一个新的类,要么就跟目标类实现个相同的接口,要么就是直接继承目标类,覆盖目标类的方法
真正去调用业务逻辑的时候,直接运行生成的Proxy类的代码,
Advice 通知,( 一对多 ) handler 方法 对应多个通知
AOP中重要的几个类
AdvisedSupport 主要读去配置 解析
->AopConfig保存 Aop 配置 变成
多个Advice ,跟业务中具体method建立一对多的关系,
最后调用动态代理类,代理类中拿到所有通知,根据一个方法拿到一个通知,在代理类中执行这些通知
Spring主要核心模块加载顺序 :IOC /AOP/DI/MVC
附加面试题一道,
Sring中的Bean是线程安全的么?为什么?