
BeanRegistrar 接口适用于我们希望以程序化方式向应用上下文注册 Bean 的场景。我们可以不依赖带有 @Bean 方法的 @Configuration 或 @Component,而是使用 BeanRegistry 抽象来动态注册 Bean。
https://docs.spring.io/spring-framework/docs/7.0.0-M3/javadoc-api/org/springframework/beans/factory/BeanRegistrar.html
使用 BeanRegistrar 相比传统的基于注解的 Bean 配置,具有以下优势:
BeanRegistrar 的应用在预编译(ahead-of-time compiled)环境中可以获得更好的性能和兼容性。(参考:Spring Framework Issue 讨论)BeanRegistrar 进行简单的 Bean 注册我们通过一个简单的 GreetingService 示例来演示。我们将使用 BeanRegistrar 动态注册它,而不是使用 @Service 或 @Bean。
public class GreetingService {
privatefinal String greeting;
public GreetingService() {
this("Hello");
}
public GreetingService(String greeting) {
this.greeting = greeting;
}
public String greet(String name) {
return greeting + ", " + name + "!";
}
}
这里,GreetingService 提供了一个可自定义的问候语。
使用 BeanRegistrar 注册 Bean
我们将创建一个配置类,导入一个自定义的注册器。
@Configuration
@Import(GreetingServiceRegistrar.class)
public class AppConfig {
}
class GreetingServiceRegistrar implements BeanRegistrar {
@Override
public void register(BeanRegistry registry, Environment env) {
// 注册默认的 GreetingService
registry.registerBean("greetingService", GreetingService.class);
// 注册一个原型作用域、延迟初始化并带有自定义提供者的 GreetingService
registry.registerBean("customGreetingService", GreetingService.class, spec -> spec
.prototype()
.lazyInit()
.description("Custom GreetingService bean")
.supplier(context -> new GreetingService("Hi there")));
}
}
在这个配置中,我们首先注册了一个名为 greetingService 的默认 GreetingService。然后我们添加了第二个 Bean customGreetingService,它定义为原型作用域(每次请求都创建新实例),配置了延迟初始化(仅在首次使用时实例化),并通过一个自定义工厂提供不同的问候语。
使用已注册的 Bean
一旦 Bean 以程序化方式注册,我们就可以像其他 Spring 管理的 Bean 一样获取和使用它们。一个简单的演示方式是创建一个 CommandLineRunner,从应用上下文中获取 Bean 并执行其逻辑。
@Component
publicclass GreetingRunner implements CommandLineRunner {
privatefinal ApplicationContext context;
public GreetingRunner(ApplicationContext context) {
this.context = context;
}
@Override
public void run(String... args) {
GreetingService defaultService = context.getBean("greetingService", GreetingService.class);
GreetingService customService = context.getBean("customGreetingService", GreetingService.class);
System.out.println(defaultService.greet("Spring Developer"));
System.out.println(customService.greet("Spring Boot User"));
}
}
这个运行器获取默认和自定义的 GreetingService Bean,并调用它们的 greet() 方法。默认 Bean 使用标准构造函数消息,而自定义 Bean 使用其自定义提供者提供的消息。
控制台输出
Hello, Spring Developer!
Hi there, Spring Boot User!
在本文中,我们探讨了如何使用 Spring 的 BeanRegistrar 以程序化方式注册具有不同作用域、延迟初始化和自定义提供者的 Bean。这种方法为开发者提供了对 Bean 注册的细粒度控制,特别适用于注解本身不足以满足需求的高级用例。