hexon
发布于 2026-07-06 / 2 阅读
0

16、Spring6新特性:BeanFactoryInitializer机制底层源码解析

在阅读refresh#finishBeanFactoryInitialization方法时我看到了一段代码:

// Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.  
// Spring6.2新特性  
String[] initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);  
for (String initializerName : initializerNames) {  
    beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);  
}

BeanFactory初始化器,在refresh#finishBeanFactoryInitialization中调用,是Spring6.2后一个针对于BeanFactory的扩展点。

/**
 * Callback interface for initializing a Spring {@link ListableBeanFactory}
 * prior to entering the singleton pre-instantiation phase. Can be used to
 * trigger early initialization of specific beans before regular singletons.
 *
 * <p>Can be programmatically applied to a {@code ListableBeanFactory} instance.
 * In an {@code ApplicationContext}, beans of type {@code BeanFactoryInitializer}
 * will be autodetected and automatically applied to the underlying bean factory.
 *
 * @author Juergen Hoeller
 * @since 6.2
 * @param <F> the bean factory type
 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons()
 */
public interface BeanFactoryInitializer<F extends ListableBeanFactory> {
​
    /**
     * Initialize the given bean factory.
     * @param beanFactory the bean factory to bootstrap
     */
    void initialize(F beanFactory);
​
}

注释的意思:

  • 在进入单例预实例化阶段之前,用于初始化 Spring ListableBeanFactory 的回调接口。

  • 可用于在常规单例 Bean 之前,触发特定 Bean 的提前初始化。

  • 可以编程方式应用于 ListableBeanFactory 实例。

  • ApplicationContext 中,类型为 BeanFactoryInitializer 的 Bean 会被自动检测,并自动应用于底层的 BeanFactory。

具体用法:

@Component  
public class MyBeanFactoryInitializer implements BeanFactoryInitializer<DefaultListableBeanFactory> {  
    @Override  
    public void initialize(DefaultListableBeanFactory beanFactory) {  
       // 在这里可以让某些Bean的创建过程提前  
       beanFactory.getBean("userService");  
    }  
}
@Component  
@Lazy  
public class UserService {  
  
    @PostConstruct  
    public void test() {  
        System.out.println("test...");  
    }  
}
public class Main {  
    public static void main(String[] args) {  
       AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();  
       applicationContext.register(MyConfig.class);  
  
       applicationContext.refresh();  
    }  
}

UserService是非懒加载的单例Bean,我们也可以在容器启动完成后就自动触发它的初始化。

思考:

1、BeanFactoryInitializer 也可以修改 BeanDefinitionDefaultListableBeanFactory它继承了ConfigurableListableBeanFactory,因此也可以获取BeanDefinition然后调用setXxx,还可以注册和移除BeanDefinition。个人觉得在这里修改BeanDefinition反而更加确定,因为执行时机是在非懒加载单例Bean实例化之前。但是官方并不推荐,而且有点故意隐藏的操作BeanDefinition的API的意思,BeanFactoryInitializer的泛型必须是ListableBeanFactory类型,看看ListableBeanFactory的实现就知道了。

2、后面还会学习BeanFactoryPostProcessor接口,这个接口里是强烈不建议实例化Bean的,它可能打乱Bean的生命周期,因为BeanPostProcessor还没有注册。BeanFactoryPostProcessor执行时机是还没有任何单例 Bean 被实例化,但BeanFactoryInitializer执行时,有一些内部基础设施 Bean已经实例化了。

官方文档:BeanFactoryPostProcessor 中不应该尝试实例化 Bean,否则会过早触发 Bean 的实例化,导致 BeanPostProcessor 无法正常生效。

3、总之,BeanFactoryInitializer主要作用就是可用于在常规单例 Bean 之前,触发特定 Bean 的提前初始化。

总结:用哪个?

如果你的目标是...

你应该选择...

增删改 BeanDefinition (例如,动态注册Controller、修改作用域、替换实现类)

BeanFactoryPostProcessor (或更精确的 BeanDefinitionRegistryPostProcessor)

设置 BeanFactory 的配置属性 (例如,解决循环依赖、设置TempClassLoader)

BeanFactoryInitializer

注册框架级的 BeanPostProcessor (例如,自定义的注解处理器)

BeanFactoryInitializer

配置 ConversionServicePropertyEditorRegistrar

BeanFactoryInitializer

结论: BeanFactoryInitializer 不是重复的发明,而是一个职责分离、时机正确、性能更优、更安全的专门化扩展点。它让“我想配置工厂”这个需求的代码比用笨重的BeanFactoryPostProcessor来写更加优雅、清晰和健壮。这是Spring框架持续优化其内部可扩展性架构的一个体现。