如何在 Spring 中禁用使用 @Component 注释创建 bean?

Ant*_*ton 6 java spring spring-annotations spring-boot

我的项目中有一些用于重构逻辑的通用接口。它看起来大约是这样的:

public interface RefactorAwareEntryPoint {

    default boolean doRefactor() {
        if (EventLogService.wasEvent(getEventType())) {
            return true;
        }
        boolean result = doRefactorInternal();
        if (result) {
            EventLogService.registerEvent(eventType);
        }
        return result;
    }

    String getEventType();
    
    boolean doRefactorInternal();
}
Run Code Online (Sandbox Code Playgroud)

然后,当我需要编写一些重构时 - 我使用方法实现此接口,标记类@Component,然后 Spring 循环评估每个接口实现并将其注册到数据库中。但我们有很多重构(每年 - 200-300 个新重构)。手动禁用旧的实现很困难,而且我们的 spring 上下文中有很多 bean。我们可以做一些事情,例如,使用一些注释 - 这将在某些条件下禁用组件创建?

例如:

@Component
@Enabled(YEAR.2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)

这个注释将像这样工作(伪代码):

if (YEAR.2020) {
  create bean -> new CustomRefactor()
}
Run Code Online (Sandbox Code Playgroud)

当它到来时YEAR.2021,我们将不会在 spring-context 中得到任何豆子YEAR.2020

Nik*_*las 8

@Profile使用使应用程序配置和 bean 在某些环境中可用的注释。

您可以在Spring Boot 2.4.0 参考文档中找到更多信息:3. Profiles

Spring Profiles 提供了一种方法来隔离应用程序配置的各个部分,并使其仅在某些环境中可用。任何@Component、@Configuration或@ConfigurationProperties都可以用@Profile标记来限制其加载时间

将每年视为一个单独的环境。

@Component
@Profile("2020")
public class CustomRefactor2020 implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)
@Component
@Profile("2021")
public class CustomRefactor2021 implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)

  • 我们还可以实现 org.springframework.context.annotation.Condition 并使用此条件来为上下文创建 bean。 (2认同)

Mar*_*nik 6

除了我们同事提供的答案之外,请考虑 spring 的一个称为“Stereotype 注解”的功能。这就是 spring 中众所周知的注释的@Service定义方式。

一般来说,使用注释标记类的事实@Component允许您将类作为 spring bean 加载,因为带注释的类成为称为“组件扫描”的过程的主题 - 该过程在您启动应用程序上下文时发生。

从 spring 4 开始,有一个条件接口,基本上可以实现类似于您所指的逻辑@Enabled(YEAR.2020)

您可以使用内置的“@ConditionalOnProperty”将 2020 年映射到属性,甚至实现自定义条件逻辑。我假设您已经实现了一个自定义条件@ConditionalOnYear

现在,有趣的是(这是我在帖子开头提到的“刻板印象”功能)是,您可以使用自定义“条件”逻辑创建自己的“组件”注释并“好像”使用它它是普通豆:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnYear(2020)
@Component
public @interface Year2020OnlyComponent {

    @AliasFor(annotation = Component.class)
    String value() default "";

}
Run Code Online (Sandbox Code Playgroud)
@Year2020OnlyComponent
public class CustomRefactor implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)

您还可以通过巧妙地使用@AliasFor注释来改进它,例如:

@SinceYearComponent(2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)

但这有点超出了这个问题的范围 - 所以我只是在这里提到一个方向。

当然,即使没有这种“Stereotype”注释功能,也可以仅使用您建议的两个注释:

@Component
@SinceYear(2020) // a custom conditional
public class CustomRefactor implements RefactorAwareEntryPoint {
 // Code implementation
}
Run Code Online (Sandbox Code Playgroud)