「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
前言
在对Spring启动流程的解析中,可以了解到BeanFactory是Spring的一个核心组件。在启动流程中使用的BeanFactory实现为DefaultListableBeanFactory,其继承树如下图所示:
www.processon.com/view/link/6…
实际上,虽然上下文对象ApplicationContext实现了BeanFactory接口,但对于BeanFactory的使用是通过组合而非继承关系实现的,相关功能是通过其设置的DefaultListableBeanFactory来进行的。
因此这里就围绕DefaultListableBeanFactory进行解析。
类解析
需要预先知道使用代表信息的类
第一个就是BeanDefinition了,这个类代表的信息是一个bean的身份证,记录了创建一个bean时所需要的相关信息。
第二个是BeanDefinitionHolder,实际上算是BeanDefinition的一个门面,附带了名字以及别名相关的信息,略显不重要,类上注释这么交代:
If you don't care about BeanNameAware and the like,
* registering RootBeanDefinition or ChildBeanDefinition is good enough.
注释
先来看看类上的注释,Spring的类注释都写得很详细:
Spring's default implementation of the {@link ConfigurableListableBeanFactory}
and {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory
based on bean definition metadata, extensible through post-processors.
<p>Typical usage is registering all bean definitions first (possibly read
from a bean definition file), before accessing beans. Bean lookup by name
is therefore an inexpensive operation in a local bean definition table,
operating on pre-resolved bean definition metadata objects.
<p>Note that readers for specific bean definition formats are typically
implemented separately rather than as bean factory subclasses: see for example
{@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
<p>For an alternative implementation of the
{@link org.springframework.beans.factory.ListableBeanFactory} interface,
have a look at {@link StaticListableBeanFactory}, which manages existing
bean instances rather than creating new ones based on bean definitions.
大致意思讲的是:
-
大致用途:DefaultListableBeanFactory是Spring中对于ConfigurableListableBeanFactory和BeanDefinitionRegistry的默认实现,一个基于beanDefinition元数据,支持通过post处理器扩展的完整beanFactory。
-
使用案例:典型的使用方法是:
- 在触达到bean之前,先注册所有BeanDeifinition(可能是从beanDefinition文件)
在预先初始化的BD元数据对象的本地BD表中,通过名字查找bean是一个耗费小的操作。
-
读取BD注意事项:
- 特殊读取BD格式的reader是被单独实现的,而不是作为beanFactory的子类,例子:XmlBeanDefinitionReader
-
平级替代:一个可替换的实现的接口是ListableBeanFactory,例子是StaticListableBeanFactory,这个实现类管理的是已存在的bean实例,而非通过BD创建一个新的bean。
根据注释,大概能了解到的信息如下:
- DefaultListableBeanFactory在Spring中的地位其实相当之高,是一个默认的终端实现,也就是说在非特殊的流程中一般见到的BeanFactory就是这个了。
- DefaultListableBeanFactory的一个核心是BD的注册和通过BD构造新实例,因此源码的阅读上重点关注这部分的内容。
流程解析 - 1.BD注册
这块主要是registerBeanDefinition,在之前额外信息【1】中已经说过了,此处不再赘述。
需要注意的一点是,这个接口是registerBeanDefinition,实际上并不是BeanFactory的接口实现,而是对BeanDefinitionRegistry的接口实现。
这一步中留意一下注释里提到的本地注册表,实质上是一堆ConcurrentHashMap构成的。
需要注意的是,这里的注册表和bean实例没关系,存放的其实是BeanDefinition。
流程解析 - 2.bean获取
到了获取Bean,根据名称很容易能定位到getBean的接口。
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
if (resolved == null) {
throw new NoSuchBeanDefinitionException(requiredType);
}
return (T) resolved;
}
看参数就能知道是通过class来获取bean的,这里也符合前面通过beanFactory中,存储BD的逻辑:名字为key,BD为value。具体的工作到了resolveBean里,接下来看看这个方法:
@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
}
else if (parent != null) {
ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
if (args != null) {
return parentProvider.getObject(args);
}
else {
return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
}
}
return null;
}
分解一下:
- resolveNamedBean
- parentBeanFactory
- ObjectProvider
resolveNamedBean
在看代码之前需要提前知道一下这个ResolvableType是何方神圣:
在上一步中,我们是通过一下方法来获取这个对象的:
public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz) {
@Override
public ResolvableType[] getGenerics() {
return EMPTY_TYPES_ARRAY;
}
@Override
public boolean isAssignableFrom(Class<?> other) {
return (clazz == null || ClassUtils.isAssignable(clazz, other));
}
@Override
public boolean isAssignableFrom(ResolvableType other) {
Class<?> otherClass = other.resolve();
return (otherClass != null && (clazz == null || ClassUtils.isAssignable(clazz, otherClass)));
}
};
}
就当作一个带着一些判别方法的class代理对象就可以了。
接下来看看具体的方法:
private <T> NamedBeanHolder<T> resolveNamedBean(
ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
//这个方法调用链很深,其实简单点来说就是通过class对象获取bean名称
String[] candidateNames = getBeanNamesForType(requiredType);
//从这里开始就是通过上面取得的bean名称,来获取实例了
//这里就会根据bean名称以及beanDefinition的相关属性,来获取可能需要的所有bean
if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = StringUtils.toStringArray(autowireCandidates);
}
}
if (candidateNames.length == 1) {
return resolveNamedBean(candidateNames[0], requiredType, args);
}
else if (candidateNames.length > 1) {
Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (String beanName : candidateNames) {
//在这里就能看到:如果有这个单例bean,那么就获取这个单例bean
if (containsSingleton(beanName) && args == null) {
Object beanInstance = getBean(beanName);
candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
}
else {
candidates.put(beanName, getType(beanName));
}
}
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
if (candidateName == null) {
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
}
if (candidateName != null) {
Object beanInstance = candidates.get(candidateName);
if (beanInstance == null) {
return null;
}
if (beanInstance instanceof Class) {
return resolveNamedBean(candidateName, requiredType, args);
}
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
}
if (!nonUniqueAsNull) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
}
}
return null;
}
大致浏览一下这个方法,其实做的事情是这样的:
-
首先,通过class,获取bean名称
-
通过这些bean名称,来获取一个备选name组合(如果有autowired的BD,就只取这些,否则全部取)
-
经过上面的步骤,在来进行分析:
- 如果只剩一个了,那么就去获取bean
- 如果还剩很多,那就先获取bean,根据优先级来决定最后剩下的bean名称,最后还是获取bean
在这里又兜兜转转回到了getBean,但这个getBean实际上就到了AbstractBeanFactory里面,这里就是获取bean最后的关键步骤了。
来看AbstractBeanFactory里的这个方法:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean方法就一百多行,就不一次性贴出,来分部解析:
doGetBean【1】 - 获取bean名称并尝试缓存获取
在方法的前面会进行一个名称的获取:
String beanName = transformedBeanName(name);
可能会有疑问了:不是有名字了吗为什么还要获取一遍?
- 其实是因为Spring是允许bean有别名的,因此需要先看看是否有已经根据别名初始化了的bean。
接下来就是获取单例bean:
Object sharedInstance = getSingleton(beanName);
这里的获取单例,是DefaultSingletonBeanRegistry里的方法。
- Spring中经常出现的三级缓存,就在这个类中了。
来看看这里的方法:
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;
}
这里会在这三个缓存中来尝试获取bean:
- singletonObjects
- earlySingletonObjects
- singletonFactories
这里能看到,三级缓存也遵守了Spring中和bean相关的一致定义:相关的缓存都是使用bean名称作为key的。
在这里是不太清楚前两个缓存有啥区别,不过第三个缓存的功能还是比较清楚的:
- 事实上这里存放的是来制造early单例的工厂。
关于这部分的内容,我们就放到BeanRegistry里来解析,这里就先往下看流程。
doGetBean【2】 - 成功获取缓存
如果上一步获取到了缓存,那么接下来执行的就是这部分的代码(上面传入的args是null):
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);
}
实际上就到这个getObjectForBeanInstance了:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
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;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
这里的注解里出现了一个也是Spring中高频被问到的类:factoryBean,我们也放到后面一并进行解析,这里只需要知道这个FactoryBean代表的其实就是把Factory封装成bean。
流程其实想要做的事情很简单,如果外部获取的是FactoryBean,就判断后返回;如果不是,就尝试通过这个FactoryBean,来获取调用方期望获得的bean。
doGetBean【3】 - 获取缓存失败
如果在【1】中获取单例bean失败,或者外部传入的args不为null,那么此时会执行下面的代码:
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).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) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
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();
}
}
配置相关
- addBeanPostProcessor
- ignoreDependencyInterface