Spring Bean的获取过程

Bean 的创建与获取是一个比较复杂的过程,本文主要关注 bean 获取的过程。

代码

一个比较好的阅读源码的方法是 debug,可以跟踪到代码执行的每一步。如下是一段测试代码,可用于调试 getBean 方法的调用过程。

1
2
3
4
5
6
7
8
9
10
// 定义 bean factory
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();

// 注册一个 BeanDefinition
RootBeanDefinition bda = new RootBeanDefinition(A.class);
bda.setScope(RootBeanDefinition.SCOPE_SINGLETON);
bf.registerBeanDefinition("a", bda);

// 根据 bean name 获取 bean
bf.getBean("a");

这里定义了一个 DefaultListableBeanFactory 作为 Spring 的 bean factory,然后为类型 A 创建了一个 RootBeanDefinition,将其 scope 设置为 singleton,并注入到 bean factory 中,最后通过 BeanFactory 接口的 getBean 方法获取该 bean 实例。

获取过程

在 IDE 中调试上面的代码,跟踪 getBean 方法的执行过程

首先看到的是 AbstractBeanFactory 的 getBean 方法,它的实现如下:

1
2
3
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

可以看到是交给 doGetBean 方法处理的,这个方法才是具体的执行者。

doGetBean

doGetBean 是 AbstractBeanFactory 类里的一个核心方法,它封装的获取 bean 的整个流程,也是我们要看的重点。它签名如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 返回一个指定类型的实例,既可以是共享的(singleton)也可以是独立的(prototype)
*
* Return an instance, which may be shared or independent, of the specified bean.
* @param name 要获取的 bean 的名字
* @param requiredType 要获取的 bean 的类型
* @param args 使用显式参数创建bean实例时要使用的参数(仅在创建新实例时应用,获取实例时用不到)
* @param typeCheckOnly 要获取的实例是否仅用于类型检查
* @return bean 的实例
* @throws BeansException 无法创建 bean 实例时抛出该异常
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException

转换 beanName

第一步要对 beanName 进行处理:如果是 factoryBean 则去掉前缀 & ,然后将别名转换为原始名

1
2
3
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

通过 BeanFactoryUtils.transformedBeanName(String name) 方法去掉 & 符号前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 没有 & 符号前缀,直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 去掉 & 符号,并且将映射关系添加到缓存中
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
// 循环去掉 & 符号
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
// 返回结果
return beanName;
});
}

通过 SimpleAliasRegistry.canonicalName(String name) 方法获取原名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// key: 别名 value: 原名
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}

尝试从 singleton 缓存中获取

拿到了 beanName 之后,先到 singleton 缓存中查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// DefaultSingletonBeanRegistry
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存中查找
Object singletonObject = this.singletonObjects.get(beanName);

//缓存中没有,且当前正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {

// 从early缓存中查找
singletonObject = this.earlySingletonObjects.get(beanName);

// early缓存中没有,且允许创建early references对应的对象
if (singletonObject == null && allowEarlyReference) {

// 获取工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过工厂创建对象
singletonObject = singletonFactory.getObject();

// 添加到early缓存中
this.earlySingletonObjects.put(beanName, singletonObject);

// 从工厂缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

因为 bean 还未创建,也不在创建过程中,所以 isSingletonCurrentlyInCreation(beanName) 返回 false,跳过后续处理,返回 null

若从 singleton 缓存中获取到

若从缓存获取到实例,并且参数为空,首先要判断下 bean 是否正在创建中(处理循环引用),然后对 bean 进行处理,获取实际需要的 bean(比如 sharedInstance 为 factoryBean,实际需要的是它对应的实例,则在这一步处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 已经注册过,并且参数为空
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
// singleton对象正在创建中
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 + "'");
}
}

// 对 sharedInstance 进行处理,比如 factoryBean 需要创建对应实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

这里取到的是 null,即未获取到,所以继续走下面的获取 bean 流程。

若未从 singleton 缓存中获取到

第一次调 doGetBean 时,bean 还未创建,因此从缓存中取不到,会走到下面的流程

检测 Prototype 循环引用

对 prototype 的循环引用进行检测,如果是正在创建中,则说明有循环引用,则抛异常结束

1
2
3
4
5
6
7
8
9
10
11
12
// 如果是 prototype 的,并且正在创建中,抛异常结束
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

委托给 parentBeanFactory

若 parentBeanFactory 不为空,并且当前 BeanFactory 不存在这个 bean,则需要交给 parentBeanFactory 处理

先要获取到原始的 bean name,用于后续 getBean

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 获取原始的 beanName,如果入参以 & 符号开头,则返回结果也以 & 符号开头
*
* @param name the user-specified name
* @return the original bean name
*/
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name);
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
  • 如果 parentBeanFactory 是 AbstractBeanFactory 类型的实例,则直接调用 doGetBean 方法
  • 否则,如果 args 不为空,则委托 BeanFactory 的 getBean(String name, Object... args) 方法
  • 否则,如果 requiredType 不为空,则委托 BeanFactory 的 getBean(String name, ClassrequiredType) 方法
  • 否则,委托 BeanFactory 的 getBean(String name) 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 获取 parent bean factory
BeanFactory parentBeanFactory = getParentBeanFactory();

// parent bean factory 不为空,且当前 bean factory 不存在这个 beanName 对应的 BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 获取原始的 beanName
String nameToLookup = originalBeanName(name);

if (parentBeanFactory instanceof AbstractBeanFactory) {
// parent bean factory 也是 AbstractBeanFactory 类型,则直接委托它的 doGetBean 方法处理
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 否则,如果 args 不为空,委托 BeanFactory 的 getBean(String name, Object... args) 方法
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 否则,如果 requiredType 不为空,委托 BeanFactory 的 getBean(String name, Class<T> requiredType) 方法
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
// 否则,委托 BeanFactory 的 getBean(String name) 方法处理
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

标记 bean 已经创建

如果要创建的 bean 不是仅用于类型检查,那么需要标记 bean 的状态为已创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 如果不是仅用于类型检查,则标记 bean 已经创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}

获取 MergedBeanDefinition

所谓 MergedBeanDefinition,可以理解为合并后的 BeanDefinition。这是因为 BeanDefinition 可能存在继承关系,需要合并相关属性后才能得到完整的 BeanDefinition,进而用于创建 Bean。

获取注册的 BeanDefinition

首先要先根据 beanName 拿到已注册的 BeanDefinition

1
2
3
4
5
/**
* 返回指定的bean name对应的bean definition
* 只要需要bean definition metadata的地方都需要调用该方法,所以子类要自己做好缓存
*/
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

具体是交给 DefaultListableBeanFactory 进行处理的

1
2
3
4
5
6
7
8
9
10
11
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
// 从map中获取BeanDefinition
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isTraceEnabled()) {
logger.trace("No bean named '" + beanName + "' found in " + this);
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}

进行合并处理

已注册的 BeanDefinition 可能是 ChildBeanDefinition,还需要进一步处理

1
2
3
4
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
  1. 先尝试从 mergedBeanDefinitions 缓存获取,若未获取到,则进行下面的操作

    mbd = this.mergedBeanDefinitions.get(beanName);

  2. 若该 BeanDefinition 没有 parent,则直接构造 RootBeanDefinition

    1
    2
    3
    4
    5
    6
    if (bd instanceof RootBeanDefinition) {
    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
    }
    else {
    mbd = new RootBeanDefinition(bd);
    }
  3. 否则,获取 parentBean 的名字

    1
    2
    // 获取 parentBean 的名字
    String parentBeanName = transformedBeanName(bd.getParentName());
  4. 若和当前的不是同一个 bean,则需要合并

    1
    2
    3
    4
    // 和当前的不是同一个,则需要合并
    if (!beanName.equals(parentBeanName)) {
    pbd = getMergedBeanDefinition(parentBeanName);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
    // 拿到原始的beanName
    String beanName = transformedBeanName(name);

    // 不在当前的bean factory里,那么去parent bean factory里找找
    // Efficiently check whether bean definition exists in this factory.
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
    return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
    }

    // 自己解析吧
    // Resolve merged bean definition locally.
    return getMergedLocalBeanDefinition(beanName);
    }
  5. 否则,交给 parentBeanFactory 处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 获取 parent BeanFactory
    BeanFactory parent = getParentBeanFactory();

    // 通过 parentBeanFactory 合并 bean definition
    if (parent instanceof ConfigurableBeanFactory) {
    pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
    }
    else {
    throw new NoSuchBeanDefinitionException(parentBeanName,
    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
    "': cannot be resolved without an AbstractBeanFactory parent");
    }
  6. 深拷贝。通过 4、5 获取到的 BeanDefintion 并不直接使用,而是返回深拷贝的结果

    1
    2
    3
    // 深拷贝,并且覆盖属性值
    mbd = new RootBeanDefinition(pbd);
    mbd.overrideFrom(bd);
  7. 到这里已经拿到了 MergedBeanDefinition,剩下的就是一些通用的设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 如果未配置 scope,则设置为默认的 singleton scope
    if (!StringUtils.hasLength(mbd.getScope())) {
    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
    }

    // 如果一个 bean 被包含在非 singleton 的 bean 中,那么这个 bean 也不能是 singleton 的
    // 这里会对其进行修正
    if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
    mbd.setScope(containingBd.getScope());
    }
  8. 最后,就是将处理好的 MergedBeanDefinition 放入到缓存中,以便后续使用

    1
    2
    3
    4
    // 放到缓存中
    if (containingBd == null && isCacheBeanMetadata()) {
    this.mergedBeanDefinitions.put(beanName, mbd);
    }

进行必要的检查

若 bean 定义为 abstract 的,则直接抛出异常结束流程

1
2
3
4
5
6
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}

DependsOn 处理

若定义了 DependOn (依赖的 bean),则注册依赖关系,并且通过 getBean 方法触发这些 bean 的注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 方法触发所依赖的 bean 进行初始化
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

Singleton bean 获取

若为 Singleton Bean

1
if (mbd.isSingleton())

则通过 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法获取,这里会注册一个 ObjectFactory 用于获取 bean 实例,它的实质是调用 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 方法。

1
2
3
4
5
6
7
8
9
10
11
12
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;
}
});

获取到的 bean 可能是一个 FactoryBean,而由 beanName 指定的、实际要获取的可能是由 FactoryBean 创建的 bean,因此还需要进一步处理

1
2
3
// 如果 sharedInstance 不是 FactoryBean 就直接返回。否则,如果 beanName 表示要获取的就是 FactoryBean
// 本身,也直接返回。否则,通过 FactoryBean 创建对应的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// factoryBean校验:如果 bean name 表示要获取的是一个 FactoryBean,但是给定的 bean 实例既不是 NullBean,
// 也不是 FactoryBean 类型的实例,则直接抛出异常
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}

// beanInstance 可能是一个普通的 bean,也可能是一个 FactoryBean
// 如果不是 FactoryBean 则直接返回结果
// 否则,如果bean的名字带&符号,就是说要获取FactoryBean,也直接返回结果
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}

// 否则,要根据FactoryBean生成所需的bean对象
Object object = null;
if (mbd == null) {
// 从FactoryBean创建的Singleton Bean缓存中取bean对象
object = getCachedObjectForFactoryBean(beanName);
}

// 缓存中未取到
if (object == null) {
// 走到了这里,说明入参中的 beanInstance 是一个 FactoryBean,可直接强转
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

// 获取 merged bean definition
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}

// 是否为合成的,也就是说不是spring自己定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());

// 委托 FactoryBeanRegistrySupport 处理,通过 FactoryBean 创建实例
// 如果是合成的则不需要后处理
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

Prototype bean 获取

创建前要设置正在创建的状态,防止循环引用时会用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}

与 singleton 类型不同的是,这里是直接调用 createBean 创建实例。这是因为不需要对 prototype 类型的 bean 进行缓存,每次调用都需要创建新的实例。

相关流程如下,这里也需要对 FactoryBean 进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 设置正在创建的状态
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 清除正在创建的状态
afterPrototypeCreation(beanName);
}

// 如果 sharedInstance 不是 FactoryBean 就直接返回。否则,如果 beanName 表示要获取的就是 FactoryBean
// 本身,也直接返回。否则,通过 FactoryBean 创建对应的实例
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

其他 scope 的 bean 获取

与 singeton 类型 bean 的获取类似,区别是创建不是交给 DefaultSingletonBeanRegistry 处理,而是交给对应的 Scope 处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 比如scope是SessionScope,就提供createBean的工厂,具体何时创建就交给scope来处理
Object scopedInstance = scope.get(beanName, () -> {
// 设置正在创建的状态
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
// 清除正在创建的状态
afterPrototypeCreation(beanName);
}
});

// 如果 sharedInstance 不是 FactoryBean 就直接返回。否则,如果 beanName 表示要获取的就是 FactoryBean
// 本身,也直接返回。否则,通过 FactoryBean 创建对应的实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}

类型处理

若指定了 requiredType,并且获取到的 bean 实例类型不匹配,则需要对类型进行转换操作。

这里首先要拿到 TypeConverter

1
2
3
4
5
6
7
8
9
10
11
12
13
public TypeConverter getTypeConverter() {
TypeConverter customConverter = getCustomTypeConverter();
if (customConverter != null) {
return customConverter;
}
else {
// Build default TypeConverter, registering custom editors.
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.setConversionService(getConversionService());
registerCustomEditors(typeConverter);
return typeConverter;
}
}

然后尝试对类型进行转换

1
2
3
4
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}

整体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 最后检查下类型是否匹配
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 类型不一致,那就尝试转换下
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}

时序图

流程图

获取 Spring bean 的主要流程如下:

image-20200403012230353

0%