java - 尊重非@Primary @Bean 上的@Lazy 注释
问题描述
当Spring配置为使用不同的@Lazy
方法返回标记为.@Bean
@Bean
@Primary
具体来说,我有一个带@Configuration
注释的类,其中有几个@Bean
方法都返回相同的接口。其中许多@Bean
方法是@Lazy
,因为它们联系应用程序当前可能未使用的外部服务。@Primary
bean 不是@Lazy
,因为它查看运行时配置以确定要返回的实现。
这是该配置类的一个人为示例,围绕一个虚构的ThingService
接口:
@Configuration
@ComponentScan(basePackages = { "com.things" })
public class ThingConfiguration {
@Bean
public ThingOptions thingOptions() {
ThingOptions options = new ThingOptions();
options.sharing = true;
return options;
}
@Primary
@Bean
public ThingService primaryThing(ThingOptions options, ApplicationContext context) {
System.out.println("PrimaryThing -- Initialized");
if (options.sharing) {
return context.getBean("OurThing", ThingService.class);
} else {
return context.getBean("YourThing", ThingService.class);
}
}
@Lazy
@Bean(name = "YourThing")
public ThingService yourThing() {
System.out.println("YourThingService -- Initialized");
return new YourThingService();
}
@Lazy
@Bean(name = "OurThing")
public ThingService ourThing() {
System.out.println("OurThingService -- Initialized");
return new OurThingService();
}
}
然后我有一个@Component
依赖于这个接口的@Primary
注解将确保将正确的实现注入到对象中。这是该下游的示例@Component
:
@Component
public class ThingComponent {
private final ThingService thingService;
@Inject
public ThingComponent(ThingService thingService) {
this.thingService = thingService;
}
}
@Lazy
然后我建立了一个小测试,以确保@Primary
所有这些都得到尊重。
public class ThingTest {
@Test
public void TestLazyAndPrimary() {
// Arrange
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(ThingConfiguration.class);
context.refresh();
// Act
ThingComponent component = context.getBean(ThingComponent.class);
// Assert
Assert.assertNotNull(component);
}
}
然而,当我运行这个测试时,我发现它@Lazy
被忽略了。以下文本被发送到控制台:
PrimaryThing -- Initialized
OurThingService -- Initialized
YourThingService -- Initialized
"YourThing"
@Bean
不应该被初始化,因为它是并且没有在运行时通过该方法@Lazy
加载。ApplicationContext.getBean()
然而,当它ThingComponent
被解决时,它会导致在选择平均值之前@Bean
返回一个实现的方法ThingService
被水合。@Primary
如何在不导致所有带注释的非实现被水合@Primary
的情况下,尊重接口的注释实现?@Primary
@Lazy
解决方案
我一直无法阻止@Primary
注释强制对所有返回该接口的方法进行急切的水合@Bean
,即使这些信息似乎可用而无需从排他性的注释中强制水合。我通过对@Bean
方法使用命名约定来解决这个问题。
具体来说,我改变了我的@Primary
注释@Bean
方法,包括name
这样的:
@Configuration
@ComponentScan(basePackages = { "com.things" })
public class ThingConfiguration {
// @Primary -- I don't want someone to accidentally use this without a @Qualifier!
@Bean(name = "PrimaryThingService")
public ThingService primaryThing(ThingOptions options, ApplicationContext context) {
System.out.println("PrimaryThing -- Initialized");
if (options.sharing) {
return context.getBean("OurThing", ThingService.class);
} else {
return context.getBean("YourThing", ThingService.class);
}
}
// ... the rest of the methods removed for clarity ...
}
然后我@Qualifier
在ThingService
被注入的对象上放置了一个@Component
这样的:
@Component
public class ThingComponent {
private final ThingService thingService;
@Inject
public ThingComponent(@Qualifier("PrimaryThingService") ThingService thingService) {
this.thingService = thingService;
}
}
现在,当我重新运行测试时,我得到以下输出:
PrimaryThing -- Initialized
OurThingService -- Initialized
因此,这删除了注释,而不是使用遵循约定的@Primary
命名,绕过 Spring 对非注释方法的过度水化。@Bean
"Primary{Interface}"
@Primary
@Bean
推荐阅读
- python - SQLite 如何动态创建表?
- jenkins - 使用流 DSL 将构建流迁移到管道中
- flutter - 如何在颤动中实现这种形状?
- javascript - 获取 API- res.json() 返回一个 [object][object]
- php - MySQL查询从表2中获取总项目数到表1中的所有者?
- swift - 如何快速更改内容?
- momentjs - 将毫秒传递给 moment() 时如何获取实际的实时日期
- windows - 一个驱动程序可以包装另一个驱动程序以使用 WEBUSB
- android - 如何在android中创建s曲线布局
- java - 如何在 Java 中对用户定义的双向链表进行排序?