前言
深入理解Spring源码分为7小节,本小节为Spring源码第二小节,各个小节目录如下。
- 扫描过程 2. bean创建过程
- 容器扩展
- AOP源码分析
- 事务源码分析
- Spring JDBC源码分析
- Spring常用设计模式
Bean二次收集
上一节说完了bean的收集过程,但那只是Spring的第一次收集,还有第二次,这个阶段收集必须实例化一些Bean才能完成,这个过程也是留给框架扩展用的,比如可能见过这样的注解@EnableXXXX,这中注解的背后往往都会向容器添加新的Bean,所以我们必须要了解。
看下AnnotationConfigApplicationContext的构造方法,scan我们不再需要说了,重要的是refresh,此方法是核心,很复杂。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
refresh下有很多方法,如下。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
/**
* 不需要看
*/
prepareRefresh();
/**
* 获取在本类的构造方法执行阶段实例化的DefaultListableBeanFactory,所有阶段都围绕这他
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 向ConfigurableListableBeanFactory中添加一些其他辅助类,如后处理器
*/
prepareBeanFactory(beanFactory);
try {
/**
* 这个方法用来扩展,这个过程没有子类重写他,不需要看
*/
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process")
/**
* 这里也实现了Bean的收集,主要会执行ConfigurationClassPostProcessor
* 这里是个循环收集过程
*/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 收集所有BeanPostProcessors
*/
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
//实例化剩余的Bean
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
我们从第一个有用的方法开始看,也就是invokeBeanFactoryPostProcessors(),这个方法非常重要,他会调用所有实现了BeanDefinitionRegistryPostProcessor接口的类的postProcessBeanDefinitionRegistry()方法,其中最核心的一个实现类是ConfigurationClassPostProcessor,他可能会向容器添加新的bean,因为类中可能有@Import、@Bean这样的注解,那么总有一个类要负责这些注解的解析,那这个类就是他。
这个接口注释是这样描述的,"可以进行更多的bean定义",也就是说,除了在类上加入注解,还可以通过这个接口向容器添加更多的bean,比如下面这样。
@Component
public class TestA implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(TestB.class)
.getBeanDefinition();
registry.registerBeanDefinition("testBean",beanDefinition);
}
}
而ConfigurationClassPostProcessor作的主要工作就是接着收集Bean,下面来看下具体是怎么做的。
执行所有BeanDefinitionRegistryPostProcessor
从invokeBeanFactoryPostProcessors()进入直接来到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(),这里做的第一件事是从现阶段收集到的bean列表中找出实现了BeanDefinitionRegistryPostProcessor接口的bean,并且还实现了PriorityOrdered接口(用来排序),在此时,唯一一个符合这个条件的就是ConfigurationClassPostProcessor,那么会调用getBean()实例化他,实例化后调用postProcessBeanDefinitionRegistry进行新的bean收集。
收集过后,容器中可能会增加同样实现了BeanDefinitionRegistryPostProcessor接口的类,那么Spring还要判断,如果这些类中有实现Ordered(用来排序)接口的,那么做同样的事,实例化他,并调用postProcessBeanDefinitionRegistry。
那么问题来了,如果这个时候还有新的类被添加到容器中,并且还有一些类是实现了BeanDefinitionRegistryPostProcessor接口,那怎么办?
依次收集呗,所以这里Spring通过一个while开始不停的套娃收集,这里的思路是,只要进入循环后,下一次的条件就是false,然后从现有的bean中重复上面的操作,如果发现某个bean没有被处理过,那么把下一次循环条件设置为true,然后再排序,在收集。
boolean reiterate = true;
while (reiterate) {
reiterate = false;
/**
* 再次获取实现了BeanDefinitionRegistryPostProcessor接口的类,并且实例化
* 这里也是个循环调用,直到所有bean中都收集完成了
*/
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);
//调用postProcessBeanDefinitionRegistry进行新的bean收集。
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
收集过后,会获取所有实现了BeanFactoryPostProcessor接口的类,会按照实现了PriorityOrdered、Ordered接口的优先级,依次调用他们的postProcessBeanFactory方法,这个方法位于BeanFactoryPostProcessor接口下,而BeanDefinitionRegistryPostProcessor又继承他。
这个方法作者是这样描述的,方法被调用时,所有bean定义都已加载,但没有被实例化,我们可以修改bean的属性,同样也可以增加新的bean,比如下面这样。
@Component
public class TestA implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(TestB.class)
.getBeanDefinition();
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition("testBean",beanDefinition);
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
}
}
参数ConfigurableListableBeanFactory唯一的实现类是DefaultListableBeanFactory,拿到他后,我们可以为所欲为,因为DefaultListableBeanFactory是一个核心类,同样也可以注册Bean。
ConfigurationClassPostProcessor
上面说到了会调用ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry,这里才是重头戏。
代码很长,就不帖了。
收集可能存在新Bean的类
首先会遍历现阶段容器中所有bean,检测这个bean类上是否标有Configuration、Component、ComponentScan、Import、ImportResource注解,标有的话,把这个bean放入一个集合中,如果没有的话,还会检测类中方法上是不是标有@Bean注解,有的话,同样放到这个集合中。
还有个知识点是如果标有Configuration注解,并且proxyBeanMethods是true,那么未来会进行增强,也就是需要进行动态代理。
如果这样写,那么最终实例化的就是原始类,但如果proxyBeanMethods是true,那么最终类会由CGLIB代理一下,打印他的话是这个样子TestC$$EnhancerBySpringCGLIB$$8d32c824@6c2d4cc6
@Configuration(proxyBeanMethods = false)
public class TestC {
}
此刻Spring已经挑出来需要进一步处理的类了,下一步就是挨个解析了,这部分由ConfigurationClassParser解析,从名字就可以看出,叫"配置类解析"
另外这个过程是个递归过程。
处理内部类
首先会判断是不是标有Component注解,当然他的"子注解"也一样,如果标有的话,会先处理他的内部类,如果内部类上同样标有@Component或者他的"子注解",那么这个类最终也会被Spring收录到容器,同样内部类中还有内部类,这种套娃的形式,Spring也考虑到了,会通过递归处理。
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass, filter);
}
收集属性
接着会判断有没有PropertySources注解,有的话封装成PropertySource添加到上下文的environment中,PropertySource就保存着如application.properties文件中的值,最后用于依赖注入。
这里还有一个知识点很重要,environment是在AnnotationConfigApplicationContext中创建的,那么这个变量是如何传递到ConfigurationClassPostProcessor中的呢?这就涉及到Aware接口了,放到后面说。
扫描新路径
接着会处理ComponentScans、ComponentScan注解,Spring拿到里面的值后,会重新使用上一章的方法,进如doScan进行扫描,扫描后会把扫描到的新Bean在走一遍这些流程。
处理Import
接着会处理@Import注解,这部分还是比较多的,因为@Import中的class可能分为以下三种情况。
- 实现了ImportSelector
- 实现了ImportBeanDefinitionRegistrar
- 独立类
简而言之这三种都可以收集新的bean,如果是第三种的话,那么新的bean名称就是他的完整路径,比如com.xxx.TestA,同样这个过程也是个递归收集过程,第二种情况会暂时先实例化后放入到一个集合中,并不会调用其中任何方法,将来才会调用,第一种和第三种暂时也不会放入到容器,而是先放入到一个集合中。
如果在TestA上标有@Import(TestB.class),在TestB上又@Import(TestA.class),这时候会发生死循环,那么Spring肯定也知道,他是通过ImportStack来完成的,比如处理TestA的时候,把TestA放进这个栈,如果在未来还要处理TestA,由于栈中已经存在了,就会抛出异常。
获取带有@Bean注解的方法
下面还要收集这个类中带有@Bean注解的方法,最终会把他封装为BeanMethod对象,添加到集合中,将来会调用这个方法,并把这个返回值放入到容器中。
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
收集接口中的default方法
这里就更牛逼了,如果这个类实现了某个接口,并且这个接口中有标有@Bean注解的的default方法,那么Spring还是要收集,并且这也是个递归过程,也就是接口继承接口的时候,会一头钻到底。
@Bean
default public TestB print() {
return new TestB();
}
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
//获取这个类所有的接口
for (SourceClass ifc : sourceClass.getInterfaces()) {
//提取有被@Bean标有的default方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (MethodMetadata methodMetadata : beanMethods) {
if (!methodMetadata.isAbstract()) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
//递归重新获取这个接口中所有被@Bean标有的default方法
processInterfaces(configClass, ifc);
}
}
处理父类
当本类处理完后,可能他的父类中同样有上面这些需求,Spring也要处理。但这不是递归过程,是个while过程,doProcessConfigurationClass就是上面说的所有过程,返回值是他的父类,没有的话会返回null。
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
到这里这个过程就结束了,开始下一个过程
向容器添加新的bean
到这里,配置类已经解析完成了,类中所有标有@Bean的方法还有其他信息都已经提取好后封装成了ConfigurationClass,下一步就是读取这些信息,把能放进容器的都放进容器。
也就是下面这段,见名知意,加载BeanDefinitions从ConfigurationClass,这里注意有s,表明一个配置类中可能有很多个BeanDefinition准备要添加到容器。
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
/**
* 判断是否跳过
*/
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
/**
* 判断这个类是不是被@Import导入的,
* 如果是,那么会把他封装成BeanDefinitionHolder,添加到容器
*/
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
/**
* 遍历这个类所有加了@Bean注解的方法
*/
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
/**
* 调用ImportBeanDefinitionRegistrar
*/
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
这里其实没有什么难的,逻辑比较多的还是在方法上收集信息的时候,因为@Bean注解上有initMethod、destroyMethod很多信息,还要提取Scope注解,判断是不是需要代理,但是总之,这些工作都是从各个地方收集信息并且封装为BeanDefinition,只是各个BeanDefinition的实现类可能不同。
在这里看下最后一行调用,上面我们说过,@Import的class如果实现了ImportBeanDefinitionRegistrar接口,那么暂时会把他实例化后放入集合,未来会调用,那么这里就是。
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((importBeanDefinitionRegistrar, annotationMetadata) -> {
importBeanDefinitionRegistrar.registerBeanDefinitions(annotationMetadata, this.registry, this.importBeanNameGenerator);
});
}
ImportBeanDefinitionRegistrar也用来收集新的Bean
BeanPostProcessor
下面就是收集所有实现了BeanPostProcessor接口的类,这个接口很重要,知道钩子函数的可能对他更好理解一点,他就类似与钩子,本来程序是按照正常的轨道执行的,但是你突然在中间增加了一个函数,这个函数接收一个输入,也有返回值,这个返回值会传递给原本的下一个函数。
比如本来有A、C两个函数,A处理的结果会传递给C,但是突然在其中增加了函数B,函数的执行顺序变成了A->B->C,并且B也有输入和输出,A把处理的结果传递给了B,B在其中可以修改A的结果,最后传递给C,C此时可能还不知道数据已经被修改了。
而这就是BeanPostProcessor的作用,在里面充当了B的角色。
在refresh()下面registerBeanPostProcessors()方法就是收集所有实现了BeanPostProcessor接口的类,也就是收集所有钩子,未来在创建对象前后会调用。
下面这段代码就是在所有bean中获取实现了BeanPostProcessor接口的类,具体是怎么获取的,本章就不看了。
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
finishBeanFactoryInitialization
这基本上是最后一步了,这里面会调用下面这段,注释的意思是实例化剩余的非懒加载的bean,为什么说剩余呢?因为在前面已经有一部分逻辑需要已经实例化过了,比如这个Bean实现了一个Spring必须要用的接口,在前面实例化了,懒加载的bean指的是当需要的时候才实例化。
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
而上面代码中的逻辑是遍历所有Bean名称,判断这个Bean是否有实例化的资格,比如懒加载的Bean在这里是没有资格的,有的话调用getBean()实例化。
getBean
这个过程是非常复杂的,主要复杂的是解决依赖问题,还有构造方法的问题,最简单的是无参构造,如果有参数,那就麻烦了,Spring要看看能不能在现有的bean中找到符合这个构造方法参数的bean,在加上可能还要处理@Value。
我们直接从AbstractBeanFactory#doGetBean开始,这里是获取bean的开始。
第一步是转换名称,因为如果使用@Bean,那么这个bean可能会有多个别名,比如name1,name2,这些名称中第一个会作为最终的bean名称放在beanDefinitionMap中,还有一个aliasMap存放这别名映射,比如name2->name1,当获取name2的时候,会最转换成name1。
接下来这一步是关键,是解决依赖问题核心。
//如果已经有实例了
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
/**
* 如果Bean实现了FactoryBean,在这里可能返回他的getObject方法
*/
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
详细看下getSingleton()
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
/**
* 如果有完整的Bean对象,则直接返回
* 所有对象创建后,并且完成属性填充,都会放入到这里
*/
Object singletonObject = this.singletonObjects.get(beanName);
/**
* 如果没有这个对象,判断这个对象是不是在循环依赖的创建过程中。
*/
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
/**
* 一般情况都为Null
*/
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
/**
* 获取这个对象提早曝光后的结果
*/
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
/**
* 获取这个对象提早曝光后的ObjectFactory
* 如果在这里存在这个对象工厂,则从工厂获取对象,这是前面提早曝光的结果
*/
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//实例对象
singletonObject = singletonFactory.getObject();
//放入到earlySingletonObjects,可能以后还会用到
this.earlySingletonObjects.put(beanName, singletonObject);
//删除对象工厂,他的对象都有了,就不需要了
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
无依赖创建过程
下面说一下无依赖创建过程,现在假如要获取testA,那么第一次从缓存中获取肯定是没有的,那么接下来会判断在不在依赖循环中,这时候肯定是不在的。
接下来会判断这个bean有没有依赖,这个依赖指的是@DependsOn,如果有的话,会先实例化他的依赖,实例化依赖的过程同样是调用getBean(),和当前流程一样。
然后判断是不是单例,一般情况下是的。
然后进入到这里,getSingleton第二个参数是ObjectFactory,用于创建对象。
sharedInstance = getSingleton(beanName, () -> {
try {
/**
* 在getSingleton中会调用到这里
*/
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
getSingleton里面做了三件重要的事,第一件事是把当前正在创建的bean放入一个集合中,用于循环依赖检测,第二件事是调用传递过来的ObjectFactory的getObject()获取对象,第三件事是把创建好的对象放入到缓存,以后可以直接从缓存中取。
所以我们来看最重要的第二件事,进入createBean()方法。
createBean()中Spring并没有自己先去实例化这个对象,而是交给扩展接口。
/**
* 试图实例化后初始化,如果扩展接口没有实例化,那么Spring自己实例化,否则直接返回
*/
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
这个接口叫InstantiationAwareBeanPostProcessor,我们可以自己实现,当创建对象时,Spring会先交给他,如果他返回null,那么Spring只能自己实例化了,否则调用所有实现了BeanPostProcessor接口的postProcessAfterInitialization()方法后进行返回,这也是Spring留给我们扩展用的。
现在假如没有任何类愿意实例化这个bean,那么Spring只能自己处理,进入到doCreateBean()中。
/**
* 自己实例化
*/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
doCreateBean()的第一句就是实例化对象。
/**
* 创建对象,初始化对象
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
这一步就比较麻烦了,因为Spring要推断很多类型。但是现在只要知道这句执行后,我们的对象就创建成功了,但这也可能是个代理对象,Spring也没有在对象创建好后去代理,而是事先替换了要实例化的类,比如原本的类是com.Test,但是此刻通过反射实例化的是com.Test$$EnhancerBySpringCGLIB$$dded467a
,这是在收集BeanDefinition过程中判断了如果这个类需要代理,那么就为先为他生成一个代理类。
创建完成后还会调用所有MergedBeanDefinitionPostProcessor接口。
接着会执行下面这句,第二个参数同样是ObjectFactory,这个叫提早曝光,对于无任何依赖的类来说,用不到,但是对依赖循环的时候有巨大用,我们把这里先称为“关键点1”
/**
* 某个对象创建后,将他加入singletonFactories中,此时这个对象没有任何属性被填充,
* 到了其他对象依赖这个对象的时候,从getEarlyBeanReference返回
*/
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
接下来是填充属性,也叫依赖注入,如果没有任何属性,也没什么用,后面单独说这个方法。
/**
* 填充属性
*/
populateBean(beanName, mbd, instanceWrapper);
/**
* 调用对象的BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
最后是初始化bean。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
/**
* 调用对象的BeanNameAware、BeanClassLoaderAware、BeanFactoryAware(如果实现了的话)
*/
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
/**
* 调用BeanPostProcessors的前置处理器尝试修改
*/
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
/**
* 调用bean的init方法
*/
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
/**
* 调用BeanPostProcessors的后置处理器尝试修改
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这部分就结束了。
有依赖情况
下面来说有依赖情况,有依赖做的事就是属性填充,所以我们要了解populateBean()方法,populateBean()中会调用所有实现了InstantiationAwareBeanPostProcessor接口的postProcessProperties()方法,而具体完成属性填充的实现类是AutowiredAnnotationBeanPostProcessor,其他实现类会填充标有其他注解的属性,
进入AutowiredAnnotationBeanPostProcessor#postProcessProperties(),首先会调用findAutowiringMetadata找到需要自动注入的字段,这里主要是找Autowired、Value,找到之后放在InjectionMetadata对象中,此对象中有个集合,保存着InjectedElement,他表示单个需要被注入的字段信息。
InjectedElement的一个实现类也位于AutowiredAnnotationBeanPostProcessor下,叫AutowiredFieldElement,当调用他的inject方法表示对这个字段进行注入。
而在内部判断了如果这个字段是Class类型,那么直接调用开头的getBean()尝试从容器中获取,比较简单。
同样对于注入@Value的逻辑也在这里,只不过比较复杂,后续会单独分析。
依赖循环情况
现在假设TestA中需要注入TestB,TestB中需要注入TestA。
从getBean("testA")开始,同样会到达populateBean()方法填充testB,然后返回来再创建TestB,TestB创建成功后,同样会执行populateBean()填充TestA。
那么这时候不可能在创建testA,这样就成了死循环了。
还记得我们说的"关键点1"吗,当对象创建成功后,会在singletonFactories中保存一个对象工厂ObjectFactory,调用这个ObjectFactory的getObject()就可以在任何地方获取刚创建的对象。
这样当TestB在获取TestA的时候,发现singletonFactories中有个工厂可以获取到TestA,那么就直接调用他,最后会进入下面这个方法
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = getBeanPostProcessorCache().smartInstantiationAware;
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
他还是要调用所有实现了SmartInstantiationAwareBeanPostProcessor接口类的getEarlyBeanReference()尝试做最后的修改,目前我只发现他在AOP时候使用到了,所以本章暂时不考虑他。
那么这个方法返回的只是传递过来的对象。
这样依赖循环就解决了。
FactoryBean
我们回到最初,还有下面这一段需要解析。
/**
* 如果Bean实现了FactoryBean,在这里可能返回他的getObject方法
*/
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
这种情况是当bean实现了FactoryBean接口的时候,getBean()会返回这个接口的getObject()的值。