Spring容器原始Bean是如何创建的?

以下内容基于 Spring6.0.4 。
这个话题其实非常庞大,我本来想从 getBean 方法讲起,但一想这样讲完估计很多小伙伴就懵了,所以我们还是一步一步来,今天我主要是想和小伙伴们讲讲 Spring 容器创建 Bean 最最核心的 createBeanInstance 方法,这个方法专门用来创建一个原始 Bean 实例 。
这里就以 Spring 源码中方法的执行顺序为例来和小伙伴们分享 。
1. doCreateBean
AbstractAutowireCapableBeanFactory#doCreateBean 就是 Bean 的创建方法,但是 Bean 的创建涉及到的步骤非常多,包括各种需要调用的前置后置处理器方法,今天我主要是想和大家聊聊单纯的创建 Bean 的过程,其他方法咱们后面文章继续 。
在 doCreateBean 方法中,有如下一行方法调用:
protectedObject doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throwsBeanCreationException {
// Instantiate the bean.
BeanWrApper instanceWrapper = null;
if(mbd.isSingleton) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if(instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance;
//...
returnexposedObject;
}
createBeanInstance 这个方法就是真正的根据我们的配置去创建一个 Bean 了 。
2. createBeanInstance
先来看源码:
protectedBeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if(beanClass != null&& !Modifier.isPublic(beanClass.getModifiers) && !mbd.isNonPublicAccessAllowed) {
thrownewBeanCreationException(mbd.getResourceDeion, beanName,
"Bean class isn't public, and non-public access not allowed: "+ beanClass.getName);
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier;
if(instanceSupplier != null) {
returnobtAInFromSupplier(instanceSupplier, beanName);
}
if(mbd.getFactoryMethodName != null) {
returninstantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
booleanresolved = false;
booleanautowireNecessary = false;
if(args == null) {
synchronized(mbd.constructorArgumentLock) {
if(mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if(resolved) {
if(autowireNecessary) {
returnautowireConstructor(beanName, mbd, null, null);
}
else{
returninstantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if(ctors != null|| mbd.getResolvedAutowireMode == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues || !ObjectUtils.isEmpty(args)) {
returnautowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors;
if(ctors != null) {
returnautowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
returninstantiateBean(beanName, mbd);
}
这里就是核心的 Bean 的创建方法了,因此这个方法我来和大家详细分析一下 。
2.1 resolveBeanClass
这个方法是用来解析出来当前的 beanClass 对象,它的 核心逻辑就是根据我们在 XML 文件中配置的类的全路径,通过反射加载出来这个 Class:
@Nullable
protectedClass<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throwsCannotLoadBeanClassException {
if(mbd.hasBeanClass) {
returnmbd.getBeanClass;
}
returndoResolveBeanClass(mbd, typesToMatch);
}
首先会调用 mbd.hasBeanClass 方法去判断是否已经通过反射加载出来 beanClass 了,如果加载出来了就直接返回,没有加载的话,就继续执行下面的 doResolveBeanClass 去加载 。

什么时候会走 if 这条线呢?松哥举一个例子,如果我们设置某一个 Bean 的 Scope 是 prototype 的话,那么当第二次获取该 Bean 的实例的时候,就会走 if 这条线 。
@NullableprivateClass<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throwsClassNotFoundException {
//...
String className = mbd.getBeanClassName;
if(className != null) {


推荐阅读