知識庫 / Spring RSS 訂閱

程序化 Bean 註冊機制及 BeanRegistrar 在 Spring 中的應用

Spring
HongKong
10
10:42 AM · Dec 06 ,2025

1. 概述

Spring beans 通常通過註解(如 @Component@Bean)進行聲明式註冊。但是,在某些情況下,我們可能需要比程序註冊提供更多的靈活性,例如基於屬性註冊 bean。

Spring 7 引入了 BeanRegistrar 作為一項強大的新特性。

在本教程中,我們將探討 BeanRegistrar 為什麼是一個受歡迎的補充,它與舊的註冊 bean 的方式相比如何,以及如何在 Java 和 Kotlin 項目中使用它。

2. 我們為什麼需要新東西

在 Spring 7 之前,我們已經可以通過 BeanDefinitionRegistryPostProcessor 類型程序化地註冊 Bean:

@Configuration
public class BeanRegistrationsSpring6Configuration {
    @Bean
    BeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor() {
        return new BeanDefinitionRegistryPostProcessor() {
            @Override
            public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
                var beanDefinition = new GenericBeanDefinition();
                beanDefinition.setBeanClass(MyService.class);
                beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
                registry.registerBeanDefinition("myService", beanDefinition);
            }

            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                // No-op
            }
        };
    }
}

雖然具有靈活性,但也存在一些缺點:

  • 它冗餘且低級。
  • 難以閲讀和測試。
  • 不適合本機圖像(AOT)場景。

3. 新的 BeanRegistrar 類型

BeanRegistrar 是一個功能接口,它允許我們以一種乾淨、聲明式和原生兼容的方式註冊 Bean。 下面的示例使用 BeanRegistrar 將一個類型為 MyService 的 Bean 註冊,並使用默認設置,以及另一個名為 “myService2” 的 Bean,具有原型作用域和程序化惰性初始化:

@Configuration
@Import(BeanRegistrationsConfiguration.MyBeanRegistrar.class)
public class BeanRegistrationsConfiguration {
    static class MyBeanRegistrar implements BeanRegistrar {
        @Override
        public void register(BeanRegistry registry, Environment env) {
            registry.registerBean(MyService.class);
            registry.registerBean("myService2", MyService.class, spec -> spec
                .prototype()
                .lazyInit()
                .primary()
            );
        }
    }
}

我們需要意識到不能使用 @Bean 風格來定義 BeanRegistrar。 而是應該使用 @Import,因為 Bean 必須在 Spring 的配置處理期間被發現。

4. Kotlin DSL 支持

對於 Kotlin,我們可以使用 BeanRegistrarDsl 以獲得一流的支持。相同的示例將變為如下所示:

@Configuration
@Import(BeanRegistrationsConfiguration.MyBeanRegistrar::class)
class BeanRegistrationsConfiguration {
    class MyBeanRegistrar : BeanRegistrarDsl({ 
        registerBean<MyService>() 
        registerBean( name = "myService2", prototype = true, lazyInit = true ){
            MyService()
        }
    })
}

5. 結論

在本文中,我們瞭解到 BeanRegistrar 是一個允許我們以簡潔、聲明式和原生兼容的方式註冊 Bean 的特性。

關於該特性的原始討論可以在 Spring Framework 項目的 GitHub 倉庫 中找到。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.