源码理解
第一、前期运行环境与工具准备
JDK版本:1.8.0_131(版本1.8就行,我的是1.8最新版,高于1.8的没试过)
下载地址: https:/www.oracle.comltechnetwork/cn/javaljavase/downloads/jdk8-downloads-2133151-zhs.html
GRADLE版本:4.9 (也可用idea自带的gradle导入就行,如果自己安装需要配置相关环境)
下载地址: https://services.gradle.orgldistributionsl
Spring源码版本下载地址:https:/lgithub.com/spring-projects/spring-framework/releases
IDEA版本:IntelliJ IDEA (2018版) 下载地址: https://www.jetbrains.com/idealdownload/
系统:WINDOws 10
第二、先配置好GRADLE、下载源码
测试gradle是否配置完成在cmd输入:gradle -version 出现如下即为成功!
源码解压
上图用红框圈出来的几个文件要重点关注下:-
- build.gradle放了一些依赖配置,有点像maven的pom文件
- gradle.properties存放当前Spring的版本,可以对比下看看是不是5.0.X版本
- gradlew.bat放的是项目的构建脚本,不过在本章用不上,本章是使用IDEA去构建
- import-into-idea.md这个是Spring导入IDEA的说明文件,可以根据里面的步骤去导入
打开SpringFramework\SourceCode\spring-framework-5.0.x\gradle\docs.gradle文件,注释掉里面dokka和asciidoctor两个配置项
步骤比较复杂详细参考百度 省略............
上图用红框圈出来的几个文件要重点关注下:-
- build.gradle放了一些依赖配置,有点像maven的pom文件
- gradle.properties存放当前Spring的版本,可以对比下看看是不是5.0.X版本
- gradlew.bat放的是项目的构建脚本,不过在本章用不上,本章是使用IDEA去构建
- import-into-idea.md这个是Spring导入IDEA的说明文件,可以根据里面的步骤去导入
打开SpringFramework\SourceCode\spring-framework-5.0.x\gradle\docs.gradle文件,注释掉里面dokka和asciidoctor两个配置项
步骤比较复杂详细参考百度 省略............
解析类容:
BeanFactory:spring顶层核心接口,用来生产Bean的
BeanDefinition:过装了一切用来生产bean方式
BeanFactory和ApplicationContext的异同?
相同:
- Spring提供了两种不同的IOC容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContext继承于BeanFactory(ApplicationContext继承ListableBeanFactory。
- 它们都可以用来配置XML属性,也支持属性的自动注入。
- BeanFactory和ApplicationContext都提供了一种方式,使用getBean("bean name")获取bean。
不同:
- 当你调用getBean()方法时,BeanFactory仅实例化bean,而ApplicationContext 在启动容器的时候实例化单例bean,不会等待调用getBean()方法时再实例化。
- BeanFactory不支持国际化,即i18n,但ApplicationContext提供了对它的支持。
- BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为监听器的bean。
- BeanFactory 的一个核心实现是XMLBeanFactory 而ApplicationContext 的一个核心实现是ClassPathXmlApplicationContext,Web容器的环境我们使用WebApplicationContext并且增加了getServletContext 方法。
- 如果使用自动注入并使用BeanFactory,则需要使用API注册AutoWiredBeanPostProcessor,如果使用ApplicationContext,则可以使用XML进行配置。
- 简而言之,BeanFactory提供基本的IOC和DI功能,而ApplicationContext提供高级功能,BeanFactory可用于测试和非生产使用,但ApplicationContext是功能更丰富的容器实现,应该优于BeanFactory
源码步骤分析:
- 实例化一个ApplicationContext的对象 new springApplication()
- 解析xml配置文件路径(AbstractApplicationContext#obtainFreshBeanFactory)
- 创建Bean工厂
- 加载bean定义到BeanDefinitionMap
- 调用了bean工厂的后置处理器
invokeBeanFactoryPostProcessors
》org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
》org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons - 判断是否符合生产标准(是不是抽象、懒加载、单例}
》org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
- 真正的生产Bean,去单例池中获取看是否已经创建,如果已经创建则直接返回,如果单例池没有就需要重新创建(为了解决循环依赖,将当前Bean加入到正在创建的标识中singletonsCurrentlyInCreation)
》org.springframework.beans.factory.support.AbstractBeanFactory#createBean 》org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
8.可以使用Bean的后置处理器直接返回自定义的Bean实例
9.调用doCreateBean开始真正创建Bean
》org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
10.实例化Bean(通过工厂方法、Supplier、Bean后看处理器)
》SmartlnstantiationAwareBeanPostProcessor.determineCandidateConstructors
11.注入属性的值
》org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
12.初始化Bean 调用Awea 调用@PostConstrut Aop的动态代理也是在初始完进行生成的
13.最终加入到单例池中
9个Bean的后置处理器
- InstantiationAwareBeanPostProcessor.postProcessBeforelnstantiation
- SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
- SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
- InstantiationAwareBeanPostProcessor.postProcessPropertyValues
- BeanPostProcessor.postProcessBeforelnitialization
- BeanPostProcessor.postProcessAfterlnitialization
- DestructionAwareBeanPostProcessor.requiresDestruction
加载Bean的流程类似下图
maven常用命令
- clean:清理编译后的目录
- compile:编译,只编译main目录,不编译test中的代码
- test-compile:编译test目录下的代码
- test:运行test中的代码
- package:打包,将项目打包成jar包或者war包
- install:发布项目到本地仓库,用在打jar包上,打成的jar包可以被其他项目使用
- deploy:打包后将其安装到pom文件中配置的远程仓库
- site:生成站点目录