目标
追踪下面一段代码的流程:
AnnotationConfigApplicationContextDemo
流程
核心逻辑都在AnnotationConfigApplicationContext的带参构造器中:
空构造器做了什么
先说答案: 两个事情,一是创建了BedefinitionReader、BeanDefinitionScanner,提供了扫描BeanDefinition的能力; 二是通过父类GenericApplicationContext的构造器创建了DefaultListableBeanFactory,提供底层的IOC能力。
初始化AnnotatedBeanDefinitionReader
提供注册beanDefinition的能力
我们会在后面探究BeanDefinitionRegistry注册BeanDefinition的本质
获取环境对象 getOrCreateEnvironment这个方法进行环境的创建并获取:
环境对象中包含了系统环境变量,自定义属性等内容。
通过构造器可以看到,AnnotatedBeanDefinitionReader底层维护了一个BeanDefinitionRegistry。实际上,他就是通过BeanDefinitionRegistry提供的注册能力,而AnnotationConfigApplicationContext本身就是一个BeanDefinitionRegistry;所以在调用AnnotatedBeanDefinitionReader构造器时,我们传入的就是AnnotationConfigApplicationContext:
初始化AnnotatedBeanDefinitionReader
初始化DefaultListableBeanFactory
首先探究以下AnnotationConfigApplicationContext和DefaultListableBeanFactory之间的关系:
实际上是组合关系,AnnotationConfigApplicationContext中大部分的能力,包括注册beanDefinition,依赖查找,依赖注入,都是通过DefaultListableBeanFactory通过的底层能力支持。
如何将配置类注册为BeanDefinition
在AnnotationConfigApplicationContext中:
从上面代码可以看出,主要是调用了reader的register方法完成的注册,来看下这个方法的实现逻辑
综合上述代码,整理以下doRegisterBean的大致逻辑:
- 创建一个配置类对象的AnnotationBeanDefinition
-
通过AnnotationBeanDefinition解析类上面是否存在@Conditional注解,并判断是否满足注册的条件,如果不满足,则不进行注册
-
向abd中注册方法入参传入的 Supplier,后续可通过该接口实现bean的实例化
-
解析@Scope属性并注册到abd中
-
创建beanName
-
解析下面几个注解,并将对应属性注册到abd中
- @Lazy
-
@Primary
-
@Role
-
@DependesOn
-
@Description
-
创建一个beanDefinitionHolder保存abd和beanName,alias之间的对应关系
-
处理非单例Scope,返回一个代理,详见@Scope的处理过程
-
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
我们来看下第9步,究竟是如何注册的:
可以看到,实际进行了两部分注册:
- 注册beanName
-
注册别名
其中registry都是AnnotationConfigApplicationContext 先看一下registerBeanDefinition方法的实现:
如下所示,我们调用的应该是GenericApplicationContext中的实现方法,进去看看:
结果发现还是使用的DefaultListableBeanFactory进行注册的,这也论证了我们上面关于DefaultListableBeanFactory和AnnotationConfigApplicationContext之间关系的结论。来看看DefaultListableBeanFactory中究竟是怎么实现的吧:
上述的代码,先检查了容器中是否已经注册过了该bd,再检查了是否正在注册该db;而我们是第一次注册,所以走的核心分支就是第59行开始的else分支。做了下面几件事情:
- 向beanDefinitionMap中放入了beanName为key的beanDefinition
-
向beanDefinitionNames中放入了beanName
-
如果manualSingletonNames中存在beanName,将其移除
为什么要单独维护一个beanDefinitionNames?主要是因为beanDefinitionMap是无序的,而beanDefinitionNames是一个ArrayList,是有序的,可以保存bd的注册顺序
refresh方法都做了什么
1.prepareRefresh
预刷新阶段主要做了一下几件事情:
- 提供initPropertySources()扩展方法供容器进行外部资源加载,在AnnotationContextApplicationContext中默认是空实现
默认容器中是没有必须存在的属性的,如果需要添加该校验,则通过beanFactory获取到Environment,然后再进行设置:
实际上是调用的AbstractPropertyResolver类的下面方法
requiredProperties是一个LinkedHashSet
-
在容器中创建earlyApplicationListeners、earlyApplicationEvents
2.obtainFreshBeanFactory
通过该方法的返回值可以判断他就是获取了容器中内置的ConfigurableListableBeanFactory,我们来看他具体是怎么获取的:
其中:getBeanFactory()方法是很好理解的,他就是把GenericApplicationContext中保存的DefaultListableBeanFactory返回,这个DefaultListableBeanFactor是在GenericApplicationContext的空构造器中实例化的。 我们看下refreshBeanFactory()中做了什么:
主要是对refreshed进行了cas修改,以保证容器只会被刷新一次
3.prepareBeanFactory(beanFactory)
容器的准备阶段
-
设置ClassLoader
-
设置el表达式解析器
-
设置PropertyEditorRegistrar
-
添加一个ApplicationContextAwareProcessor判断bean是否实现了下面的Aware接口,如果实现了,这把相应的内建bean或单例对象赋给该bean 1.EnvironmentAware -> applicationContext.getEnvironment() 2.EmbeddedValueResolverAware -> embeddedValueResolver 3.ResourceLoaderAware -> applicationContext 4.ApplicationEventPublisherAware -> applicationContext 5.MessageSourceAware -> applicationContext 6.ApplicationContextAware -> applicationContext 7.ApplicationStartupAware -> applicationContext.getApplicationStartup()
-
ignoreDependencyInterface:在自动装配时忽略下面这些接口,实现了下述接口,可以通过set方法接受aware回调传入的值进行装配
- 添加容器内建依赖。容器的内建依赖会保存在resolvableDependencies,支持通过类型进行依赖注入,主要解决的问题是同一种类型存在多个依赖对象,spring在自动装配的时候会报错,但是如果在resolvableDependencies中指定了具体类型的装配对象,则直接可以使用指定对象。spring容器中存在多个BeanFactory等类型的对歌对象,所以这里将其依赖对象指定,避免报错。我们也可以通过自定义BeanFactoryPostProcessor获取Beanfactory,然后指定自己的类型-依赖对象关系。
- 添加ApplicationListenerDetector,DestructionAwareBeanPostProcessor:bean曝光前回调,在对外提供bean实例之前,可以返回代理对象替换beanMergedBeanDefinitionPostProcessor
4.postProcessBeanFactory
预留的扩展方法,默认没有实现
5.invokeBeanFactoryPostProcessors(beanFactory)
关于BeanFactoryPostProcesso,我们先了解下面两点:
- 注册BeanFactoryPostProcessor:ConfigurableApplicationContext#addBeanFactoryPostProcessor
-
BeanFactoryPostProcessor的作用:
简而言之,就是在第3步将内置beanfactory准备完毕之后。给用户一次机会再获取到beanFactory 接下来我们研究invokeBeanFactoryPostProcessors的流程,这里默认容器中是不会注册BeanFactoryPostProcessor的,但是这个方法还有其他的作用
getBeanFactoryPostProcessors()
PostProcessorRegistrationDelegate
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
主要流程:
- 创建两个list分别保存BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
-
将自定义注册的BeanFactoryPostProcessor按照类型分别存入regularPostProcessors或者registryProcessors,并且:如果是BeanDefinitionRegistryPostProcessor,则直接调用其postProcessBeanDefinitionRegistry方法
-
创建一个新的列表来保存容器内置的BeanDefinitionRegistryPostProcessor
-
通过BeanDefinitionRegistryPostProcessor类型以及PriorityOrdered获取容器中对对应的bean,放入currentRegistryProcessors,并将名字放入processedBeans,表示已经执行。这里会得到一个:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
-
将currentRegistryProcessors排序,并且放入registryProcessors
-
遍历执行currentRegistryProcessors中的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
-
这里会执行internalConfigurationAnnotationProcessor的回调方法,这个类后续会专项研究,其结果就是把配置类中@Bean方法对应的类加载到容器中注册为bd
-
清空currentRegistryProcessors
-
重复4-8,调用的是实现了Ordered接口的BeanDefinitionRegistryPostProcessor
-
重复4-8,调用没有实现排序接口的BeanDefinitionRegistryPostProcessor
-
通过上面的操作,所有的BeanDefinitionRegistryPostProcessor都加入了registryProcessors,所有的自定义BeanFactoryPostProcessor都加入了regularPostProcessors。执行他们的postProcessBeanFactory方法
-
现在还有容器内置的BeanFactoryPostProcessor没有处理,也按照PriorityOrdered,Ordered,nonOrdered的顺序依次加载并调用他们的postProcessBeanFactory方法
6.initMessageSource
MessageSource列为专题讨论
7.initApplicationEventMulticaster()
事件广播机制列为专题讨论
8.onRefresh
截止到这里,整个beanfactory已经准备就绪了。剩下的就是容器中的bean的处理了,再此之前,可以通过onFresh方法执行回调。例如在SpringBoot中,就是通过这个方法进行的嵌入式web容器启动
9.registerListeners()
- 注册容器内置的listener
-
注册实现了ApplicationListener接口的类
10.inishBeanFactoryInitialization(beanFactory)
实例化所有非懒加载的单例bean 这个流程又是非常复杂的逻辑,我们放在第二章进行讨论
总结
经过上述的步骤,spring容器已经初始化完成,beanFactory准备就绪。ApplicatiionContext提供的扩展特性:事件机制,资源,AOP等能力也已经初始化完成
最后
我想,可能还有很多人在今年刚过去的金三银四春招中保持着观望的形势,害怕自己的能力不够,或者是安于现状,觉得目前拿着几千的月薪觉得能够接受,那么你就要注意了,这是非常危险的!
我们身为技术人员,最怕的就是安于现状,一直在原地踏步,那么你可能在30岁就会迎来自己的职业危机,因为你工作这么久提升的只有自己的年龄,技术还是万年不变!
如果你想在未来能够自我突破,圆梦大厂,那或许以上这些Java面试题资料,你需要阅读阅读,希望能够对你的职业发展有所帮助。
进
【
Java进阶之路群】,找管理员获取哦!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70000430/viewspace-2780654/
,如需转载,请注明出处,否则将追究法律责任。