深度解析从IOC容器中获取Bean的过程

一、学习指引​

你了解过从Spring IOC容器中获取Bean的过程吗?

成都创新互联公司专注于企业全网整合营销推广、网站重做改版、平邑网站定制设计、自适应品牌网站建设、H5响应式网站商城网站建设、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为平邑等各大城市提供网站开发制作服务。

学习过Spring的小伙伴都知道:如果是单实例Bean,则IOC容器启动时,就会创建Bean对象,IOC容器关闭时,销毁Bean对象。如果是多实例Bean,IOC容器在启动时,不会创建Bean对象,在每次从IOC容器中获取Bean对象时,都会创建新的Bean对象返回,IOC容器关闭时,也不会销毁对象。也就是说,如果是多实例Bean,IOC容器不会管理Bean对象。

那从IOC容器中获取Bean的具体过程是怎样的呢?想深度学习Spring源码的小伙伴继续往下看。

二、测试案例​

整个调试Spring6.0源码的案例玩玩儿呗?

本章的案例比较简单,只是实现一个用于调试源码的小案例,具体的实现步骤如下所示。

(1)创建配置类BeanConfig

BeanConfig类的源码详见:spring-annotation-chapter-04工程下的io.binghe.spring.annotation.chapter04.config.BeanConfig。

@Configuration
@ComponentScan(basePackages = "io.binghe.spring.annotation.chapter04")
public class BeanConfig {
}

可以看到,在BeanConfig类上标注了@Configuration注解,说明BeanConfig类是Spring的配置类,使用@ComponentScan注解标注了扫描的包是io.binghe.spring.annotation.chapter04。

(2)创建测试类BeanTest

BeanTest类的源码详见:spring-annotation-chapter-04工程下的io.binghe.spring.annotation.chapter04.BeanTest。

public class BeanTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
context.close();
}
}

可以看到,在BeanTest类中只是简单的使用AnnotationConfigApplicationContext类创建IOC容器,并关闭IOC容器。

好了,测试案例准备好了,接下来,就一步步分析从IOC容器中获取Bean的过程。

三、源码时序图​

结合时序图理解源码会事半功倍,你觉得呢?

其实,经过前面章节的学习,细心的小伙伴在调试Spring源码的过程中会发现,在Spring的AbstractApplicationContext类中的refresh()方法中,会调用invokeBeanFactoryPostProcessors()方法,就是在这个invokeBeanFactoryPostProcessors()方法中后续的调用过程中,会调用beanFactory对象的getBean()方法来获取Bean对象。本章,就一起分析从invokeBeanFactoryPostProcessors()方法中获取Bean对象的过程。

从IOC容器中获取Bean的过程的源码时序图如图4-1和4-2所示。

图4-1

图4-2

由图4-1和图4-2可以看出,从IOC容器中获取Bean的过程会涉及到BeanTest类、AnnotationConfigApplicationContext类、AbstractApplicationContext类、PostProcessorRegistrationDelegate类、AbstractBeanFactory类、DefaultSingletonBeanRegistry类和AbstractAutowireCapableBeanFactory类。具体的源码执行细节参见源码解析部分。

四、源码解析​

源码时序图整清楚了,那就整源码解析呗!

从IOC容器中获取Bean的过程的源码执行流程,结合源码执行的时序图,会理解的更加深刻。

(1)运行案例程序启动类

案例程序启动类源码详见:spring-annotation-chapter-04工程下的io.binghe.spring.annotation.chapter04.BeanTest,运行BeanTest类的main()方法。

在BeanTest类的main()方法中调用了AnnotationConfigApplicationContext类的构造方法,并传入了ComponentScanConfig类的Class对象来创建IOC容器。接下来,会进入AnnotationConfigApplicationContext类的构造方法。

(2)解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class... componentClasses)构造方法

源码详见:org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class... componentClasses)。

public AnnotationConfigApplicationContext(Class... componentClasses) {
this();
register(componentClasses);
refresh();
}

可以看到,在上述构造方法中,调用了refresh()方法来刷新IOC容器。

(3)解析AbstractApplicationContext类的refresh()方法

源码详见:org.springframework.context.support.AbstractApplicationContext#refresh()。

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//############省略其他代码##############
try {
//############省略其他代码##############
invokeBeanFactoryPostProcessors(beanFactory);
//############省略其他代码##############
}catch (BeansException ex) {
//############省略其他代码##############
}finally {
//############省略其他代码##############
}
}
}

refresh()方法是Spring中一个非常重要的方法,很多重要的功能和特性都是通过refresh()方法进行注入的。可以看到,在refresh()方法中,调用了invokeBeanFactoryPostProcessors()方法。

(4)解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

源码详见:org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

可以看到,在AbstractApplicationContext类的invokeBeanFactoryPostProcessors()方法中调用了PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors()方法。

(5)解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法

源码详见:org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)。

由于方法的源码比较长,这里,只关注当前最核心的逻辑,如下所示。

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

//############省略其他代码##############
List currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
//############省略其他代码##############
}

可以看到,在PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法中,有多处通过beanFactory对象的getBean()方法获取Bean对象的代码。

(6)解析AbstractBeanFactory类的getBean(String name, ClassrequiredType)方法

源码详见org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, ClassrequiredType)。

@Override
public T getBean(String name, Class requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}

可以看到,getBean()方法调用了doGetBean()方法。

(7)解析AbstractBeanFactory类的doGetBean(String name, ClassrequiredType, Object[] args, boolean typeCheckOnly)方法

源码详见:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean(String name, @Nullable ClassrequiredType, @Nullable Object[] args, boolean typeCheckOnly)。

protected  T doGetBean(
String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object beanInstance;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}

return adaptBeanInstance(name, beanInstance, requiredType);
}

doGetBean()方法的源码比较长,也是一个非常重要的方法,方法的大体流程如下所示。

  • 先通过transformedBeanName()方法转换bean的名称,这里可能是FactoryBean的名称(&开头),需要转成不带&开头的名称,如果有别名,再获取别名。
  • 从缓存中获取bean,这里的缓存分为一二三级缓存,也就是spring的三级缓存。
  • 根据获取到的对象再去获取想要的Bean,因为这里获取到的对象可能是需要的Bean,也可能是FactoryBean(工厂Bean)。
  • 如果缓存中没有,就去创建Bean对象。
  • 查看有没有父类的BeanFactory,如果有,那么就使用父类去创建Bean对象。
  • 获取要创建的Bean对象的@DependsOn注解上的名称,先去创建DependsOn的Bean,并且校验是否存在循环引用。
  • 创建Bean,根据类型创建不同的Bean,比如singleton,prototype,request,session等。
  • 如果需要转换类型,则进行类型转换。如果不需要转换类型,就不转换类型。

本章后续的源码解析部分,都是以doGetBean()方法作为基础进行解析的。

(8)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName)方法

源码详见:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(String beanName)

@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

可以看到,在getSingleton()方法中调用了另一个getSingleton()方法。

(9)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName, boolean allowEarlyReference)方法

源码详见:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)。

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

在Spring中,这个getSingleton(String beanName, boolean allowEarlyReference)方法是个非常重要的方法,这个方法中使用了Spring的三级缓存,在后续的文章中,还会对这个方法进行深度解析。这里,先给大家介绍下Spring的三级缓存。

  • singletonObjects:一级缓存,实例化的Bean都会存储在这个Map集合中。
  • earlySingletonObjects:二级缓存,存放未完成的bean的缓存,如果有代理的话,存放的是代理对象。
  • singletonFactories:三级缓存,存放的是一个ObjectFactory,数据通过getObject方法获得。

(10)解析AbstractBeanFactory类的getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)方法

源码详见:org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)。

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//name是否是以&开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
//如果bean不是FactoryBean,直接返回beanInstance
if (!(beanInstance instanceof FactoryBean factoryBean)) {
return beanInstance;
}

Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
//从缓存中获取对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//通过FactoryBean获取需要的beanInstance
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
}
return object;
}

整个getObjectForBeanInstance()方法的源码还算是比较简单,大家多看几遍就能理解。这里,给大家说明下大体的流程。

  • 首先判断name是不是FactoryBean的name,也就是&开头的name,如果beanInstance不是FactoryBean则抛异常。
  • 如果name是FactoryBeanName,那么需要获取的就是FactoryBean,直接返回对象。
  • 如果都没有返回,那么已经可以确定此时已经可以确定beanInstance是FactoryBean了,因为如果不是FactoryBean在(beanInstance instanceof FactoryBean)就已经返回了。
  • 通过FactoryBean的getObject方法获取需要的Bean实例。

(11)解析DefaultSingletonBeanRegistry类的getSingleton(String beanName, ObjectFactory singletonFactory)方法。

源码详见:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory singletonFactory)。

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
//#########省略异常代码################
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//获取创建的bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
//将创建的Bean对象加到一级缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

在上述getSingleton()方法中,传入了一个beanName和一个singletonFactory来创建单实例Bean对象,ObjectFactory类中封装了创建Bean的具体逻辑。在上述getSingleton()方法中,创建Bean对象之前调用了 beforeSingletonCreation()方法,在创建对象之后调用了afterSingletonCreation()方法。两个方法的源码如下所示。

protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

可以看到,beforeSingletonCreation()方法和afterSingletonCreation()方法的执行逻辑比较简单,这里不再赘述。

(12)回到AbstractBeanFactory类的doGetBean(String name, ClassrequiredType, Object[] args, boolean typeCheckOnly)方法,这里重点看如下代码片段。

if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

可以看到,调用了createBean()方法来创建Bean对象。

(13)解析AbstractAutowireCapableBeanFactory类的createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法

源码详见:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//##############省略其他代码############
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creati

网站栏目:深度解析从IOC容器中获取Bean的过程
浏览地址:http://www.gawzjz.com/qtweb/news23/190673.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联