Spring 源码分析
2021-12-02 22:14:29 2 举报
spring 源码解析,IOC,AOP ,bean 的生命周期,源码流程概览
作者其他创作
大纲/内容
注入属性值
String beanName : beanNames
DefaultSingletonBeanRegistry # getSingleton
执行已经在 spring 容器中注册的 beanFactoryPostProcesor(bean 工厂的后置处理器),其实就是上面提到过的ConfigurationClassPostProcessor,spring 的包扫描,或 mybatis 扫描 mapper 接口,以及 @Import,@ImportSelector,@ImportBeanDefinitionRegistra 都在这里进行处理
for
orderedPostProcessors.add(pp);
InitDestroyAnnotationBeanPostProcessor # invokeInitMethods
registerBeanDefinitionForImportedConfigurationClass(configClass);
synchronized (this.singletonObjects)
AnnotatedGenericBeanDefinition
AnnotationConfigApplicationContext # refresh()
这里都是在执行开发者自定义的 bean 工厂后置处理器,如果开发者没有添加自定义的 beanFactorypostprocesor,则可忽略
getSingleton(beanName)这个方法在初始化的时候会调用,在 getBean() 的时候也会调用也就是说 Spring 在初始化的时候会先获取这个对象,判断这个对象是否已经被实例化好从 Spring 的 bean 容器中获取一个 bean,由于 Spring 的 bean 容器是一个 map (singleObjects)所以可以把 getSingleton(beanName) 理解为 beanMap.getBean()这个方法在 doGetBean() 方法中会被调用两次,两次是不同的重载方法,也是解决 Spring 循环依赖的关键
调用实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessors ConfigurationClassPostProcessor 实现了 PriorityOrdered 接口,所以在这里会被调用
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
afterSingletonCreation(beanName);
这个 this 即 GenericApplicationContextthis.beanFactory 即 DefaultListableBeanFactory,之前已经写过了,忘了可以看前面
初始化一个 Set 集合用于存放 BeanDefinitionHolder 类,可以把 BeanDefinitionHolder 看做是一个数据结构,是对 BeanDefinition 的一个封装,里边有三个属性, BeanName BeanDefinition Alias
注意,getBean 方法这里暂时不讲,在之后的流程会详细说明 bean 的实例化,流程都一样,只需要知道 ConfigurationClassPostProcessor 这个类此时已经成了 bean 对象,交由 spring 管理
ConfigurationClass configClass : configurationModel
return candidateName;
DefaultListableBeanFactory # resolveDependency
这二者之间不存在继承关系
beanDefinitnioMap
true
这是一个beanPostProcessor,处理 @Autowired 自动装配,在后面会详细解释
注解启动,首先 new 一个 spring 容器,将配置类传入
this.beanFactory
postProcessBeanFactory(beanFactory)
false
在这之前,spring实际还对 bean 的构造方法作了推断,看有没有合适的构造方法,如果没有,再进入这个方法,调用无参构造,实例化 bean 对象
在这个方法里会判断,当前 bean 是否实现了 Aware 接口及其子接口,如果实现了,则调用当前 bean 实现的Aware 接口的的方法
sbd.setResource(resource);
同上。。。。。。
BeanDefinitionRegistryPostProcessor postProcessor : postProcessors
main 方法
这里步骤较多,只i挑选了重要步骤
先添加到集合列表中,最后会循环这个列表统一执行
private final DefaultListableBeanFactory beanFactory
在这个方法里 spring 给 bean 工厂添加了两个 beanPostProcessor,即 bean 的后置处理器
根据指定的 beanClass 创建一个 AnnotatedGenericBeanDefinition,这个 beanClass 即传入的配置类 AppConfig
再从单例池中获取一次 bean,严谨性
AbstractBeanDefinition
参数 this 即 AnnotationConfigApplicationContext
implements
BeanDefinitionReaderUtils # registerBeanDefinition
newSingleton = true;
Class<?> candidateClass = candidate.loadClass();
return singletonObject;
DefaultListableBeanFactory
ConfigurationClassPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
new AnnotationConfigApplicationContext(AppConfig.Class)
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
candidate.setScope(scopeMetadata.getScopeName())
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata())
这也是一个beanPostProcessor,处理通用注解,比如 @Resource 注解
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>(); 存放bean 工厂的后置处理器的列表
GenericApplicationContext
registry 是 AnnotationConfiApplicationContext
extends
Object singletonObject = this.singletonObjects.get(beanName);
如果上面的判断都不通过,则返回 null
element.invoke(target)
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this))
准备了 2 个 list 集合,根据 beanpostprocessor 实现的接口分类装进不同的集合中注册顺序已实现的接口排序 PriorityOrdered ---> Ordered ---> regular
这里从 new 一个 AnnotationConfigApplicationContext 作为程序入口
这里就可以看出,@Primary 比 @Priority 优先级更高
判断 当前循环的BeanDefinition 是否加了注解,然后判断加了什么注解,之前已经说明,现在能拿到的除了 spring 内置的类,就只有 new 容器时注册的 AppConfig配置类,所以这里实际是在处理开发者提供的配置类,看他是否需要被 cglib 代理如果加了 @Configuration 注解 ,下边 4 个注解不会在判断如果没加 @Configuration 注解,才会判断 candidateIndicators.add(Component.class.getName()); candidateIndicators.add(ComponentScan.class.getName()); candidateIndicators.add(Import.class.getName()); candidateIndicators.add(ImportResource.class.getName());如果存在 @Configuration 注解, 则为 BeanDefinition 设置 CONFIGURATION_CLASS_ATTRIBUTE 属性为 CONFIGURATION_CLASS_FULL如果不存在 @Configuration 注解但存在以上注解, 则为 BeanDefinition 设置 CONFIGURATION_CLASS_ATTRIBUTE 属性为 CONFIGURATION_CLASS_LITE当前类只要存在以上的注解,都会将它放进 list --> configCandidates 中从 checkConfigurationClassCandidate 的判断可以解释为什么配置类 AppConfig 不管有没有加上 @Configuration 注解都会解析这里就可以判断当前解析的类是否是个 全注解 的配置类 ,可如果没有加上 @Configuration只有以下 4 个注解中的任意一个,虽然 spring 也会把它当成是个配置类,但它只是个 半注解 配置类,其实就是在讨论 @Configuration 注解的真正作用
AbstractAutowireCapableBeanFactory
对 bean 属性进行注入
实例化 ConfigurationClassParser, 为接下来包扫描做解析
最后 调用开发者自定义的 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法,如果没提供则忽略
这两个方法要递归调用之后才能进入,加入到 importStack 后调用 processConfigurationClass 进行处理,processConfigurationClass 主要是把类放到 configurationClasses,configurationClasses 是一个集合,在后边会拿出来解析成 BeanDefinition 继而注册,可以看到普通类在扫描的时候就被注册,如果是 ImportSelector , 会先放到 configurationClasses 后面进行注册
scanCandidateComponents(basePackage)
ConfigurationClassBeanDefinition
从二级缓存中去取出单例 bean,放入三级缓存并移除二级缓存中对应的单例 bean,这里的一系列操作都跟 spring 的循环依赖有关,详细可以看笔者另外一幅图 《spring 循环依赖》
判断 Map 中的对象所属的类是否有加上了 @Primary 注解
解析注解对象,并把解析出来的 BeanDefinition 放入 map,但这里的 BeanDefinition 只是普通的 bd什么是不普通的? 比如 @Bean 和各种 BeanFactoryPostProcessor 得到的 bean 不在这里put 但也是在这里解析,只是不会 put 进 beanDefinitionMap
PostProcessorRegistrationDelegate #registerBeanPostProcessors
AnnotationConfigApplicationContext # this()
把 beanName 添加进 singletonsCurrentlyInCreation Set 集合中
BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors
完成BeanFactory的初始化创建工作;IOC容器就创建完成
DefaultSingletonBeanRegistry
String basePackage : basePackages
循环candidates ,处理扫描到的 beanDefiniton
BeanDefinitionRegistry
这里放入了两个 spring 内置的后置处理器 AutowiredAnnotationProcessor CommonAnnotationProcessor这是一开始 spring 就已经封装好 bd 的,之前的流程已经提到过,此时会将这两个 bp 放入这两个集合中
至此,Spring 容器创建完成
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
CommonAnnotationBeanPostProcessor # postProcessBeforeInitialization
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
给容器注册 bean 的常用的几种方式: @Bean(导入第三方包或组件,在容器中使用,如 SqlSessionFactory) @ComponentScan + @Controller / @Service /@Repository / @Component /@Configuration,包扫描 + 注解标注 @Import 快速导入一个类 ImportSelector ImportBeanDefinitionRegistar
创建 BeanDefinition 并添加到 beanDefinitionMap 中
做一些准备工作:包括设置启动时间 是否激活标识位初始化属性源头(Property source)配置
loadBeanDefinitionsForBeanMethod(beanMethod);
ClassPathBeanDefinitionScanner # doScan((String... basePackages))
singletonObject = singletonFactory.getObject();
orderedPostProcessorNames.add(ppName)
写在前面
beforeSingletonCreation(beanName);
beanDefs.add(holder)
这里执行的是实现了 BeanPostProcessor 接口的 postProcessBeforeInitialization 方法@PostConstruct 就是在这里执行
List<String> nonOrderedPostProcessorNames = new ArrayList<>()
beanFactory.addBeanPostProcessor(postProcessor)
判断 beanDef 的属性 CONFIGURATION_CLASS_ATTRIBUTE,这里在之前的流程已经提到过,就是看是否加了 @Configuration 注解,如果加了则为 true,如果没有加,则不对 AppConfig 做 cglib 代理加强
AutoProxyCreator 一个 beanPostProcessor,AOP 的 后置处理器,在之后 InitializeBean 方法中调用该后置处理器为实现了 AOP 的对象创建代理
这里从 Spring 容器中获取可以注入的 bean 对象,也是循环依赖注入的关键出口,详细可查看笔者另外一幅图 《Spring 循环依赖》
按照类型找到可注入属性的所有对象,然后把对象都缓存到一个 Map 中
将当前 registry 转换为 DefaultListableBeanFactory ,为什么这里的 registry 需要反复转换,跟 spring 的 beanfactory 继承链有关,见上,先根据当前 registry 在哪一条继承链上,如果是 GenericApplicationContext ,那么调用它的 getDefaultListableBeanFactroy,返回一个 DefaultListableBeanFactroy
internalPostProcessors.add(pp)
scanner 会遍历 @ComponentScan 包含以及过滤的包
判断该类名对应的类是否实现了 Ordered接口
将封装好的 beanDefinition 存放进集合中,并返回
循环processors,这里以 CommonAnnotationBeanPostProcessor,通用主节后置处理器为例
判断是否是 FactoryBean,如果是 FactoryBean,则需要加上 & 符号
从 bean池 中获取的 bean 如果不为空直接返回
Field field = (Field) this.member;
定义一个 list 存放 app 中提供的 BeanDefinition
给 bean 工厂做一些必要的准备工作
refresh 方法里执行的所有方法都使用了 synchronized 加了锁,锁时一个 Object 对象,保证线程安全
beanFactory 家族中各个成员类中重要的属性
Object sharedInstance = getSingleton(beanName);
是否是多例
BeanDefinition 是 对 bean 的一个描述,spring 在实例化 bean 之前,会首先将要交给 spring 管理或创建的类的信息封装为 BeanDefinition 对象,这里举了几个接口和类,如 : AnnotatedBeanDefinition,专门负责描述加了注解的类,如 @Sevice,@Controller 等 RootBeanDefinition 则负责描述 spring 内置的 bean,这些bean会对初始化 spring 容器起到重要作用 ConfigurationClassBeanDefinition 负责描述 @Bean注解标示的类
this.reader.register(componentClasses)
refresh 方法是整个 spring 源码中的重中之重
AutowiredAnnotationBeanPostProcessor # postProcessProperties
AbstractApplicationContext
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
AnnotationConfigUtils # registerAnnotationConfigProcessors(this.registry);
将创建好的 beanPostProcessor 放入准备好的 list 集合中
判断该 bp 是否属于 MergedBeanDefinitionPostProcessor 的子类
国际化
DefaultListableBeanFactory #registerBeanDefinition
把需要注入的属性名放入 autowiredBeanNames List 中
这是一个空方法,没有执行任何代码, spring 可能会在后续版本做扩展
else
这幅图笔者画了近一个月,一开始想看看本网站有没有现成的 spring 源码解析图,但翻看了很多,感觉都不够详细(笔者也想偷懒啊),于是乎,只能自己动手,丰衣足食。 笔者建议,读者在翻看这幅图的时候,自己先写一个 spring 小 demo,new 一个 span style=\
判断 Map 中的对象所属的类是否有加上了 @Priority注解
synchronized (this.singletonObjects)
List<String> orderedPostProcessorNames = new ArrayList<>();
对当前这个单例 bean 加锁
!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)
beanDefs 就是之前 new 得一个 LinkedHashSet
currentRegistryProcessors.add(font color=\"#f44336\
this.registeredSingletons.add(beanName);
调用这个读取器的构造方法,其参数做了一个向上引用,BeanDefinitionRegistry 也是 AnnotationConfigApplicationContext 的父接口
initApplicationEventMulticaster();
创建一个的读取器,只读取通过注解定义的 bean,在此处注册一些 Spring 初始化需要的类,这些类都是 Spring 内置的类,且都只是 BeanDefinition 而非 Bean(BeanDefinition 释义见右边)span style=\
与读者约定
这个 registry 已经向上引用变成了 BeanDefinitionRegistry
将实例化好的 bp bean 对象放入后置处理器集合列表中
beanName = FACTORY_BEAN_PREFIX + beanName
candidate.isAssignable(ImportBeanDefinitionRegistrar.class)
DefaultListableBeanFactory # preInstantiateSingletons
DefaultListableBeanFactory这个类非常关键,它就是 BeanFactory 的实现类,就是 bean 工厂,beanDefinitnioMap 就是它的属性之一,是一个 ConcurrentHashMap,负责存放 Bean的定义信息--BeanDefinition,同时也继承了 DefaultSingletonBeanRegistry,spring 的三级缓存 singletonObjects,存放单例 bean 的 Map,也就是很多初学者理解的 spring 容器,这是错误的理解 singletonFactories, earlySingletonObjects 都是 DefaultSingletonBeanRegistry 的属性但是 DefaultSingletonBeanRegistry 和 BeanFactory 并不处于同一条继承链上
AnnotationConfigApplicationContext
componentClasses 即传入的 AppConfig.class,开发者提供的 spring 配置类,这一个方法实际就是将开发者自定义的 java (不仅仅是配置类)封装成 beanDefinition,并 put 进 beanDefinitionMap 中
首先进入 AnnotationConfigApplicationContext 的构造方法,调用 this()方法 时候首先应该调用其父类 GenericApplicationContext 的构造方法,然后再执行 this() 方法
isFactoryBean(beanName)
这个继承图并不完整,只画了重要的接口和类
matchingBeans.size() > 1
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
processConfigBeanDefinitions(registry)
spring beanFactory接口详细介绍
String ppName : orderedPostProcessorNames
ConfigurableListableBeanFactory
String beanName = transformedBeanName(name);
mbd.isPrototype()
beanDef.setResource(configClass.getResource());
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
finishRefresh()
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class)
font color=\"#f44336\
这个方法主要是处理 Bean 的后置处理器,所有的 beanPostProcessor 都是在这里变成了 bean ,包括开发者自定义的后置处理器,借此空白,简单概述一下 BeanPostProcessor BeanPostProcessor 是 Spring 框架通过的一个扩展类点(不止一个) 通过实现 BeanPostProcessor 接口 ,程序员可以插手 bean 的实例化过程 , 减轻 BeanFactory 的负担 这个接口可设置多个,形成一个列表 beanPostProcessors,然后依次执行 具体查看 AbstractBeanFactory , private final List<BeanPostProcessor> beanPostProcessors=new CopyOnWriteArrayList<>(); 此属性 维护一个 List<BeanPostProcessor> public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor){ this.beanFactoryPostProcessors.add(postProcessor); } 方法添加一个 BeanPostProcessorList<BeanPostProcessor> getBeanPostProcessors() 此方法返回 BeanPostProcessors 列表 在整个 bean 的实例化过程中,依次循环这个 List<BeanPostProcessor> 来达到插手 bean 实例化的过程 比如 AOP 就是在 bean 的实例化后将切面逻辑动态的织入 bean实例中,AOP 也正是通过 BeanPostProcessor 和 IOC 容器建立起了联系 Spring 默认提供了喝多 PostProcessor 1. ApplicationContextAwareProcessor 作用: 当应用程序定义的 Bean 实现了 ApplicationContextAware 接口时给其注入 ApplicationContext 对象 2.InitDestroyAnnotationBeanPostProcessor 作用: 用来处理自定义的初始化方法和销毁方法 Spring 提供了 3 种自定义初始化和销毁方法 1.通过 @Bean 指定 init-method 和 destroy-method 属性 2.Bean 实现 InitializingBean 和 DisposableBean 接口 3.@PostConstructor 和 @PreDestroy 3.InstantiationAwareBeanPostProcessor 4.CommonAnnotationBeanPostProcessor 5.AutowiredAnnotationBeanPostProcessor 6.RequireAnnotationBeanPostProcessor 7.BeanValidationPostProcessor 8.AbstractAutoProxyCreator (AOP)
ClassPathScanningCandidateComponentProvider # findCandidateComponents
第二个值恒定为 true,表示允许循环依赖
pp instanceof MergedBeanDefinitionPostProcessor
ImportSelector 和 ImportBeanDefinitionRegistra 接口的区别: 二者都可以向 Spring 容器注入 bean 不过 ImportSelector 接口属于静态配置,使用该接口配置 bean 之前,这个类必须已经存在,在 selectImports 方法中返回类的全限定名 例如:spring 声明式事务 而 ImportBeanDefinitionRegistra 接口更加灵活,属于动态配置,java 类可以不存在,在 ImportBeanDefinitionRegistra 接口中的 registerBeanDefinitions 方法中动态生成 beanDefinition,手动添加进 bdMap 例如:@MapperScan
autowiredBeanNames.add(autowiredBeanName)
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
这个 reader即上面实例化的 读取器 AnnotatedBeanDefinitionReader
ConfigurationClassBeanDefinitionReader # loadBeanDefinitions
String beanName : candidateNames
这里执行的是实现了 BeanPostProcessor 接口的 postProcessAfterInitialization 方法,AOP 代理就是在这里实现的
继承 extends
空壳方法
循环遍历 resource,找到需要扫描的包中所有的 java 类
processConfigurationClass(candidate.asConfigClass(configClass));
因为 上边的 registryProcessors 存放的是开发者自己定义实现的 BeanDefinitionRegistryPostProcessor 接口的类,这里的 currentRegistryProcessors 存放的是 Spring 内部自己定义实现了 BeanDefinitionRegistryPostProcessor 接口的类,spring 将其分开执行
调用当前 bean 对象的 被@PostConstruct 注解标注的方法
注意,虽然是同一个类,但二者调用的方法不一样,postProcessBeanDefinitionRegistry 是 BeanDefinitionRegistryPostProcessor 接口的方法,postProcessBeanFactory 是 BeanFactoryPostProcessor 接口的方法
regularPostProcessors.add(postProcessor);
AnnotationConfigUtils # registerPostProcessor
BeanFactory
addSingletonFactory 将刚刚实例化的 bean 放入二级缓存 singletonFactory
ConfigurationClassPostProcessor # postProcessBeanFactory
循环第一部拿到的 String 数组,里边存放了当前 beanDefinitionMa 中所有的 beanPostProcessor 的类名
BeanDefinition 释义
合并list registryProcessors 、 currentRegistryProcessors 两个 list 集合,即开发者自定义的 BeanDefinitionRegistryPostProcessor 和 Spring 内部的 BeanDefinitionRegistryPostProcessor
这里循环一般情况 postProcessors 只有一条数据,即 ConfigurationClassPostProcessor,除非还有用户自定义的 bean工厂后置处理器
prepareRefresh()
postProcessor.postProcessBeanDefinitionRegistry(registry)
先准备一个集合用于存放扫描到的类
GenericApplicationContext # 构造方法
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
spring 判断应该注入哪个 bean 为当前 bean 对象的属性值
实现 implements
this.beanFactory = new DefaultListableBeanFactory();
this.reader.loadBeanDefinitions(configClasses)
initMessageSource();
AnnotatedBeanDefinitionReader # AnnotatedBeanDefinitionReader (BeanDefinitionRegistry registry)
在容器中找到可装配属性值的对象
nonOrderedPostProcessorNames.add(ppName);
candidates.add(sbd);
class
BeanMethod beanMethod : configClass.getBeanMethods()
postProcessor instanceof BeanDefinitionRegistryPostProcessor
ConfigurableListableBeanFactory 也是一个 BeanFactory 的接口,这里做了一个向上引用详细见上边的 beanFactory 继承图
ConfigurableBeanFactory
getBean(beanName)
注册 ImportSelector 导入的类,还是先封装成 beanDefinition,再放入beanDefinitionMap
判断该类名对应的类是否实现了 PriorityOrdered 接口
this.earlySingletonObjects.remove(beanName);
这里 add 进去的只有开发者提供的配置类,即加了以上注解的类
Set<BeanDefinition> candidates = findCandidateComponents(basePackage)
为什么要对配置类进行 cglib 加强?如果不增强的情况下,@Bean 方法 A 希望在创建 A 的过程中调用 @Bean 方法 B 作为自身属性,那么必然是一个 new 的新对象 B,无法保证单例B的存在,所以 cglib 后就是为了增加额外的判断保证单例cglib加强类的父接口为EnhancedConfiguration,继承了BeanFactoryAware,所以该类现在实现了 BeanFactoryAware 接口BeanFactoryAwareGeneratorStrategy 负责为 cglib的代理类申明 $$beanFactory 字段 用于存放BeanFactoryBeanFactoryAwareMethodInterceptor 负责拦截ImportAwareBeanPostProcessor中触发的setBeanFactory方法,做一些额外处理并赋值BeanFactory至 $$beanFactory字段。额外操作是什么呢?如果其被加强的原始的类实现了setBeanFactory 则会调用真正的原始类的setBeanFactory 否则只是会给proxy通过反射塞入beanFactoryBeanMethodInterceptor在访问@Bean注解的方法是,优先从属性$$beanFactory中获取Bean的实例,保证单例
Author:helloworld
registryProcessor.postProcessBeanDefinitionRegistry(registry);
candidate.isAssignable(ImportSelector.class)
如果当前 bean 实现了 InitializingBean 接口,执行当前 bean 实现该接口的 afterPropertiesSet 方法,这也是一个初始化方法,然后再执行 bean 的生命周期初始化回调方法 init-method,不是 @PostConstruct
用 beanName 生成器生成一个 beanName
prepareBeanFactory(beanFactory)
得到 @Import 中导的value,即需要导入的全路径类名,即 XxxImortSelector 全限定名
如果以上接口都没有实现,就放入这个list 集合
获取到依赖的类型,即属性需要注入的类型
postProcessor.postProcessBeanFactory(beanFactory);
装配属性 @Value @Autowired注解
循环遍历每一个需要扫描的包
Class<?> candidateClass = candidate.loadClass()
parser.parse(candidates)
enhanceConfigurationClasses(beanFactory)
BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor 扩展了 BeanFactoryPostProcessor接口,开发者自定义的 BeanFactoryProcessor 可以有两种实现方式,实现 BeanDefinitionRegistryPostProcessor 或者 BeanDefinitionRegistryPostProcessor,实现功能不同,所以准备两个 list 存放不同的 BeanFactoryProcessor,接下来做不同处理
getFactory() 返回的是 DefaultListableBeanFactory
BeanPostProcessor postProcessor : postProcessors
上边也有一个 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); 为什么 Spring 要定义两个 List<BeanDefinitionRegistryPostProcessor> ?
注册 BeanPostProcessor,包括开发者自定义的 beanPostProcessor 也在此处被注册Spring 5.1 之前的版本会注册进 7 个 BeanPostProcessor但在 5.1 版本之后,RequiredAnnotationBeanPostProcessor 这个后置处理器被弃用了font color=\"#000000\
return priorityCandidate;
Set<BeanDefinition> candidates = new LinkedHashSet<>();
ApplicationContext
else if
singletonFactory.getObject();这个方法实际执行的就是getSingleton 的第二个参数,函数表达式里的 createBean() ----> doCreateBean()这里就返回了一个已经创建好并且完成了属性注入的 bean
singletonObject = this.earlySingletonObjects.get(beanName);
registryProcessors.addAll(currentRegistryProcessors)
先从三级缓存中取单例 bean对象
this.registry.registerBeanDefinition
重要
interface
this.singletonFactories.remove(beanName);
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
存放 bean 的后置处理器列表
sbd.setSource(resource);
String[] candidateNames = registry.getBeanDefinitionNames();
singletonFactory != null
得到 @Import 中导的value,即需要导入的全路径类名,即 XxxImortBeanDefinition 全限定名
将 AppConfig 封装为 BeanDefinitionHolder
从容器中获取当前所有注册的 BeanDefinition 的名字,此时只有 spring 内置的那几个 beanDefinition 以及开发者在 new 容器的时候传入的那个配置类 AppConfig
Class<?> type = descriptor.getDependencyType();
PS:笔者用的 spring 版本是 5.1.10
registerBean(componentClass)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
这里 getBean() 实例化了一些 Spring 初始化需要的对象,ConfigurationClassPostProcessor 类的就是在这里实例化的,因为下边调用 invokeBeanDefinitionRegistryPostProcessors 方法,需要调用ConfigurationClassPostProcessor 的 postPr,ocessBeanDefinitionRegistry 方法,所以在这里必须先实例化 ConfigurationClassPostProcessor,实例化成为 bean 对象后将它放入 currentRegistryProcessors 集合中
余下还有 4 个内置的类
return null
找到可注入的属性
BeanPostProcessor processor : getBeanPostProcessors()
if 条件判断
ComponentScanAnnotationParser # parse
AbstractApplicationContext # finishBeanFactoryInitialization
提示箭头
执行顺序,如果存在多个分支箭头,顺序由上到下,从左至右
AnnotationConfigApplicationContext #register(componentClasses)
注释箭头
String ppName : postProcessorNames
CommonAnnotationBeanPostProcessor
invokeBeanFactoryPostProcessors(beanFactory)
AnnotatedBeanDefinitionReader # register
递归调用 processImports,这里递归是为了防止导入的 类上还存在 @Import 注解
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
调用 selector 中的selectImports 方法,获取到需要交由 spring 管理的 bean的 全限定名,
处理 @Import 注解 如:mybatis 中的 @MapperScan 注解就是在这里@Import 可以处理 普通类 可以处理 ImportSelectorfont color=\"#f44336\
RootBeanDefinition
封装 ImportSelector, ImportBeanDefinitionRegistra, @Bean 等接口和注解添加的类为 bd 存入 map
isSingletonCurrentlyInCreation 方法中 this.singletonsCurrentlyInCreation.contains(beanName);判断 singletonsCurrentlyInCreation 集合中是否存在这个 beanName如果存在,则表示是一个正在被创建的 bean,如果不存在,则表示不是一个正在被创建的 bean那他是在什么时候把 beanName put 进 singletonsCurrentlyInCreation 集合中的呢? beforeSingletonCreation(beanName); 见右边在注释箭头 在 createBean 方法中,创建单例之前把这个beanName放入集合中缓存起来,表示这个 bean 正在被创建那他是在什么时候把 beanName 从 singletonsCurrentlyInCreation 集合中 remove 掉的呢? 单例 bean 创建完成,执行 afterSingletonCreation(beanName) 方法的时候
return primaryCandidate;
这个 postProcessor 就是 ConfigurationClassPostProcessor,也就是说执行它的 postProcessBeanDefinitionRegistry 方法
这里的第二个参数是一个函数式接口,这里笔者简写了,实际代码还有一个 try-catch
完成包扫描,将 @ConponengScan 扫描到的类封装为 BeanDefinition 存入 map,但 ImportSelector, ImportBeanDefinitionRegistra, @Bean 等接口和注解添加的 bean 并不是在这儿封装成bd 存入 map 中的,这些在下一步处理
finishBeanFactoryInitialization(beanFactory)
beanFactory.preInstantiateSingletons()
this.registry = registry
使用 cglib 代理 AppConfig,即开发者传入的配置类
BeanPostProcessor bp : getBeanPostProcessors()
准备好一个 list 集合,用于存放实现了 Ordered 接口的 beanPostProcessor
在构造方法里实例化 bean 工厂
判断是否匹配到了多个 bean
这几个方法不必细致解读
def.setSource(source)
this.reader = new AnnotatedBeanDefinitionReader(this);
上边调用的则是 继承了 BeanDefinitionRegistryPostProcessor 接口的 bean 工厂后置处理器,这里调用的是 继承了 BeanFactoryPostProcessor 接口的 bean 工厂后置处理器,注意看参数不同,这也是为什么 spring 要用两个 list 分开装
BeanDefinition
priorityOrderedPostProcessors.add(pp)
这两个集合只存放 bp 的 name
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
得到需要注入的属性 field
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8)
至此,将 AppConfi 配置类封装为 AnnotatedGenericBeanDefinition 放入 beanDefinitionMap 中,这里的步骤与上边 spring 处理内置类是一样的
private final DefaultListableBeanFactory beanFactory; bean 工厂
BeanDefinitionHolder holder : configCandidates
registerListeners()
AbstractBeanFactory # getBean
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
bp instanceof InstantiationAwareBeanPostProcessor
this.scanner = new ClassPathBeanDefinitionScanner(this)
以上,都只是创建了 spring 内置的类为 bean 对象,开发者自定义的 beanFactoryPostProcessor 和 beanPostProcessor,并扫描封装了开发者要交由 spring 管理的类为 BeanDefinition,这一步,才真正开始创建所有交由 Spring 管理的单例 bean
准备好一个 list 集合,用于存放剩下的 beanPostProcessor,流程与上边一样,不再赘述
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass)
AbstractBeanFactory
newSingleton
将单例 bean 放入一级缓存 singletonObjects,并把二三级缓存中的 bean 移除,最后再将当前 beanName 放入 Set集合
这里调用了一个工具类的方法
封装 @Bean 注解描述的类为 ConfigurationClassBeanDefinition,存入 beanDefinitionMap
AnnotatedBeanDefinition
得到配置类上的所有 @ComponentScan 以及其中的所有属性
这一步只是处理 @Import ImportSelector ImportBeanDefinitionRegistra导入的类,将其扫描出来存放到集合中 (这个集合并不是 beanDefinitionMap),此时,ImportSelector 和 ImportBeanDefinitionRegistra 导入的类还未封装成BeanDefinition
以上代码完成了 普通类的扫描,并且已经放入了map,何为普通类,即加了 @Component 注解的类
是否是单例
循环 BeanName,开始创建 Bean
将封装好的 BeanDefinition 存入 beanDefinitionMap
反射得 @Import 中类名,得到自定义的 XxxImportBeanDefinitionRegistrar 的实例化对象
getImportBeanDefinitionRegistrars() 方法,取出存在里边的类,看箭头提示
sharedInstance != null && args == null
构建一个 beanDefinition,将扫描的类封装成为一个 bd
ConfigurationClassPostProcessor # postProcessBeanDefinitionRegistry
CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor两个后置处理器,都在这里针对 @Resourcce 和 @Autowired 进行属性注入,这里以 AutowiredAnnotationBeanPostProcessor 为例
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
AnnotationConfigUtils #unwrapDefaultListableBeanFactory(registry)
ConfigurationClassUtils.isFullConfigurationClass(beanDef)
this.singletonFactories.remove(beanName);
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars())
singletonObjects singletonFactories earlySingletonObjects
Resource resource : resources
把开发者交给 Spring 管理的类 注册为 BeanDefinition 对象并封装进 beanDefinitionMap 中
getBeanFactoryPostProcessors() 方法先从spring 容器中取出存放 beanPostProcessor 的 list 集合,在上面 《beanFactory 家族中各个成员类中重要的属性》 中有提到,这个方法不仅能取出 spring 容器内置的 beanPostProcessor,也可以取出开发者自定义的后置处理器,但是,开发者自定义的后置处理器需要调用 app.addBeanFactoryPostProcessor(new XxxBeanFactoryPostProcessor()) 手动添加,直接在类上加 @Component 注解无效
ConfigurationClassParser # parse
注释
对 bean 做初始化工作,aop @PostConstruct init-method 就是在这里实现
注册监听器
BeanDefinition candidate : candidates
GenericApplicationContext # getBeanFactory()
scanner.doScan(StringUtils.toStringArray(basePackages));
解析 Scope 属性
调用 ImportBeanDefinitionRegistrar 的 registerBeanDefinitions 方法,手动封装 beanDefinition,存入 map中
准备初始化 spring 内置的类,这些类会在之后容器初始化过程中起到重要作用
DefaultSingletonBeanRegistry # getSingleton
InjectionMetaData # inject
这也是 spring 声明式事务实现的原理
registerBeanPostProcessors(beanFactory)
primaryCandidate != null
在这儿进行包扫描,扫描普通类,注册 BeanDefinition , put beanDefinitionMap
loadBeanDefinitionsForConfigurationClass
对 configCandidates 进行去重
进入构造方法
循环执行后边的流程
singletonObject == null && isSingletonCurrentlyInCreation(beanName)
如果 sharedInstance 是普通的单例 bean,下面方法会直接返回如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例。如果要获取 FactoryBean 本身,这里也不会做特殊处理,直接返回即可,因为 FactoryBean 本身就是一种 Bean如果判断为 true 即获取到了 bean ,直接返回不再继续后面的步骤
创建 bean 对象,此时只是一个没有对属性赋值且没有初始化的 bean
从这里可以看出,spring 默认注入方式是,先按类型查找对应的 bean,如果按类型查找存在多个 bean,那么再按属性名匹配,属性名与注入的 beanName 一致,则优先注入bytype ----> byName
反射得 @Import 中类名,得到自定义的 XxxImportSelector 的实例化对象
BeanDefinition bd = holder.getBeanDefinition();
AutowiredAnnotationBeanPostProcessor
mbd.isSingleton()
设置bd 属性
最后会返回一个 set 集合,里边存放着扫描到的类,已经被封装成了 BeanDefinition
allowEarlyReference 即第二个参数, spring 直接传了一个 true
onRefresh()
从容器中拿取 beanPostProcessor 的实例,这里的 getBean 实际上是在创建,因为spring 的规则是先获取,获取不到再创建,此时容器中还没有,所以会创建bean 返回
循环拿出当前所有 BeanDefinition
singletonObject == null && allowEarlyReference
将 beanName 添加到 singletonsCurrentlyInCreation Set 集合中,表示该 Bean实例 正在被创建这里与 Spring 的循环依赖有关
priorityCandidate != null
继续调用这个读取器的有参构造方法
单例 bean 创建完成,在这里创建完成后把 beanName 从 singletonsCurrentlyInCreation 集合中移除
0 条评论
下一页