Skip to content

createBeanInstance源码解析

一、createBeanInstance的核心作用

createBeanInstance的主要职责是:根据RootBeanDefinition(合并后的bean定义),选择合适的实例化策略(工厂方法、构造函数注入、默认构造函数),创建bean的原始实例

它的输入是:

  • beanName:bean的名称;
  • mbd:合并后的RootBeanDefinition(包含bean的类信息、工厂方法、构造函数参数等);
  • args:显式传入的构造函数/工厂方法参数(如getBean("beanName", args)中的args)。

输出是:bean的原始实例(未进行依赖注入和初始化)。

二、createBeanInstance的源码流程剖析

我们直接看AbstractAutowireCapableBeanFactory中的createBeanInstance方法源码(Spring 5.3.x版本),并分步骤解析:

java
protected Object createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 1. 解析bean的Class对象(从mbd中加载,若未解析则用ClassLoader加载)
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }

    // 2. 处理InstanceSupplier(Spring 5.0+新增,优先用供应商提供实例)
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return instanceSupplier.get();
    }

    // 3. 处理工厂方法(若有factoryMethodName,用工厂方法实例化)
    if (mbd.hasFactoryMethod()) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // 4. 处理构造函数注入(无工厂方法时进入)
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            // 4.1 检查缓存的构造函数(避免重复解析)
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        // 4.2 使用缓存的构造函数:若需要自动装配,调用autowireConstructor;否则用默认构造函数
        return autowireNecessary ? autowireConstructor(beanName, mbd, null, null) : instantiateBean(beanName, mbd);
    }

    // 4.3 调用BeanPostProcessor获取候选构造函数(如@Autowired标注的构造函数)
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        // 4.4 有候选构造函数/需要构造函数自动装配/有参数,调用autowireConstructor
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 5. 无任何特殊配置,用默认无参构造函数实例化
    return instantiateBean(beanName, mbd);
}

步骤1:解析bean的Class对象

resolveBeanClass方法从mbd中获取bean的Class对象(若mbdbeanClass是字符串,会用BeanFactoryClassLoader加载)。同时检查类的访问权限:若类不是public且未设置nonPublicAccessAllowed(允许非公共类实例化),则抛出异常。

步骤2:处理InstanceSupplier(优先度最高)

InstanceSupplier是Spring 5.0引入的函数式实例供应商,用于直接提供bean实例。例如:

  • 使用@Bean(supplier = MyBean::new)标注的方法;
  • 通过BeanDefinition.setInstanceSupplier(() -> new MyBean())设置。

instanceSupplier不为空,直接调用get()方法获取实例,跳过后续所有步骤。这是最灵活的实例化方式,常用于动态创建bean。

步骤3:处理工厂方法(factoryMethod

mbdfactoryMethodName不为空(即配置了factory-method),则调用instantiateUsingFactoryMethod方法,通过工厂方法实例化bean。

工厂方法分为两类:

  • 静态工厂:工厂方法是静态的(如MyFactory.createBean()),无需工厂bean实例;
  • 实例工厂:工厂方法是实例方法(如myFactory.createBean()),需要先实例化工厂bean(factory-bean配置)。

instantiateUsingFactoryMethod的核心逻辑(由ConstructorResolver实现):

  1. 解析工厂bean名称(factoryBeanName)和工厂方法名称(factoryMethodName);
  2. 若为实例工厂,先获取工厂bean实例(通过getBean(factoryBeanName));
  3. 解析工厂方法的参数(优先用args,否则用mbdconstructorArgumentValues);
  4. 查找匹配的工厂方法(根据方法名称和参数类型);
  5. 调用工厂方法(静态方法用Class.invoke,实例方法用工厂bean实例invoke)。

例子

xml
<!-- 静态工厂 -->
<bean id="myBean" class="com.example.MyFactory" factory-method="createStaticBean"/>

<!-- 实例工厂 -->
<bean id="myFactory" class="com.example.MyFactory"/>
<bean id="myBean" factory-bean="myFactory" factory-method="createInstanceBean"/>

步骤4:处理构造函数注入(核心逻辑)

若没有工厂方法,进入构造函数注入流程。这是最常见的实例化方式(如@Autowired标注的构造函数)。

子步骤4.1:检查缓存的构造函数

mbd中的resolvedConstructorOrFactoryMethod缓存了之前解析过的构造函数(或工厂方法),constructorArgumentsResolved标记参数是否已解析。若有缓存,直接使用缓存的构造函数,避免重复解析。

子步骤4.2:获取候选构造函数(BeanPostProcessor扩展点)

determineConstructorsFromBeanPostProcessors方法调用**InstantiationAwareBeanPostProcessor**的postProcessCandidateConstructors方法,获取候选构造函数。例如:

  • AutowiredAnnotationBeanPostProcessor:扫描@Autowired@Value标注的构造函数;
  • CommonAnnotationBeanPostProcessor:扫描@Resource标注的构造函数(较少用)。

例子

java
@Component
public class MyBean {
    private final AnotherBean anotherBean;

    // @Autowired标注的构造函数会被作为候选
    @Autowired
    public MyBean(AnotherBean anotherBean) {
        this.anotherBean = anotherBean;
    }
}

子步骤4.3:选择并调用构造函数

若有候选构造函数(ctors != null)、需要构造函数自动装配(mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR)、有构造函数参数值(mbd.hasConstructorArgumentValues())或显式传入args,则调用autowireConstructor方法:

  1. 选择最合适的构造函数:根据候选构造函数、参数数量/类型匹配,选择最优构造函数(如参数数量最多的、@Autowired(required=true)的);
  2. 解析构造函数参数:参数值来源包括:
    • 显式传入的argsgetBean时的参数);
    • mbdconstructorArgumentValues(XML配置的<constructor-arg>);
    • 自动装配(根据参数类型从BeanFactory中查找bean);
    • @Value注解解析(从配置文件或环境变量中获取值);
  3. 调用构造函数:用Constructor.newInstance(args)实例化bean。

步骤5:默认无参构造函数实例化

若以上步骤均不满足(无工厂方法、无候选构造函数、无参数),则调用instantiateBean方法,使用默认无参构造函数实例化bean。

instantiateBean的核心逻辑:

  • 使用BeanUtils.instantiateClass(beanClass)(反射调用无参构造函数);
  • 若需要CGLIB代理(如@Configuration的bean、scope=prototype且有AOP拦截),则用CGLIB生成子类实例(SimpleInstantiationStrategyinstantiateWithCglib方法)。

三、关键扩展点与机制

1. InstantiationAwareBeanPostProcessor(实例化前扩展)

InstantiationAwareBeanPostProcessor是影响实例化的核心扩展接口,其postProcessBeforeInstantiation方法在createBeanInstance之前调用,若返回非null值,则跳过后续实例化步骤,直接使用该返回值作为bean实例。例如:

  • AOP的AnnotationAwareAspectJAutoProxyCreator:在实例化前检查是否需要代理,若需要则返回代理对象;
  • 自定义InstantiationAwareBeanPostProcessor:用于动态生成bean实例(如代理、 mock)。

例子

java
@Component
public class MyInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanClass == MyBean.class) {
            // 返回代理对象,跳过后续实例化
            return Proxy.newProxyInstance(beanClass.getClassLoader(), new Class[]{MyBean.class}, (proxy, method, args) -> {
                System.out.println("Before method: " + method.getName());
                return method.invoke(new MyBean(), args);
            });
        }
        return null;
    }
}

2. 实例化策略(InstantiationStrategy

InstantiationStrategy是实例化的策略接口,默认实现是SimpleInstantiationStrategy,支持两种实例化方式:

  • 反射实例化:用于无参构造函数或构造函数注入(BeanUtils.instantiateClass);
  • CGLIB实例化:用于需要代理的bean(如@Configuration的bean),通过CGLIB生成子类,添加无参构造函数(若原类没有),并设置方法拦截器。

@Configuration的bean为什么需要CGLIB?
@Configuration的bean会被CGLIB代理,目的是防止@Bean方法重复实例化。例如:

java
@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean(anotherBean()); // 若没有CGLIB代理,anotherBean()会调用普通方法,重复实例化
    }

    @Bean
    public AnotherBean anotherBean() {
        return new AnotherBean();
    }
}

CGLIB代理会将anotherBean()方法拦截,改为从BeanFactory中获取已实例化的AnotherBean,避免重复创建。

3. 构造函数选择逻辑

当有多个候选构造函数时,Spring会按以下优先级选择:

  1. @Autowired(required=true)标注的构造函数:必须存在且参数可解析;
  2. 参数数量最多的构造函数:优先匹配参数数量多的构造函数;
  3. 参数类型匹配的构造函数:根据参数类型从BeanFactory中查找匹配的bean。

例子

java
@Component
public class MyBean {
    // 候选构造函数1:参数数量2
    @Autowired
    public MyBean(AnotherBean anotherBean, String message) { ... }

    // 候选构造函数2:参数数量1
    @Autowired(required=false)
    public MyBean(AnotherBean anotherBean) { ... }

    // 候选构造函数3:无参(默认)
    public MyBean() { ... }
}

AnotherBeanmessage@Value解析)均存在,Spring会选择构造函数1;若message不存在,会选择构造函数2required=false);若均不存在,选择构造函数3

四、常见问题与解决方案

1. NoSuchMethodException(无此方法异常)

原因:构造函数/工厂方法的参数数量或类型与mbd中的配置不匹配。
解决方案

  • 检查mbdconstructorArgumentValuesfactoryMethodArguments是否正确;
  • 检查显式传入的args是否与构造函数/工厂方法的参数匹配;
  • 确保@Autowired标注的构造函数参数可解析(如AnotherBean已被实例化)。

2. BeanCreationException(bean创建异常):无默认构造函数

原因:bean类没有无参构造函数,且未配置构造函数注入或工厂方法。
解决方案

  • 添加无参构造函数(若允许);
  • 配置构造函数注入(如@Autowired标注有参构造函数);
  • 使用工厂方法实例化。

3. @Autowired构造函数未被调用

原因AutowiredAnnotationBeanPostProcessor未被注册(如未启用组件扫描或@EnableAutowired)。
解决方案

  • 确保@ComponentScan扫描到MyBean所在的包;
  • 确保@EnableAutowiredcontext:annotation-config已配置(Spring Boot自动启用)。

五、总结

createBeanInstance是Spring bean实例化的核心入口,其流程可概括为:

  1. 优先使用InstanceSupplier(最灵活);
  2. 处理工厂方法(静态/实例工厂);
  3. 处理构造函数注入@Autowired、自动装配);
  4. 默认无参构造函数(兜底方案)。

通过InstantiationAwareBeanPostProcessorInstantiationStrategy等扩展点,Spring允许开发者自定义实例化过程,满足各种复杂需求(如代理、动态创建bean)。深入理解createBeanInstance的源码,有助于解决bean实例化过程中的问题,提升对Spring容器的认知。

参考资料

  • Spring Framework 5.3.x源码(AbstractAutowireCapableBeanFactoryConstructorResolver);
  • 《Spring源码深度解析》(郝佳);
  • Spring官方文档(Bean Instantiation部分)。