doGetBean源码分析
2022-01-12 17:37:29 4 举报
AI智能生成
doGetBean源码分析
作者其他创作
大纲/内容
1. 转化bean名称
String beanName = transformedBeanName(name);
String beanName = transformedBeanName(name);
1. 如果是工厂bean则去除bean工厂前缀
2. 判断 ./1 处理后的名称是否为别名,是的话查找出真实bean名称进行返回
2. 通过 ./1 中转换的bean名称先尝试从单例缓存中取值
Object sharedInstance = getSingleton(beanName);
Object sharedInstance = getSingleton(beanName);
1. 通过bean名称从singletonObjects中取值
Object singletonObject = this.singletonObjects.get(beanName);
Object singletonObject = this.singletonObjects.get(beanName);
如果单例bean存在singletonObjects缓存中,说明该bean已经构造好并初始化化完成了
因为在#4.7.1.6.1节点才会往singletonObjects中添加初始化完成的bean
因为在#4.7.1.6.1节点才会往singletonObjects中添加初始化完成的bean
2. 如果 ./1 中有取到值则返该值,没取到且bean但bean正在创建则继续 ./3 逻辑。否则返回null
正在创建的bean会存放在 singletonsCurrentlyInCreation 中
正在创建的bean会存放在 singletonsCurrentlyInCreation 中
如果bean正在创建,说明这个bean正处于循环依赖状态。比如A->B且B->A
在加载A前会将A添加到singletonsCurrentlyInCreation(#4.7.1.3)
接着开始构造A(#4.7.1.4.5.3),构造完后进行注入依赖(#4.7.1.4.5.7)发现依赖了B,则会去加载B
在完成B的构造后注入依赖的时候发现又依赖了A则又会去加载A
这个时候就会在这一步出现当前bean A正在创建的情形,因为如果B没有依赖A的话在B初始化完成后
A会完成剩下的依赖注入及初始化操作然后从singletonsCurrentlyInCreation中移除(#4.7.1.5)
在加载A前会将A添加到singletonsCurrentlyInCreation(#4.7.1.3)
接着开始构造A(#4.7.1.4.5.3),构造完后进行注入依赖(#4.7.1.4.5.7)发现依赖了B,则会去加载B
在完成B的构造后注入依赖的时候发现又依赖了A则又会去加载A
这个时候就会在这一步出现当前bean A正在创建的情形,因为如果B没有依赖A的话在B初始化完成后
A会完成剩下的依赖注入及初始化操作然后从singletonsCurrentlyInCreation中移除(#4.7.1.5)
3. 从earlySingletonObjects中取值,有取到则返回该值,没取到但allowEarlyReference为true则继续 ./4 逻辑。否则返回null
singletonObject = this.earlySingletonObjects.get(beanName);
singletonObject = this.earlySingletonObjects.get(beanName);
进入到这个地方的时候一开始earlySingletonObjects中应该是没有当前bean的
因为要在 ../5 中才会添加到earlySingletonObjects
因为要在 ../5 中才会添加到earlySingletonObjects
4. 通过bean名称从singletonFactories中去获取ObjectFactory,如果没有取到则返回null,有则继续 ./5 逻辑
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
这个地方的singletonFactory是在(#4.7.1.4.5.5)中进行设置进去的,是解决循环依赖的关键
在B加载A的时候进入到这个地方能取到singletonFactory的值,然后在 ../5 中调用 singletonFactory.getObject()
返回未初始化完成的bean A 设置到B的依赖中,不会继续去创建A,这样就解决了循环依赖
在B加载A的时候进入到这个地方能取到singletonFactory的值,然后在 ../5 中调用 singletonFactory.getObject()
返回未初始化完成的bean A 设置到B的依赖中,不会继续去创建A,这样就解决了循环依赖
5. 如果上一步得到的singletonFactory不为null,则执行右侧操作
singletonFactory
singletonFactory
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
3. 如果 ./2 中sharedInstance有取到值且args参数为空,则调用getObjectForBeanInstance方法取出实例,在 ./6 处返回,否则进入 ./4 的处理逻辑
因为sharedInstance可能是个工厂bean,所以要做这个操作。需要注意的是传入的name是未经过 ./1 转换的name
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
因为sharedInstance可能是个工厂bean,所以要做这个操作。需要注意的是传入的name是未经过 ./1 转换的name
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
1. 如果name是以工厂bean前缀开头,先排除掉如右两种情况
bean实例是NullBean则直接返回bean实例
bean实例不是工厂bean则抛出BeanIsNotAFactoryException异常
2. bean实例不是个工厂bean或是个工厂bean且name还是以工厂bean前缀开头(说明是取bean工厂实例本身)则直接返回bean实例
3. 能走到这里则说明bean实例是个工厂bean,而且不是以工厂bean前缀开头说明不是想取工厂bean实例本身
则通过工厂bean实例获取getObject方法返回值进行返回
则通过工厂bean实例获取getObject方法返回值进行返回
4. 如果 ./3 中条件不满足,则执行该beanName实例化
1. 如果该beanName是正在创建的原型bean,则抛出BeanCurrentlyInCreationException异常
原型bean是不允许循环引用的,因为每次都需要创建新的实例,构造完后不能先放入缓存中
原型bean是不允许循环引用的,因为每次都需要创建新的实例,构造完后不能先放入缓存中
2. 如果存在父BeanFactory容器,且该beanName已经被父容器实例化过了则直接返回实例化好了的bean实例
3. 如果typeCheckOnly值为false说明是创建bean,而不是类型检查
markBeanAsCreated(beanName);
markBeanAsCreated(beanName);
1. 移除beanName在mergedBeanDefinitions集合中存在的值,让 ../4 中重写去执行合并操作
以防止上一次合并后bean定义数据发生了变化的情况
以防止上一次合并后bean定义数据发生了变化的情况
2. 将beanName添加到 Set<String> alreadyCreated集合中
4. 如果beanName对应的bean定义不是RootBeanDefinition类型则会合并为RootBeanDefinition类型
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
5. 检查 mdb 是不是抽象类,是抽象类则抛出BeanIsAbstractException异常
checkMergedBeanDefinition(mbd, beanName, args);
checkMergedBeanDefinition(mbd, beanName, args);
6. 如果 mdb 有@dependsOn注解依赖其他bean,则先处理依赖
1. 取出 mdb @dependsOn注解中依赖的bean 名称数组
String[] dependsOn = mbd.getDependsOn();
String[] dependsOn = mbd.getDependsOn();
2. 如果上一步取出的dependsOn数组不为空则循环处理依赖bean
3. 通过依赖缓存(下一步会添加)判断是否有循环依赖的情况,有则抛出BeanCreationException异常
4. 注册依赖bean名称到依赖缓存中,上一步就是通过缓存判断是否有循环依赖的情况
registerDependentBean(dep, beanName);
registerDependentBean(dep, beanName);
1. 取出依赖bean的真实名称,防止依赖bean名称是个别名的情况
需要注意的是此处的beanName是 ../4 中传入的dep参数噢
String canonicalName = canonicalName(beanName);
需要注意的是此处的beanName是 ../4 中传入的dep参数噢
String canonicalName = canonicalName(beanName);
2. 如果canonicalName在dependentBeanMap缓存中不存在则实例化一个LinkedHashSet
然后将dependentBeanName( ../4 中传入的beanName) 添加到set中
最后以canonicalName为key,set为值添加到dependentBeanMap缓存中缓存中
如果canonicalName之前就存在于缓存中,则把dependentBeanName 添加到对应的set中
然后将dependentBeanName( ../4 中传入的beanName) 添加到set中
最后以canonicalName为key,set为值添加到dependentBeanMap缓存中缓存中
如果canonicalName之前就存在于缓存中,则把dependentBeanName 添加到对应的set中
3. 和上一步相似,只不过是以dependentBeanName作为key,canonicalName为set值添加到dependenciesForBeanMap缓存中
5. 通过依赖bean 名称执行getBean操作
getBean(dep);
getBean(dep);
7. 如果mdb 是单例bean,执行单例bean实例化逻辑,否则进入下一步
1. 调用getSingleton(String beanName, ObjectFactory<?> singletonFactory),singletonFactory为lambda表达式
表达式里面会调用createBean(String beanName, RootBeanDefinition mbd, Object[] args)
如createBean发生BeansException,在catch中会执行destroySingleton(beanName)移除掉已添加到缓存中的东西
sharedInstance = getSingleton(beanName, ()->{ return createBean(beanName, mbd, args); });
表达式里面会调用createBean(String beanName, RootBeanDefinition mbd, Object[] args)
如createBean发生BeansException,在catch中会执行destroySingleton(beanName)移除掉已添加到缓存中的东西
sharedInstance = getSingleton(beanName, ()->{ return createBean(beanName, mbd, args); });
1. 先尝试从singletonObjects缓存中获取,如果缓存中有值则直接返回,不进行后面的操作
Object singletonObject = this.singletonObjects.get(beanName);
Object singletonObject = this.singletonObjects.get(beanName);
2. 如果单例工厂正在在销毁,则抛出BeanCreationNotAllowedException异常
3. 创建单例bean之前的回调操作,主要操作是将beanName添加到singletonsCurrentlyInCreation缓存中
beforeSingletonCreation(beanName);
beforeSingletonCreation(beanName);
4. 执行 ../1 中传入的 createBean 操作
singletonObject = singletonFactory.getObject();
singletonObject = singletonFactory.getObject();
1. 将 mbd(#4.4中合并的RootBeanDefinition) 放入一个mbdToUse 变量中
RootBeanDefinition mbdToUse = mbd;
RootBeanDefinition mbdToUse = mbd;
2. 如果mbd中的beanClass还未加载,则将beanClass加载后重新对mbdToUse赋值
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
3. 处理lookup-method 和 replace-method
mbdToUse.prepareMethodOverrides();
mbdToUse.prepareMethodOverrides();
4. 执行实例化前的后置处理操作,如果能取到值,则直接返回
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
1. 循环执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法
如果某个处理器有返回值则停止循环,将该值返回供下一步操作,若都没值返回则返回null
如果某个处理器有返回值则停止循环,将该值返回供下一步操作,若都没值返回则返回null
2. 上一步如果有值返回,则循环调用BeanPostProcessor#postProcessAfterInitialization方法
如果某个处理器返回null,则停止循环,返回当前值给 ../4
如果某个处理器返回null,则停止循环,返回当前值给 ../4
5. 执行创建bean逻辑
doCreateBean(beanName, mbdToUse, args);
doCreateBean(beanName, mbdToUse, args);
1. 定义一个BeanWrapper对象用来包装创建的bean对象
BeanWrapper instanceWrapper = null;
BeanWrapper instanceWrapper = null;
2. 如果是创建单例bean则先尝试通过beanName去factoryBeanInstanceCache缓存中取值赋值给instanceWrapper
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
3. 如果 ./2 中没取到值则创建wrapper对象赋值给instanceWrapper,真正的bean实例化在这一步
instanceWrapper = createBeanInstance(beanName, mbd, args);
instanceWrapper = createBeanInstance(beanName, mbd, args);
1. 取出bean定义中的 beanClass,如果beanClass还没有加载会先加载class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
Class<?> beanClass = resolveBeanClass(mbd, beanName);
2. 如果beanClass不为null且不是public访问级别且nonPublicAccessAllowed为false
则抛出BeanCreationException异常
则抛出BeanCreationException异常
3. 如果存在supplier回调,则通过给定的回调方法初始化策略实例化返回
在使用GenericApplicationContext#registerBean方法注册bean时可以使用该方式
return obtainFromSupplier(instanceSupplier, beanName);
在使用GenericApplicationContext#registerBean方法注册bean时可以使用该方式
return obtainFromSupplier(instanceSupplier, beanName);
4. 如果存在工厂方法,则通过工厂方法初始化返回
在方法上使用@Bean注解定义bean会使用该方式
return instantiateUsingFactoryMethod(beanName, mbd, args);
在方法上使用@Bean注解定义bean会使用该方式
return instantiateUsingFactoryMethod(beanName, mbd, args);
5. 如果args为null且mdb.resolvedConstructorOrFactoryMethod不为null
则说明之前有解析过可使用缓存的构造器进行构建,不需要进入下一步的构造器选择
则说明之前有解析过可使用缓存的构造器进行构建,不需要进入下一步的构造器选择
6. 根据参数确定候选构造器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
会循环调用SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors方法
如果某个处理器有返回构造器则停止循环,将值放回给 ../6
此处主要逻辑由AutowiredAnnotationBeanPostProcessor处理器处理
如果某个处理器有返回构造器则停止循环,将值放回给 ../6
此处主要逻辑由AutowiredAnnotationBeanPostProcessor处理器处理
7. 如果上一步有根据参数解析到匹配的构造器或者args参数不为null
或mdb.constructorArgumentValues不为空或mdb.autowireMode为自动注入模式
则使用自动注入构造方式进行实例化bean
return autowireConstructor(beanName, mbd, ctors, args);
或mdb.constructorArgumentValues不为空或mdb.autowireMode为自动注入模式
则使用自动注入构造方式进行实例化bean
return autowireConstructor(beanName, mbd, ctors, args);
这一步中如果出现构造器注入参数循环依赖会抛出UnsatisfiedDependencyException
构造器是不允许循环依赖的
构造器是不允许循环依赖的
8. 如果mdb中有设置默认的首选构造器
ctors = mbd.getPreferredConstructors();
ctors = mbd.getPreferredConstructors();
9. 如果上一步判断不符合自动注入构造方式的条件,则使用默认的无参构造实例化bean
return instantiateBean(beanName, mbd);
return instantiateBean(beanName, mbd);
4. 循环执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法
类型的后置处理器,主要是用来缓存一些meta信息供后续属性填充用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
类型的后置处理器,主要是用来缓存一些meta信息供后续属性填充用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
此处CommonAnnotationBeanPostProcessor会查找bean中标注了右侧注解
的属性/方法放入injectionMetadataCache中,key为bean名称
的属性/方法放入injectionMetadataCache中,key为bean名称
查找标注了@Resource注解的属性或方法,在 ../../7.5 中会进行依赖注入
查找标注了@PostConstruct注解的方法,在 ../../8.2 中会执行该方法
会将该方法名称放入bean定义的externallyManagedInitMethods列表中
会将该方法名称放入bean定义的externallyManagedInitMethods列表中
查找标注了@PreDestroy注解的方法
会将该方法名称放入bean定义的externallyManagedDestroyMethods列表中
会将该方法名称放入bean定义的externallyManagedDestroyMethods列表中
此处AutowiredAnnotationBeanPostProcessor会获取bean中标有@Autowired注解
的属性/方法放入injectionMetadataCache中供 ../7.5 进行使用,key为bean名称
的属性/方法放入injectionMetadataCache中供 ../7.5 进行使用,key为bean名称
5. 如果是单例bean且允许循环引用且当前bean正在创建中,则执行添加单例工厂的操作
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
1. 往singletonFactories中添加beanName的单例工厂
需要注意的是此处添加单例bean工厂一个lambda表达式,在存在循环依赖时#2.5处会调用工厂的getObject
就会执行该lambda表达式,该表达式中会循环SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
方法,如果该bean的某个方法满足代理条件则就会对这个该bean进行代理,这样依赖该对象就是依赖的代理类了
就会执行该lambda表达式,该表达式中会循环SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
方法,如果该bean的某个方法满足代理条件则就会对这个该bean进行代理,这样依赖该对象就是依赖的代理类了
详情代码可查看aop(Aspectj)源码分析#4.2
2. 移除earlySingletonObjects中的beanName
3. 往registeredSingletons中添加beanName
6. 定义一个exposedObject对象用于存在暴露的bean实例,后面可能会代理类覆盖
而instanceWrapper中依旧保存原始bean(存在earlySingletonObjects中的是原始bean)
Object exposedObject = bean;
而instanceWrapper中依旧保存原始bean(存在earlySingletonObjects中的是原始bean)
Object exposedObject = bean;
7. 对bean属性依赖进行填充,属性又依赖其他bean,则递归初始化其他bean
populateBean(beanName, mbd, instanceWrapper);
populateBean(beanName, mbd, instanceWrapper);
1. 对传入BeanWrapper做非空判断,如果为null则直接return
如果为空且有propertyValues值则抛出BeanCreationException异常
如果为空且有propertyValues值则抛出BeanCreationException异常
2. 循环执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
如果其中某个控制器方法返回false,则会跳出循环且return方法不进行后面的操作了
此处也是在注入前最后一次能修改bean属性的时机,因为后面就要开始注入属性依赖了
如果其中某个控制器方法返回false,则会跳出循环且return方法不进行后面的操作了
此处也是在注入前最后一次能修改bean属性的时机,因为后面就要开始注入属性依赖了
3. 取出mbd中的propertyValues值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
4. 判断依赖注入的方式,默认是0手动依赖(比如手动通过@Autowired注解标注属性的)
AUTOWIRE_BY_NAME表示通过属性名进行自动依赖,AUTOWIRE_BY_TYPE表示根据属性类型进行自动依赖
AUTOWIRE_BY_NAME表示通过属性名进行自动依赖,AUTOWIRE_BY_TYPE表示根据属性类型进行自动依赖
5. 循环执行InstantiationAwareBeanPostProcessor#postProcessProperties方法
如果某个控制器返回null则return方法不进行后面的操作了
此处通过右侧两个控制器实现了bean属性的依赖注入
如果某个控制器返回null则return方法不进行后面的操作了
此处通过右侧两个控制器实现了bean属性的依赖注入
1. CommonAnnotationBeanPostProcessor
对java中依赖注解进行处理,如:@Resource
对java中依赖注解进行处理,如:@Resource
2. AutowiredAnnotationBeanPostProcessor(会进入AutowiredAnnotationBeanPostProcessor#inject方法进行依赖注入)
对spring中的依赖注解进行处理:如:@Autowire
对@Value 标注的属性进行赋值(详细使用见备注)
对spring中的依赖注解进行处理:如:@Autowire
对@Value 标注的属性进行赋值(详细使用见备注)
8. 对bean进行初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
exposedObject = initializeBean(beanName, exposedObject, mbd);
1. 如果实现了BeanNameAware或BeanClassLoaderAware或BeanFactoryAware接口则进行织入操作
invokeAwareMethods(beanName, bean);
invokeAwareMethods(beanName, bean);
2. 循环执行BeanPostProcessor#postProcessBeforeInitialization方法
如果某个控制器返回null则return上一个处理器返回的值,不执行后面的处理器了
wrappedBean =applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
如果某个控制器返回null则return上一个处理器返回的值,不执行后面的处理器了
wrappedBean =applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
如果bean中有标注@PostConstruct注解的方法,CommonAnnotationBeanPostProcessor处理器将执通过反射执行该方法
如果bean实现了ImportAware接口则ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor会在此时调用setImportMetadata方法
ImportAware使用示例
如果bean实现右侧Aware接口,则ApplicationContextAwareProcessor处理器将在这一步进行织入操作
ApplicationContextAware
MessageSourceAware
ApplicationEventPublisherAware
ResourceLoaderAware
EmbeddedValueResolverAware
EnvironmentAware
3. 执行afterPropertiesSet和initMethod方法
invokeInitMethods(beanName, wrappedBean, mbd);
invokeInitMethods(beanName, wrappedBean, mbd);
1. 如果该bean实现了InitializingBean接口,且没有被@PostConstruct注解标注且方法名为afterPropertiesSet的方法
则执行InitializingBean#afterPropertiesSet方法
则执行InitializingBean#afterPropertiesSet方法
2. 如果该bean定义中有设置initMethodName值,且满足右侧两个条件
则通过反射执行该initMethodName方法
则通过反射执行该initMethodName方法
1. 该bean没有实现InitializingBean接口或实现了该接口但initMethodName值不为afterPropertiesSet
2. 没有被@PostConstruct注解标注且方法名为initMethodName的方法
4. 循环执行BeanPostProcessor#postProcessAfterInitialization方法
如果某个控制器返回null则return上一个处理器返回的值,不执行后面的处理器了
aop代理通常就是在这个地方进行的,详情可查看aop(Aspectj)源码分析#4.3
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
如果某个控制器返回null则return上一个处理器返回的值,不执行后面的处理器了
aop代理通常就是在这个地方进行的,详情可查看aop(Aspectj)源码分析#4.3
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
如果bean实现了ApplicationListener接口ApplicationListenerDetector将在这一步将该监听器添加到ApplicationContext#applicationEventMulticaster中
9. 处理循环依赖有时原始bean和暴露bean不一致的情况
1. getSingleton方法获取earlySingletonReference(如果循环依赖的话是有值的)
Object earlySingletonReference = getSingleton(beanName, false);
Object earlySingletonReference = getSingleton(beanName, false);
2. 暴露的exposedObject和原始bean相同则earlySingletonReference赋值给exposedObject
exposedObject = earlySingletonReference;
exposedObject = earlySingletonReference;
当前bean中使用了@Async注解会可能会出现不相等的情况,因为@Async注解是在initializeBean的时候(#4.7.1.4.5.8)
进行代理bean的,而去加载依赖是在initializeBean(#4.7.1.4.5.7),比代理的时间早,所以会导致依赖的是原始bean,而暴露的是代理bean
在循环依赖时不会有这种问题,因为循环依赖时依赖的bean在4.7.1.4.5.5.1就进行了代理,所以不会有这种问题
解决方案可在依赖该bean的时候添加@Lazy注解
@Lazy实现原理:AutowiredAnnotationBeanPostProcessor#postProcessProperties方法在加载属性依赖的时候如果发现有标注@Lazy注解
则会为依赖的添加代理,在真正调用依赖的时候才会从bean容器中重新加载bean对象再通过反射调用bean对象的方法,这样就起到了延迟加载的效果
具体代理代码可查看ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy方法
进行代理bean的,而去加载依赖是在initializeBean(#4.7.1.4.5.7),比代理的时间早,所以会导致依赖的是原始bean,而暴露的是代理bean
在循环依赖时不会有这种问题,因为循环依赖时依赖的bean在4.7.1.4.5.5.1就进行了代理,所以不会有这种问题
解决方案可在依赖该bean的时候添加@Lazy注解
@Lazy实现原理:AutowiredAnnotationBeanPostProcessor#postProcessProperties方法在加载属性依赖的时候如果发现有标注@Lazy注解
则会为依赖的添加代理,在真正调用依赖的时候才会从bean容器中重新加载bean对象再通过反射调用bean对象的方法,这样就起到了延迟加载的效果
具体代理代码可查看ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy方法
3. 上一步的条件不满足且allowRawInjectionDespiteWrapping=false
且有依赖bean则进入该处理逻辑
且有依赖bean则进入该处理逻辑
4. 取出所有的依赖bean名称
5. 循环上面的依赖bean,如果有一个bean是存在alreadyCreated中(加载完毕,不会加载依赖了)
则抛出BeanCurrentlyInCreationException异常
则抛出BeanCurrentlyInCreationException异常
10. 注册bean销毁时的回调(@PreDestroy/DisposableBean/destroy-method)
5. 创建完单例bean的回调,主要操作是将beanName从singletonsCurrentlyInCreation缓存中移除
afterSingletonCreation(beanName);
afterSingletonCreation(beanName);
6. 将创建好的单例bean添加到缓存中
addSingleton(beanName, singletonObject);
addSingleton(beanName, singletonObject);
1. 将创建好的单例bean添加到singletonObjects缓存中
this.singletonObjects.put(beanName, singletonObject);
this.singletonObjects.put(beanName, singletonObject);
2. 将beanName从singletonFactories缓存中移除
this.singletonFactories.remove(beanName);
this.singletonFactories.remove(beanName);
3. 将beanName从earlySingletonObjects缓存中移除
this.earlySingletonObjects.remove(beanName);
this.earlySingletonObjects.remove(beanName);
4. 将beanName添加到registeredSingletons缓存中
this.registeredSingletons.add(beanName);
this.registeredSingletons.add(beanName);
2. 通过上一步获取的实例进行getObjectForBeanInstance,和#3中一样的操作
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
8. 如果mdb 是原型bean,执行原型bean实例化逻辑,否则进入下一步
1. 将当前正在创建的原型bean名称添加到prototypesCurrentlyInCreation中
因为是原型bean,所以prototypesCurrentlyInCreation为ThreadLocal类型
beforePrototypeCreation(beanName);
因为是原型bean,所以prototypesCurrentlyInCreation为ThreadLocal类型
beforePrototypeCreation(beanName);
1. 如果prototypesCurrentlyInCreation中没有值则直接把当前bean名称放入prototypesCurrentlyInCreation中
2. 如果prototypesCurrentlyInCreation中有值且为String则说明是在加载依赖bean
则把prototypesCurrentlyInCreation中已经存在的bean名称和正在加载的bean名称添加到一个Set集合中
然后将该Set集合放入prototypesCurrentlyInCreation中
则把prototypesCurrentlyInCreation中已经存在的bean名称和正在加载的bean名称添加到一个Set集合中
然后将该Set集合放入prototypesCurrentlyInCreation中
3. 如果不符合 ./1 和 ./2 则说明prototypesCurrentlyInCreation中已经是个Set集合了
则将当前加载的bean名称添加到Set集合中就行了
则将当前加载的bean名称添加到Set集合中就行了
2. 执行创建bean的操作,参考 #4.7.1.4
prototypeInstance = createBean(beanName, mbd, args);
prototypeInstance = createBean(beanName, mbd, args);
3. 进行 ./1 中添加到prototypesCurrentlyInCreation中的bean名称进行移除操作
afterPrototypeCreation(beanName);
afterPrototypeCreation(beanName);
4. 通过上一步获取的实例进行getObjectForBeanInstance,和#3中一样的操作
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
9. 执行mdb 是request或session作用域的bean
1. 取出当前bean定义中的scope值
String scopeName = mbd.getScope();
String scopeName = mbd.getScope();
2. 通过scopeName从BeanFactory#scope中取出Scope对象
如果没有取到则抛出IllegalStateException异常
final Scope scope = this.scopes.get(scopeName);
如果没有取到则抛出IllegalStateException异常
final Scope scope = this.scopes.get(scopeName);
在springboot内嵌初始化#2.7.4.1.3有对BeanFactory#scope进行设置
request值为RequestScope继承自AbstractRequestAttributesScope,在该抽象父类中实现了获取bean实例的get方法
session值为SessionScope继承自AbstractRequestAttributesScope,重写了父类的get方法(会先进行加锁操作然后调用父类的get方法)
request值为RequestScope继承自AbstractRequestAttributesScope,在该抽象父类中实现了获取bean实例的get方法
session值为SessionScope继承自AbstractRequestAttributesScope,重写了父类的get方法(会先进行加锁操作然后调用父类的get方法)
3. 通过上一步取出的scope#get方法获取bean实例,第二个参数为ObjectFactory
此处传入的是个lambda表达式,该表达式里面的获取bean实例逻辑和#4.8一样
Object scopedInstance = scope.get(beanName, () -> {...} );
此处传入的是个lambda表达式,该表达式里面的获取bean实例逻辑和#4.8一样
Object scopedInstance = scope.get(beanName, () -> {...} );
1. 取出当前请求的RequestAttributes
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
2. 根据作用域去不同的地方通过bean名称尝试去取bean实例,如去request或session中取
Object scopedObject = attributes.getAttribute(name, getScope());
Object scopedObject = attributes.getAttribute(name, getScope());
3. 上一步在对应的作用域中有获取到值则直接放回,没有的话则通过通过传入的ObjectFactory#getObject方法进行获取bean实例
然后通过将获取到的bean实例设置到对应的作用域中
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
然后通过将获取到的bean实例设置到对应的作用域中
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
5. 如果requiredType类型参数不为空而且从上面得到的bean实例类型与requiredType不匹配
则调用类型转换器进行转换,转换成功直接返回转换后得bean实例,转换失败抛出BeanNotOfRequiredTypeException异常
则调用类型转换器进行转换,转换成功直接返回转换后得bean实例,转换失败抛出BeanNotOfRequiredTypeException异常
6. 返回上面得到的bean实例
return (T) bean;
return (T) bean;
0 条评论
下一页