上一篇Spring创建Bean我们知道了,Spring创建Bean后,会将Bean存放在容器的singletonObjects中,那么获取一个bean的过程又是如何呢?我们还是使用之前用到的debug断点调试法来探究一下。
1. 获取Bean源码阅读
我们知道,Spring中获取一个Bean是使用getBean(beanName)来获取,那么我们来跟踪getBean(beanName)的源码,看看获取bean的逻辑,getBean(beanName)的源码如下:
public Object getBean(String name) throws BeansException {
/**
* 该方法执行后进入AbstractRefreshableApplicationContext的assertBeanFactoryActive()方法,
* 该方法是一个空方法,所以不用管
*/
this.assertBeanFactoryActive();
//1.先获取容器对象
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
//2.再通过容器beanFactory获取对象
Object object = beanFactory.getBean(name);
return object;
}
从源码上可以得到,核心逻辑我们需要阅读this.getBeanFactory().getBean(name)对应的方法。但是这行代码是一个链式调用,this.getBeanFactory()方法得到的ConfigurableListableBeanFactory是一个接口,实际上返回的是他的实现类DefaultListableBeanFactory。调用DefaultListableBeanFactory的getBean方法来获取bean。
2. DefaultListableBeanFactory的getBean方法源码阅读
getBean()的源码中调用的是doGetBean(),这个方法我们在探索创建Bean的时候,有探索过,只是之前探索的是创建Bean的过程,现在需要探索获取bean的过程。贴出源码,源码如下:
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
3. AbstractBeanFactory的doGetBean()方法源码阅读
doGetBean()方法是获取bean的执行方法,该方法的逻辑很重要。需要仔细阅读,源码如下:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
//该方法执行后,对象就拿到了
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var12;
if (dependsOn != null) {
var12 = dependsOn;
int var13 = dependsOn.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dep = var12[var14];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
try {
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var31) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
}
}
}
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var12 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
beanInstance = this.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 = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var30) {
throw new ScopeNotActiveException(beanName, scopeName, var30);
}
}
} catch (BeansException var32) {
beanCreation.tag("exception", var32.getClass().toString());
beanCreation.tag("message", String.valueOf(var32.getMessage()));
this.cleanupAfterBeanCreationFailure(beanName);
throw var32;
} finally {
beanCreation.end();
}
}
return this.adaptBeanInstance(name, beanInstance, requiredType);
}
4. DefaultSingletonBeanRegistry的getSingleton方法源码阅读
getSingleton()是最终的获取方法,由于对象创建后,会存在singletonObjects中,所以在singletonObjects这个Map获取到后直接返回,源码如下:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
/**
* 根据beanName在singletonObjects中获取,
* 如果获取到对象信息,即singletonObject != null,
* 则返回singletonObject
*/
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
到此,Spring获取Bean的完整流程就全部分析完成了,我们做个总结。结论如下:
- 首先通过ApplicationContext对象,调用getBean()方法
- getBean()方法中会先获取BeanFactory实例对象DefaultListableBeanFactory
- 然后调用BeanFactory的getBean方法
- getBean()方法中调用doGetBean()方法
- doGetBean()方法中根据传入的beanName调用getSingleton()方法
- getSingleton()中根据beanName查询singletonObjects中Value,该Value就是bean对象
- 查询到bean对象后,返回
以上就是Spring获取bean的所有逻辑流程!