第二章 Spring bean实例化、IOC、循环依赖笔记

  • Post author:
  • Post category:其他





一、




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属性也会有值了。