本身喜欢将看过的东西写成博客,一是方便本身查看,二也能够提供他人参考。由于这段时间比较空闲,借此机会研究Spring源码,旨在培养习惯、提高本身,但毕竟是一家之言,若是有不对的地方或者建议,欢迎拍砖。git
本身研究源码的初心就是想看看那些牛逼的框架究竟是有多牛逼,代码到底有多优雅,怎么利用设计模式去构建程序,如何漂亮实现解耦,如何设计扩展点灵活让第三方开发者干预框架的运行,如何与框架进行整合。说出来可能有人还不信,我的并非由于想去BAT这些大厂而研究源码,估计像我这个年龄别人也不会要了。。。自嘲一下!github
但愿本身经过阅读Spring源码提升以下能力:设计模式
1.首先确定是阅读源代码的能力,找到阅读源码的基本方法,提升DEBUG的能力,增强如何定位问题的技巧闭包
2.让本身内心的大象迈出一小步,让本身熟悉阅读源码,培养习惯,之后看更多的源码框架
3.从源码中找到写出漂亮代码的底层逻辑,好比设计模式、如何解耦、优雅的语法或者API、很是棒的工具类工具
4.提升项目脚手架质量,提高编码能力,加快BUG定位速度源码分析
5.将阅读源码的结果分享出来,尽可能可让路过的人能够产生阅读源码的兴趣,解决工做中遇到问题学习
最新的Spring源码是经过Gradle构建的,所以只接触过Maven构建的朋友建议花几个小时在网上找一个Gradle的学习视频,大概了解一下grovvy和Gradle相关知识,否则真的看不懂gradle.build文件。好比闭包、Gradle特有的API等,还有Gradle的安装、IDEA如何提高Gradle编译速度等。gradle
基于本身的环境写了一篇博客:http://www.javashuo.com/article/p-vfbhnoop-ch.html 欢迎参考ui
1.简单学习grovvy和Gradle相关知识
2.了解一下设计模式,好比装饰者、模板方法、工厂方法,还有抽象类、接口的运用,里面用了大量的设计模式,不提早了解一下,代码看起来比较吃力
3.学习Java8的Lamda表达式
4.学习Idea的快捷键,DEBUG的一些技巧
等Spring源码构建完成后,该如何着手去看喃,固然是写一个工程,经过DEBUG Spring源码看执行过程等,总结本身看源码几点经验
1.必定要从GIT上下载源码并构建,反编译看源码,特别是复杂的代码会发蒙的。
2.在工程中开启新的工程或者module,引用项目中的module进行调试
3.看源码以前必定要对框架的使用比较熟悉,千万不要对框架的使用都不熟悉就跑去看源码,那样必定会发蒙的。因此花点钱买点框架使用的书或者视频先看看,不要吝啬那几分钱,等你看完工资必定会涨的。好比SpringMVC,你就只知道加@Controller @Service @Component完成业务代码可不行。
4.看源码时经过DEBUG对框架有整体上的认识,不要一来就往深、细了抠,若是那样的话,你会发现本身很快就看不下去了
5.DEBUG时着重先关注每行代码执行完后关键变量的变化,好比Spring源码当中的beanDefinitionMap singletonObjects beanPostProcessors等,返回的对象或者值是否是可能你须要关注的
6.善用DEBUG的条件断点,不然可能你按了无数次F6也到不了你关注的触发点或者执行点
7.必定要边看边加注释、作笔记、画图什么的,由于一两天你是看不完的,极可能由于其余事情耽搁了,等下次来看又蒙了
8.GOOGLE 百度是经常使用工具,也能够试着搜索一下gitee或者github上面是否已经有别人看过的源码分析的项目,DOWN下来接着看,能够提升阅读速度,可是必定要写代码去验证,由于有人直接翻译的英文,也许那并无什么Luan用。既然是看源码,是基本的东西,凡是别人的东西必定要多方面验证才能吸取成正确的本身的,不然看了半天结果是错的就麻烦了。我就遇到了这样的问题,在搜索引擎上找到的内容其实在Spring5已经变了。
开始王婆卖瓜。。。。由于如今开发都是基于注解的,所以也是拿AnnotationConfigApplicationContext做为分析对象
很是概要的图描述Spring容器初始化过程
核心类起的做用就好像汽车的发动机,没它都跑不了咯,还能期望它带你去撩妹、看帅哥么。一样,Spring的核心类可以保证容器或者叫上下文可以正常工做,基于它管理咱们的业务对象,实现业务逻辑,好比:
AnnotationConfigApplicationContext:也就是Spring的整个容器,Spring还有另一个相似的叫ClassPathXmlApplicatonContext(基于XML配置的),在它里面包含了全部实例化的单例Bean、系统参数与配置文件加载后的键值对、后置处理器、每一个Bean的定义等等
AnnotatedBeanDefinitionReader:负责读取被注解修饰了的Bean的定义,并添加到某一个Bean定义的集合当中。典型的场景就是个人ImportResourceAppConfig.class传入到AnnotatedBeanDefinitionReader.register()方法中,在BeanDefinitionMap中会新增一个对应的元素。
DefaultListableBeanFactory:这个就至关至关重要了。。。它包含了注册BeanDefinition-registerBeanDefinition(),而后利用BeanDefinition获取或者建立Bean的逻辑-getBean(),对应的就有两个方法常使用的四个变量:
private final Map<String, BeanDefinition> beanDefinitionMap;--存放全部的Spring Bean定义(BeanDefinition),关于BeanDefinition详解查看:http://www.javashuo.com/article/p-tqmnjqch-p.html
private final Map<String, Object> singletonObjects --存放全部的单例Spring Bean
private final Map<String, Object> earlySingletonObjects --存放循环依赖时须要提早被暴露的Bean,这些Bean并无被不少PostProcessor(中文翻译为后置处理器)处理,以解决循环依赖不会出现无限制的递归(这里没明白不要紧,知道它和解决循环依赖有很重要关系便可,后面会详细说明)
private final Set<String> singletonsCurrentlyInCreation --存放当前容器中正在被建立的beanName(它也和循环依赖有很大关系)
图中的就是Bean定义集合的元素截图,这些组件会完成@ComponentScan注解的包扫描,以及被扫描到的类定义注册,实例化裸对象,完成SpringBean的初始化(包含了各类PostProcessor的处理,好比依赖注入)
图中截图Map中Key对应的类以下顺序:
ConfigurationClassPostProcessor:扫描@ComponentScan中指定包路径下全部符合Spring规则的类,如加了@Configuration @Component等的类,将他们的BeanDefinition注册到beanDefinitionMaps当中。还有另一个功能就是添加一个ImportAwareBeanPostProcessor,它可让你的Bean获取到将@Import做为元注解时自定义注解的属性键值对(此功能能够先无论)
DefaultEventListenerFactory:和Application Event有关,还没详细查看之后再补充
EventListenerMethodProcessor:和Application Event有关,还没详细查看之后再补充
AutowiredAnnotationBeanPostProcessor:负责依赖注入和属性注入,好比@Autowired @Value的相应动做
CommonAnnotationBeanPostProcessor:负责JSR250相关注解的解析与执行,好比@PostContruct @Resource等
使用AnnotatedBeanDefinitionReader.register(ImportResourceAppConfig.class)将ImportResourceAppConfig的BeanDefinition注册到beanDefinitionMaps当中。完成这个动做以后Spring才能拿到配置类作下一步的包扫描、依赖注入等操做
主要就是ConfigurationClassPostProcessor和AutowiredAnnotationBeanPostProcessor两个类启核心做用(固然还有这两个牵扯出来的其余类),好比ConfigurationClassPostProcessor.ConfigurationClassPaser就是负责完成包扫描的,包含了@ComponentScan @Component @Import @ImportResource @Bean 注解的解析完成全部的BeanDefinition的建立并注册到beanDefinitionMaps当中
上一步已经将全部的BeanDefinition准备好,接下来就是遍历他们,使用动态代理完成对象的实例化,并最终获得Spring Bean(多是裸对象,也多是代理对象)。
总结:简单的说Spring并非直接根据Class文件建立一个Bean,而是生成对应的BeanDefinition对象,再根据它建立想要的Bean,在这个过程中Spring提供了丰富的扩展点去干预BeanDefinition状态和Bean的状态,这些扩展点就是Spring真正强大的缘由。