大家好,欢迎来到IT知识分享网。
前言
上周线上项目出了一个bug,使用WebMvcConfigurer和WebMvcConfigurationSupport不能同时使用,要不然WebMvcConfigurer能扫描到容器中,但是他的方法不能执行。
只有搞懂了spring的源码流程,才能对这个问题进行整体的把握。
ApplicationContext简介
通过debug的方式对spirng源码进行一步一步的解读,spring的核心之一就是IOC容器,这是一个抽象的概念,对应IOC,做过spirng开发的想必都有所耳闻,但是对于他是什么大部分初级程序员是不明朗的。
IOC体现在spring中就是ApplicationContext,这是最重要的接口,spirng中有众多的类实现了这个接口,不同的ApplicationContext在不同的应用场景使用。
AnnotationConfigApplicationContext是基于注解的方式启动容器,ClassPathXmlApplicationContext是基于xml配置的方式启动容器,其他还有许多的方式启动容器,虽然多,但是能够见名知意,名字都是**ApplicationContext。
类名有个简单的印象就行,如果都看一遍太枯燥了,笔者也不推荐这样做。
Beanfactory简介
BeanFactory我的理解就是IOC容器中的一些工具方法,这是我浅显的理解,下图是BeanFactory 的所有方法,ApplicationContext继承了这个接口。
启动过程
通过debug的方式一步步深挖spring源码,一定要自己debug要不然很累!一定要自己debug要不然很累!一定要自己debug要不然很累!重要事情说三遍。
先通过一个简单的样例,看下spring-ico的一个简单使用。这个方法的作用就是new了一个ApplicationContext传入一个定义的bean,然后通过getBeanDefinitionNames()获取到它的容器中所有的bean。
点进去ApplicationContext的构造方法,会发现它调用了一个refresh()方法,这个方法是spring-ico最核心的方法,IOC初始化、注册bean等等一系列方法都是这这里完成的。
值得一提的是,springboot的run方法一步步点进去调用的还是这个refresh方法,看到这相信大家对于spirng和springboot的关系有了一个模糊的认识。
透过现象看本质,其实springboot的核心启动方法还是调用了spring的run方法,只是在这个方法的前后又做了一些启动的事,增强了spring而已。
书归正传,让我们重新回到refresh方法中一步步的解读。在refresh上面打上一个断点,一步一步看每一个方法都做了什么事。
高能预警:下面是一段超长的源码分析,可能引起不适,但是对于技术的提高也是显著的。
@Override
public void refresh() throws BeansException, IllegalStateException {
// 加锁,避免 refresh() 启动和销毁容器混乱this.startupShutdownMonito该锁为当前对象。
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
**ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();**
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
// 国际化
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。
registerListeners();
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,ApplicationContext 初始化完成
finishRefresh();
}
// Destroy already created singletons to avoid dangling resources.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();
// 把异常往外抛
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// 重置缓存
resetCommonCaches();
}
}
}
以上就是refresh()方法概述,如果全部展开来讲的话会很长很长,接下来会分很多文章来解读每一个方法的源码,但是读者要对它的所有方法做到心中有数。
spring与其他框架的整合,都蕴含在这些方面中,充分利用了spring的扩展性。
总结
在花了一天时间后,这篇文章终于算是基本写完了,应该透过现象看本质,去理解 Spring 写得好的地方,去理解它的设计思想。
充分解读spring代码量真的比较大,分支旁路众多。以后会逐步拆解它的每一个问题,敬请期待吧。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30622.html