一、
Bean的实例化过程
流程图地址:
https://www.processon.com/view/link/5df87156e4b0cfc88c3c18c5
org.springframework.context.support.AbstractApplicationContext#refresh方法中
/*
* 这个方法是spring中最重要的方法,没有之一
,
所以这个方法一定要理解要具体看
* 1、bean实例化过程
* 2、ioc
* 3、注解支持
* 4、BeanPostProcessor的执行
* 5、Aop的入口
*/
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
1、
BeanDefinitionRegistryPostProcessor接口
Refresh().invokeBeanFactoryPostProcessors这个方法里面。
BeanDefinitionRegistryPostProcessor这个接口的调用分为三部:
1)调用实现了PriorityOrdered排序接口
2)调用实现了Ordered排序接口
3)没有实现接口的调用
这个接口的理解:获取BeanDefinitionRegistry对象,获取到这个对象就可以获取这个对象中注册的所有BeanDefinition对象,所以我们知道了,我们拥有这个对象就可以完成里面所有BeanDefinition对象的修改我新增操作。
@Component
public class
BeanDefinitionTest
implements
BeanDefinitionRegistryPostProcessor {
@Override
public void
postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry
)
throws
BeansException {
GenericBeanDefinition genericBeanDefinition =
new
GenericBeanDefinition();
genericBeanDefinition.setBeanClass(BeanClass.
class
);
MutablePropertyValues propertyValues = genericBeanDefinition.getPropertyValues();
propertyValues.addPropertyValue(
“username”
,
“Hnakin”
)
registry.registerBeanDefinition(
“beanClass”
,genericBeanDefinition);
ClassPathBeanDefinitionScanner scanner =
new
ClassPathBeanDefinitionScanner(registry);
//
TODO 将自定义的注解@MyService添加到ClassPathBeanDefinitionScanner
//
private final List<TypeFilter> includeFilters = new LinkedList<>();
scanner.addIncludeFilter(
new
AnnotationTypeFilter(
MyService
.
class
));
scanner.scan(
“com.chj”
);
}
2、
BeanPostProcessor的注册
Refresh().registerBeanPostProcessors这个方法里面。
org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
public static void
registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.
class
,
true
,
false
);
拿到BeanFactory中所有注册的BeanDefinition对象的名称beanName。
for
(String ppName : postProcessorNames) {
if
(beanFactory.isTypeMatch(ppName, PriorityOrdered.
class
)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.
class
);
priorityOrderedPostProcessors.add(pp);
if
(pp
instanceof
MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if
(beanFactory.isTypeMatch(ppName, Ordered.
class
)) {
orderedPostProcessorNames.add(ppName);
}
else
{
nonOrderedPostProcessorNames.add(ppName);
}
}
然后判断是否实现了PriorityOrdered排序接口,Ordered排序接口,getBean是将该ppName对应的BeanDefinition对象实例化。
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
把对应的BeanPostProcessor对象注册到BeanFactory中,BeanFactory中有一个list容器接收。
3、
getSingleton方法
代码位置: AbstractBeanFactory.doGetBean方法中
// Create bean instance.
if
(mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try
{
return createBean(beanName, mbd, args);
}
catch
(BeansException ex) {
destroySingleton(
beanName
);
throw
ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
方法里面核心要点:
beforeSingletonCreation(beanName);
protected void
beforeSingletonCreation(String beanName) {
if
(!
this
.
inCreationCheckExclusions
.contains(beanName) && !
this
.
singletonsCurrentlyInCreation
.add(beanName)) {
throw new
BeanCurrentlyInCreationException(beanName);
}
}
把beanName添加到singletonsCurrentlyInCreation Set容器中,在这个集合里面的bean都是正在实例化的bean,就是实例化还没做完的BeanName。
try
{
singletonObject = singletonFactory.getObject();
newSingleton =
true
;
}
调到getObject方法,完成bean的实例化。接下来
finally
{
if
(recordSuppressedExceptions) {
this
.
suppressedExceptions
=
null
;
}
afterSingletonCreation(beanName);
}
if
(newSingleton) {
addSingleton(beanName, singletonObject);
}
getObject 调用完后,就代表着 Bean 实例化已经完成了,这时候就需要
1)singletonsCurrentlyInCreation 把 beanName 从这个集合中删除
2)addSingleton,把 bean 缓存到一级缓存中
protected void
addSingleton(String beanName, Object singletonObject) {
synchronized
(
this
.
singletonObjects
) {
this
.
singletonObjects
.put(beanName, singletonObject);
this
.
singletonFactories
.remove(beanName);
this
.
earlySingletonObjects
.remove(beanName);
this
.
registeredSingletons
.add(beanName);
}
4、
createBean方法
,具体实例化过程
代码位置:AbstractBeanFactory.doGetBean方法中
注意:默认初始化bean的条件是非抽象类,单例且非懒加载。
@Override
public void
preInstantiateSingletons()
throws
BeansException {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Pre-instantiating singletons in ”
+
this
);
}
//xml解析时,讲过,把所有beanName都缓存到beanDefinitionNames了
List<String> beanNames =
new
ArrayList<>(
this
.
beanDefinitionNames
);
// Trigger initialization of all non-lazy singleton beans…
for
(String beanName : beanNames) {
//把父BeanDefinition里面的属性拿到子BeanDefinition中
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果不是抽象的,单例的,非懒加载的就实例化
if
(!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断bean是否实现了FactoryBean接口,这里可以不看
if
(isFactoryBean(beanName)) {
Object bean = getBean(
FACTORY_BEAN_PREFIX
+ beanName);
if
(bean
instanceof
FactoryBean) {
final
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean
isEagerInit;
if
(System.
getSecurityManager
() !=
null
&& factory
instanceof
SmartFactoryBean) {
isEagerInit = AccessController.
doPrivileged
((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());
}
else
{
isEagerInit = (factory
instanceof
SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if
(isEagerInit) {
getBean(beanName);
}
}
}
else
{
//主要从这里进入,看看实例化过程
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans…
for
(String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if
(singletonInstance
instanceof
SmartInitializingSingleton) {
final
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if
(System.
getSecurityManager
() !=
null
) {
AccessController.
doPrivileged
((PrivilegedAction<Object>) () -> {
smartSingleton
.afterSingletonsInstantiated();
return null
;
}, getAccessControlContext());
}
else
{
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected
<
T
>
T
doGetBean(
final
String name,
@Nullable
final
Class<
T
> requiredType,
@Nullable
final
Object[] args,
boolean
typeCheckOnly)
throws
BeansException {
//如果是scope 是Prototype的,校验是否有出现循环依赖,如果有则直接报错
if
(isPrototypeCurrentlyInCreation(beanName)) {
throw new
BeanCurrentlyInCreationException(beanName);
}
//着重看,大部分是单例的情况
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try
{
return
createBean(beanName, mbd, args);
}
catch
(BeansException ex) {
destroySingleton(
beanName
);
throw
ex;
}
});
//
该
方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
4.1、进入方法createBean(beanName, mbd, args);
这个方法是
bean
实例化核心方法:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected
Object doCreateBean(
final
String beanName,
final
RootBeanDefinition mbd,
final
@Nullable
Object[] args)
throws
BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper =
null
;
if
(mbd.isSingleton()) {
instanceWrapper =
this
.
factoryBeanInstanceCache
.remove(beanName);
}
if
(instanceWrapper ==
null
) {
//创建实例,,重点看,重要程度:5
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if
(beanType != NullBean.
class
) {
mbd.
resolvedTargetType
= beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized
(mbd.
postProcessingLock
) {
if
(!mbd.
postProcessed
) {
try
{
//CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
//AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
//BeanPostProcessor接口的典型运用,这里要理解这个接口
//对类中注解的装配过程
//重要程度5,必须看
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.
postProcessed
=
true
;
}
}
//是否 单例bean提前暴露
boolean
earlySingletonExposure = (mbd.isSingleton() &&
this
.
allowCircularReferences
&&
isSingletonCurrentlyInCreation(beanName));
if
(earlySingletonExposure) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Eagerly caching bean ‘”
+ beanName +
“‘ to allow for resolving potential circular references”
);
}
//这里着重理解,对理解循环依赖帮助非常大,重要程度 5 添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try
{
//ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
populateBean(beanName, mbd, instanceWrapper);
//bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch
(Throwable ex) {
if
(ex
instanceof
BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw
(BeanCreationException) ex;
}
else
{
throw new
BeanCreationException(
mbd.getResourceDescription(), beanName,
“Initialization of bean failed”
, ex);
}
}
if
(earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName,
false
);
if
(earlySingletonReference !=
null
) {
……
}
}
// Register bean as disposable.
try
{
//注册bean销毁时的类DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch
(BeanDefinitionValidationException ex) {
throw new
BeanCreationException(
mbd.getResourceDescription(), beanName,
“Invalid destruction signature”
, ex);
}
return
exposedObject;
}
实例化方法,把bean实例化,并且包装成BeanWrapper。
4.2、点进instantiateUsingFactoryMethod这个方法里面
if
(mbd.getFactoryMethodName() !=
null
) {
return
instantiateUsingFactoryMethod(beanName, mbd, args);
}
这个方法是反射调用类中的factoryMethod方法。这要知道@Bean方法的原理,实际上spring会扫描有@bean注解的方法,然后把方法名称设置到BeanDefinition的factoryMethod属性中,接下来就会调到上面截图中的方法实现@Bean方法的调用。该方法里面的参数解析过程不需要了解。
1)有参构造函数的时候
//
寻找当前bean中有@Autowired注解的构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if
(ctors !=
null
|| mbd.getResolvedAutowireMode() ==
AUTOWIRE_CONSTRUCTOR
||
mbd.hasConstructorArgumentValues() || !ObjectUtils.
isEmpty
(args)) {
return
autowireConstructor(beanName, mbd, ctors, args);
}
determineConstructorsFromBeanPostProcessors这个方法是BeanPostProcessor接口类的首次应用,最终会掉到AutowiredAnnotationBeanPostProcessor类的方法,在方法中会扫描有注解的构造函数然后完成装配过程。
2)无参构造函数的实例化
//无参构造函数的实例化,大部分的实例是采用的无参构造函数的方式实例化
// No special handling: simply use no-arg constructor.
return
instantiateBean(beanName, mbd);
这就是简单的反射实例化
,
大部分类的实例化都会走这个逻辑
。
4.3、类中注解的收集
@Autowired
或者
@Resource
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
实例化完成后接下来就需要对类中的属性进行依赖注入操作,但是类里面属性和方法的依赖注入往往用@Autowired或者@Resource 注解,那么这些注解的依赖注入是如何完成的呢?
注解的收集:
// Allow post-processors to modify the merged bean definition.
synchronized
(mbd.
postProcessingLock
) {
if
(!mbd.
postProcessed
) {
try
{
//CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
//AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
//BeanPostProcessor接口的典型运用,这里要理解这个接口
//对类中注解的装配过程
//重要程度5,必须看
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch
(Throwable ex) {
throw new
BeanCreationException(mbd.getResourceDescription(), beanName,
“Post-processing of merged bean definition failed”
, ex);
}
mbd.
postProcessed
=
true
;
}
}
也是通过 BeanPostProcessor 接口类型实例来挨个处理的。
4.3.1、首先是
CommonAnnotationBeanPostProcessor
类,这个类完成了
@Resource
注解的属性或者方法的收集,这个类还对
@PostConstruct
和
@PreDestory
支持
protected void
applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
/*
* 1、扫描类里面的属性或者方法
* 2、判断属性或者方法上面是否有@PostConstruct @PreDestroy @Resource注解
* 3、如果有注解的属性或者方法,包装成一个类
* */
@Override
public void
postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//扫描@PostConstruct @PreDestroy
super
.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//扫描@Resource,扫描属性和方法上面是否有@Resource注解,如果有则收集起来封装成对象
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
CommonAnnotationBeanPostProcessor的构造方法:
public
CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.
LOWEST_PRECEDENCE
–
3
);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType(
“javax.xml.ws.WebServiceContext”
);
}
4.3.2、收集过程:
1
)看缓存里面有没有
InjectionMetadata
对象
private
InjectionMetadata findResourceMetadata(String beanName,
final
Class<?> clazz,
@Nullable
PropertyValues pvs) {
String cacheKey = (StringUtils.
hasLength
(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if
(InjectionMetadata.
needsRefresh
(metadata, clazz)) {
synchronized
(
this
.
injectionMetadataCache
) {
metadata =
this
.
injectionMetadataCache
.get(cacheKey);
if
(InjectionMetadata.
needsRefresh
(metadata, clazz)) {
if
(metadata !=
null
) {
metadata.clear(pvs);
}
//主要看这个方法
metadata = buildResourceMetadata(clazz);
this
.
injectionMetadataCache
.put(cacheKey, metadata);
}
}
}
return
metadata;
}
2)从类中获取所有Field对象,循环field对象,判断field有没有@Resource注解,如果有注解封装成 ResourceElement对象。
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata
ReflectionUtils.
doWithLocalFields
(targetClass, field -> {
else if
(field.isAnnotationPresent(
Resource
.
class
)) {
if
(Modifier.
isStatic
(field.getModifiers())) {
throw new
IllegalStateException(
“@Resource annotation is not supported on static fields”
);
}
if
(!
this
.
ignoredResourceTypes
.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
3)从类中获取所有Method对象,循环Method对象,判断Method有没有@Resource注解,如果有注解封装成ResourceElement对象。
ReflectionUtils.
doWithLocalMethods
(targetClass, method -> {
else if
(bridgedMethod.isAnnotationPresent(
Resource
.
class
)) {
if
(Modifier.
isStatic
(method.getModifiers())) {
throw new
IllegalStateException(
“@Resource annotation is not supported on static methods”
);
}
Class<?>[] paramTypes = method.getParameterTypes();
if
(paramTypes.
length
!=
1
) {
throw new
IllegalStateException(
“@Resource annotation requires a single-arg method: ”
+ method);
}
if
(!
this
.
ignoredResourceTypes
.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.
findPropertyForMethod
(bridgedMethod, clazz);
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
4)最终把两个field和Method封装的对象集合封装到InjectionMetadata对象中。
private
InjectionMetadata buildResourceMetadata(
final
Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements =
new
ArrayList<>();
elements.addAll(0, currElements);
return new InjectionMetadata(clazz, elements);
4.3.3、然后是
AutowiredAnnotationBeanPostProcessor
类,对
@Autowired
注解的属性和方法的收集。
收集过程基本上跟@Resource 注解的收集差不多,这里就不赘述了。
5、
注解@Resource与@Autowired的区别
@Resource注解
@Resource有两个常用属性name、type,所以分4种情况
指定name和type:通过name找到唯一的bean,找不到抛出异常;如果type和字段类型不一致,也会抛出异常
指定name:通过name找到唯一的bean,找不到抛出异常
指定type:通过tpye找到唯一的bean,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
都不指定:通过字段名作为key去查找,找到则赋值;找不到则再通过字段类型去查找,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
@Autowired注解
@Autowired只有一个属性required,默认值为true,为true时,找不到就抛异常,为false时,找不到就赋值为null。
@Autowired按类型查找,如果该类型的bean不唯一,则抛出异常;可通过组合注解解决@Autowired()@Qualifier(“baseDao”)。
相同点:
Spring都支持
都可以作用在字段和setter方法上
不同点:
-
Resource是JDK提供的,而Autowired是Spring提供的;
-
Resource不允许找不到bean的情况,
而Autowired允许(@Autowired(required = false));
-
指定name的方式不一样,@Resource(name = “baseDao”),@Autowired()@Qualifier(“baseDao”);
-
Resource默认通过name查找,而Autowired默认通过type查找。
二、
IOC\DI
依赖注入与循环依赖分析
1、
IOC\DI
依赖注入
经过AbstractAutowireCapableBeanFactory#doCreateBean方法的下面两个方法,完成了spring工厂对bean的创建,和类属性注解的扫描装配过程。
if
(instanceWrapper ==
null
) {
//创建实例,,重点看,重要程度:5
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
try
{
//CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
//AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
//BeanPostProcessor接口的典型运用,这里要理解这个接口
//对类中注解的装配过程
//重要程度5,必须看
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
然后将首次创建的单实例bean提前暴露,放到三级缓冲中(循环依赖使用)
1.1、是否单例bean提前暴露
boolean
earlySingletonExposure = (mbd.isSingleton() &&
this
.
allowCircularReferences
&&
isSingletonCurrentlyInCreation(beanName));
if
(earlySingletonExposure) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Eagerly caching bean ‘”
+ beanName +
“‘ to allow for resolving potential circular references”
);
}
//这里着重理解,对理解循环依赖帮助非常大,重要程度 5 添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
三级缓存对象工厂ObjectFactory.getObject()调用到这个方法
protected
Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if
(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return
exposedObject;
}
SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
default
Object getEarlyBeanReference(Object bean, String beanName)
throws
BeansException {
return
bean;
}
1.2、对应的方法populateBean:
try
{
//ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
populateBean(beanName, mbd, instanceWrapper);
//bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
看到这个if代码块
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
//重点看这个if代码块,重要程度 5
if
(hasInstAwareBpps) {
if
(pvs ==
null
) {
pvs = mbd.getPropertyValues();
}
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//依赖注入过程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if
(pvsToUse ==
null
) {
if
(filteredPds ==
null
) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.
allowCaching
);
}
/
/老版本用这个完成依赖注入过程,@Autowired的支持
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if
(pvsToUse ==
null
) {
return
;
}
}
pvs = pvsToUse;
}
}
}
这里又是一个BeanPostProcessor类型接口的运用,前面我们讲到了@Resource@Autowired注解的收集,那么这个方法就是根据收集到的注解进行反射调用。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessProperties
@Override
public
PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try
{
metadata.inject(bean, beanName, pvs);
}
public void
inject(Object target,
@Nullable
String beanName,
@Nullable
PropertyValues pvs)
throws
Throwable {
Collection<InjectedElement> checkedElements =
this
.
checkedElements
;
Collection<InjectedElement> elementsToIterate =
(checkedElements !=
null
? checkedElements :
this
.
injectedElements
);
if
(!elementsToIterate.isEmpty()) {
for
(InjectedElement element : elementsToIterate) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Processing injected element of bean ‘”
+ beanName +
“‘: ”
+ element);
}
element.inject(target, beanName, pvs);
}
}
}
循环收集到的metaData中的list对象,然后挨个调用里面的InjectedElement的inject方法完成依赖注入。
try
{
Method method = (Method)
this
.
member
;
ReflectionUtils.
makeAccessible
(method);
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
其中value值的获取,如果依赖的属性是一个引用类型必定会触发该属性的BeanFactory.getBean操作,从而从spring容器中获取到对应的实例。方法的依赖注入类似这里就不再赘述。
上述是对注解@Resource和@Autowired的依赖注入的实现逻辑,xml配置的依赖注入,比如在bean标签中配置了:
<property name=”age” value=”18″/>
标签的依赖注入是这个逻辑:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
//这个方法很鸡肋了,建议不看,是老版本用<property name=”username” value=”
hankin
“/>
//标签做依赖注入的代码实现,复杂且无用
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
这块逻辑是专门做xml配置依赖注入的,基本上现在基于xml配置的依赖很少使用,这里就不讲这块逻辑,没多大用。
2、单实例bean的循环依赖分析
假设业务bean CircularRefA里面,属性注入了CircularRefB,而且CircularRefB的属性里面也注入了CircularRefA,如此就形成了循环依赖的问题。
@Service
public class
CircularRefA {
@Value
(
“123”
)
private
String
username
;
@Autowired
private
CircularRefB
circularRefB
;
}
@Service
public class
CircularRefB {
@Value
(
“xxxk”
)
private
String
username
;
@Autowired
private
CircularRefA
circularRefA
;
}
2.1、流程图如下
流程如地址:
https://www.processon.com/view/link/5df9ce52e4b0c4255ea1a84f
2.2、从缓冲中获取bean实例的源码
1)根据beanName从缓存中拿实例,先从一级缓存拿;
2)如果一级缓存没有,从二级缓存中拿;
3)如果还拿不到,并且允许bean提前暴露,从三级缓存中拿到对象工厂
4)如果三级缓存中存在,则从工厂中拿到对象,然后升级到二级缓存,删除三级缓存
public class
DefaultSingletonBeanRegistry
extends
SimpleAliasRegistry
implements
SingletonBeanRegistry {
//一级缓存
private final
Map<String, Object>
singletonObjects
=
new
ConcurrentHashMap<>(
256
);
//
三
级缓存
private final
Map<String, ObjectFactory<?>>
singletonFactories
=
new
HashMap<>(16);
//
二
级缓存
private final
Map<String, Object>
earlySingletonObjects
=
new
HashMap<>(
16
);
@Nullable
protected
Object getSingleton(String beanName,
boolean
allowEarlyReference) {
//根据beanName从缓存中拿实例
//先从一级缓存拿
Object singletonObject = this.singletonObjects.get(beanName);
//如果bean还正在创建,还没创建完成,其实就是堆内存有了,属性还没有DI依赖注入
if
(singletonObject ==
null
&& isSingletonCurrentlyInCreation(beanName)) {
synchronized
(
this
.
singletonObjects
) {
//从二级缓存中拿
singletonObject = this.earlySingletonObjects.get(beanName);
//如果还拿不到,并且允许bean提前暴露
if
(singletonObject ==
null
&& allowEarlyReference) {
//从三级缓存中拿到对象工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if
(singletonFactory !=
null
) {
//从工厂中拿到对象
singletonObject = singletonFactory.getObject();
//升级到二级缓存
this
.
earlySingletonObjects
.put(beanName, singletonObject);
//删除三级缓存
this
.
singletonFactories
.remove(beanName);
}
}
}
}
return
singletonObject;
}
2.3、如果缓存中没有,触发getBean方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
1)
CircularRefA
首先执行doCreateBean方法,继续创建bean,并扫描属性注解。
//创建实例,,重点看,重要程度:5
instanceWrapper = createBeanInstance(beanName, mbd, args);
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
注意:
此时
CircularRefA还没有完全完成bean的实例化加属性赋值,但是该对象已经实例化,并且放到了三级缓存。
2)
CircularRefA
执行是否单例bean提前暴露,然后放入三级缓冲
singletonFactories中
boolean
earlySingletonExposure = (mbd.isSingleton() &&
this
.
allowCircularReferences
&&
isSingletonCurrentlyInCreation(beanName));
if
(earlySingletonExposure) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Eagerly caching bean ‘”
+ beanName +
“‘ to allow for resolving potential circular references”
);
}
//这里着重理解,对理解循环依赖帮助非常大,重要程度 5 添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
protected void
addSingletonFactory
(String beanName, ObjectFactory<?> singletonFactory) {
Assert.
notNull
(singletonFactory,
“Singleton factory must not be null”
);
synchronized
(
this
.
singletonObjects
) {
if
(!
this
.
singletonObjects
.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this
.
earlySingletonObjects
.remove(beanName);
this
.
registeredSingletons
.add(beanName);
}
}
}
3)
CircularRefA
最后调用bean的属性赋值方法populateBean()
//ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
populateBean(beanName, mbd, instanceWrapper);
2.4、执行@Autowired private CircularRefB circularRefB;
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//依赖注入过程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
此时
CircularRefA还没有完全完成bean的实例化加属性赋值,但是该对象已经实例化,并且放到了三级缓存,所以这个时候在完成属性CircularRefB的赋值的时候,又触发了对象CircularRefB的实例化操作,在完成CircularRefB对象的属性赋值的时候,可以获取到CircularRefA对象的实例,所以CircularRefB对象完成属性赋值,最后因为CircularRefB已经完成了实例化,所以CircularRefA对象可以完成最后的属性赋值。
2.5、实例化CircularRefB的过程中,又会引入CircularRefA
此时流程又回到到了开始阶段doGetBean方法,不过这个时候因为CircularRefA已经实例化,所以代码流程进入缓存
singletonFactories
中获取逻辑部分;获取到对象实例以后升级到二级缓存,然后删除三级缓存(注意三级缓存的生命周期只存在于对象创建的过程中,有点完成属性赋值就会删除)。
//如果还拿不到,并且允许bean提前暴露
if
(singletonObject ==
null
&& allowEarlyReference) {
//从三级缓存中拿到对象工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if
(singletonFactory !=
null
) {
//从工厂中拿到对象
singletonObject = singletonFactory.getObject();
//升级到二级缓存
this
.
earlySingletonObjects
.put(beanName, singletonObject);
//删除三级缓存
this
.
singletonFactories
.remove(beanName);
}
}
3、
bean
实例化后的操作
3.1、代码走到这里initializeBean方法:
try
{
/
/ioc di,依赖注入的核心方法,该方法必须看,重要程度:5
populateBean(beanName, mbd, instanceWrapper);
//bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)
protected
Object initializeBean(
final
String beanName,
final
Object bean,
@Nullable
RootBeanDefinition mbd) {
if
(System.
getSecurityManager
() !=
null
) {
AccessController.
doPrivileged
((PrivilegedAction<Object>) () -> {
invokeAwareMethods(
beanName
,
bean
);
return null
;
}, getAccessControlContext());
}
else
{
//调用Aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if
(mbd ==
null
|| !mbd.isSynthetic()) {
//对类中某些特殊方法的调用,比如@PostConstruct,Aware接口,非常重要 重要程度 :5
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try
{
//InitializingBean接口,afterPropertiesSet,init-method属性调用,非常重要,重要程度:5
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return
wrappedBean;
}
3.2、首先是对某些
Aware
接口的调用
private void
invokeAwareMethods(
final
String beanName,
final
Object bean) {
if
(bean
instanceof
Aware) {
if
(bean
instanceof
BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if
(bean
instanceof
BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if
(bcl !=
null
) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if
(bean
instanceof
BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.
this
);
}
}
}
3.3、然后
@PostConstruct
注解方法的调用
@Override
public
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws
BeansException {
Object result = existingBean;
/*
* 着重看几个
* 1、ApplicationContextAwareProcessor 对某个Aware接口方法的调用
* 2、InitDestroyAnnotationBeanPostProcessor @PostConstruct注解方法的调用
* 3、ImportAwareBeanPostProcessor 对ImportAware类型实例setImportMetadata调用
* 这个对理解springboot有很大帮助。 这里暂时不需要深入看
* */
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if
(current ==
null
) {
return
result;
}
result = current;
}
return
result;
}
这里又是一个BeanPostProcessor接口的运用,前面讲过,有@PostConstruct注解的方法会收集到一个metaData对象中,现在就是通过 BeanPostProcessor 接口调到CommonAnnotationBeanPostProcessor类,然后在类中拿到metaData对象,根据对象里面的容器来反射调用有注解的方法。
3.4、
InitializingBean
接口和
init-method
属性调用
//bean 实例化+ioc依赖注入完以后的调用,非常重要,重要程度:5
exposedObject = initializeBean(beanName, exposedObject, mbd);
//InitializingBean接口,afterPropertiesSet,init-method属性调用,非常重要,重要程度:5
invokeInitMethods(beanName, wrappedBean, mbd);
实现了InitializingBean接口的类就必然会调用到afterPropertiesSet
protected void
invokeInitMethods(String beanName,
final
Object bean,
@Nullable
RootBeanDefinition mbd)
throws
Throwable {
boolean
isInitializingBean = (bean
instanceof
InitializingBean);
if
(isInitializingBean && (mbd ==
null
|| !mbd.isExternallyManagedInitMethod(
“afterPropertiesSet”
))) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Invoking afterPropertiesSet() on bean with name ‘”
+ beanName +
“‘”
);
}
if
(System.
getSecurityManager
() !=
null
) {
try
{
AccessController.
doPrivileged
((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null
;
}, getAccessControlContext());
}
catch
(PrivilegedActionException pae) {
throw
pae.getException();
}
}
else
{
((InitializingBean) bean).afterPropertiesSet();
}
}
Init-method属性调用是在afterPropertiesSet之后
if
(mbd !=
null
&& bean.getClass() != NullBean.
class
) {
String initMethodName = mbd.getInitMethodName();
if
(StringUtils.
hasLength
(initMethodName) &&
!(isInitializingBean &&
“afterPropertiesSet”
.equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
在这个方法里面还有一个重要的逻辑:
if
(mbd ==
null
|| !mbd.isSynthetic()) {
wrappedBean =
applyBeanPostProcessorsAfterInitialization
(wrappedBean, beanName);
}
也是一个BeanPostProcessor接口的运用,在这里会返回bean的代理实例,这个就是AOP的入口。
4、
BeanPostProcessor 接口理解
BeanPostProcessor 接口类型实例是针对某种特定功能的埋点,在这个点会根据接口类型
来过滤掉不关注这个点的其他类,只有真正关注的类才会在这个点进行相应的功能实现。
4.
1
、获取有
@Autowired
注解的构造函数埋点
过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor
调用的方法是:determineCandidateConstructors
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
if
(instanceWrapper ==
null
) {
//创建实例,,重点看,重要程度:5
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Candidate constructors for autowiring?
//寻找当前正在实例化的bean中有@Autowired注解的构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if
(ctors !=
null
|| mbd.getResolvedAutowireMode() ==
AUTOWIRE_CONSTRUCTOR
||
mbd.hasConstructorArgumentValues() || !ObjectUtils.
isEmpty
(args)) {
//如果ctors不为空,就说明构造函数上有@Autowired注解
return
autowireConstructor(beanName, mbd, ctors, args);
}
4.
2
、收集
@Resource@Autowired@Value@PostConstruct
,
@PreDestroy
注解的方法和属性埋点
过滤的接口类型是:MergedBeanDefinitionPostProcessor
调用的方法是:postProcessMergedBeanDefinition
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
// Allow post-processors to modify the merged bean definition.
synchronized
(mbd.
postProcessingLock
) {
if
(!mbd.
postProcessed
) {
try
{
//CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解
//AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解
//BeanPostProcessor接口的典型运用,这里要理解这个接口
//对类中注解的装配过程
//重要程度5,必须看
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch
(Throwable ex) {
throw new
BeanCreationException(mbd.getResourceDescription(), beanName,
“Post-processing of merged bean definition failed”
, ex);
}
mbd.
postProcessed
=
true
;
}
}
protected void
applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
4.
3
、循环依赖解决中
bean
的提前暴露埋点
过滤的接口类型是:SmartInstantiationAwareBeanPostProcessor
调用的方法是:getEarlyBeanReference
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//是否 单例bean提前暴露
boolean
earlySingletonExposure = (mbd.isSingleton() &&
this
.
allowCircularReferences
&&
isSingletonCurrentlyInCreation(beanName));
if
(earlySingletonExposure) {
if
(
logger
.isTraceEnabled()) {
logger
.trace(
“Eagerly caching bean ‘”
+ beanName +
“‘ to allow for resolving potential circular references”
);
}
//这里着重理解,对理解循环依赖帮助非常大,重要程度 5 添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
4.
4
、阻止依赖注入埋点
过滤的接口类型是:InstantiationAwareBeanPostProcessor
调用的方法是:postProcessAfterInstantiation
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
//这里很有意思,写接口可以让所有类都不能依赖注入
if
(!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
//是否需要DI,依赖注入
continueWithPropertyPopulation =
false
;
break
;
}
}
}
}
default boolean
postProcessAfterInstantiation
(Object bean, String beanName)
throws
BeansException {
return true
;
}
4.5、
IOC/DI
依赖注入埋点
过滤的接口类型是:InstantiationAwareBeanPostProcessor
调用的方法是:postProcessProperties
//重点看这个if代码块,重要程度 5
if
(hasInstAwareBpps) {
if
(pvs ==
null
) {
pvs = mbd.getPropertyValues();
}
for
(BeanPostProcessor bp : getBeanPostProcessors()) {
if
(bp
instanceof
InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//依赖注入过程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if
(pvsToUse ==
null
) {
if
(filteredPds ==
null
) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.
allowCaching
);
}
//老版本用这个完成依赖注入过程,@Autowired的支持
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if
(pvsToUse ==
null
) {
return
;
}
}
pvs = pvsToUse;
}
}
}
5、总结:
循环依赖步骤:
1)A类无参构造函数实例化后,设置三级缓存;
2)A类populateBean进行依赖注入,这里触发了B类属性的getBean操作;
3)B类无参构造函数实例化后,设置三级缓存;
4)B类populateBean进行依赖注入,这里触发了A 类属性的getBean操作;
5)A类之前正在实例化,
singletonsCurrentlyInCreation
集合中有已经有这个A类了,三级缓存里面也有了,所以这时候是从三级缓存中拿到的提前暴露的A实例,该实例还没有进行B类属性的依赖注入的,B类属性为空;
6)B类拿到了A的提前暴露实例注入到A类属性中了;
7)B类实例化已经完成,B类的实例化是由A类实例化中B属性的依赖注入触发的getBean操作进行的,现在B已经实例化,所以A类中B属性就可以完成依赖注入了,这时候A类B属性已经有值了;
8)B类A属性指向的就是A类实例堆空间,所以这时候B类A属性也会有值了。