如何禁用在 Spring 中使用 @Component 批注创建 bean?
How can I disable creating bean with @Component annotation in Spring?
我的项目中有一些用于重构逻辑的通用接口。它看起来像这样:
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();
}
然后,当我需要编写一些重构时 - 我用方法实现这个接口,标记 class 就像 @Component
,并且 Spring 在循环中评估每个接口实现并注册它在数据库中。
但是我们有很多重构(每年 - 200-300 个新的)。很难手动禁用旧的实现,而且我们的 spring-context 中有很多 bean。
我们可以做点什么吗,例如,使用一些注解——这将在某些情况下禁用组件创建?
例如:
@Component
@Enabled(YEAR.2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
并且此注释将像这样工作(伪代码):
if (YEAR.2020) {
create bean -> new CustomRefactor()
}
什么时候会是 YEAR.2021
- 我们将在 spring-context.
中没有来自 YEAR.2020
的 bean
查看 BeanFactoryPostprocessor 接口。也许您可以在创建 bean 之前删除它。
否则您可以实现自己的 BeanFactory 并使用您的实现创建 ApplicationContext。
您可以使用 spring boot 提供的 excludeFilter 注释。
使用注释 @Profile
使应用程序配置和 bean 在某些环境中可用。
您可以在 Spring Boot 2.4.0 reference documentation: 3. Profiles
找到更多信息
Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component, @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded
将每一年都视为一个单独的环境。
@Component
@Profile("2020")
public class CustomRefactor2020 implements RefactorAwareEntryPoint {
// Code implementation
}
@Component
@Profile("2021")
public class CustomRefactor2021 implements RefactorAwareEntryPoint {
// Code implementation
}
除了我们同事提供的答案之外,请考虑 spring 称为“Stereotype annotations”的功能。这就是在 spring.
中定义像 @Service
这样的 well-known 注释的方式
通常,您使用 @Component
注释标记 class 的事实允许您将 class 作为 spring bean 加载,因为注释 class 成为一个名为“组件扫描”的过程的主题 - 当您启动应用程序上下文时会发生一个过程。
自 spring 4 以来,有一个条件接口,基本上可以实现与您所说的 @Enabled(YEAR.2020)
.
类似的逻辑
您可以使用 built-in“@ConditionalOnProperty”将 2020 年映射到 属性,甚至可以实现 custom conditional logic。我假设您已经将自定义条件实现为 @ConditionalOnYear
现在,有趣的是(这是我在 post 开头提到的“刻板印象”功能)是您可以使用自定义“条件”创建自己的“组件”注释" 逻辑并使用它"就好像"它是一个普通的 bean:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnYear(2020)
@Component
public @interface Year2020OnlyComponent {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Year2020OnlyComponent
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
您还可以通过巧妙地使用 @AliasFor
注释来改进它,例如:
@SinceYearComponent(2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
但这有点超出了这个问题的范围 - 所以我在这里只提到一个方向。
当然,即使没有这个“刻板印象”注释功能,也可以只使用您建议的两个注释:
@Component
@SinceYear(2020) // a custom conditional
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
- 正如其他人所提到的,您始终可以使用
@Profile
注释来
enable/disable 个人资料。
- 另一种选择是
excludeFilter
我的项目中有一些用于重构逻辑的通用接口。它看起来像这样:
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();
}
然后,当我需要编写一些重构时 - 我用方法实现这个接口,标记 class 就像 @Component
,并且 Spring 在循环中评估每个接口实现并注册它在数据库中。
但是我们有很多重构(每年 - 200-300 个新的)。很难手动禁用旧的实现,而且我们的 spring-context 中有很多 bean。
我们可以做点什么吗,例如,使用一些注解——这将在某些情况下禁用组件创建?
例如:
@Component
@Enabled(YEAR.2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
并且此注释将像这样工作(伪代码):
if (YEAR.2020) {
create bean -> new CustomRefactor()
}
什么时候会是 YEAR.2021
- 我们将在 spring-context.
YEAR.2020
的 bean
查看 BeanFactoryPostprocessor 接口。也许您可以在创建 bean 之前删除它。
否则您可以实现自己的 BeanFactory 并使用您的实现创建 ApplicationContext。
您可以使用 spring boot 提供的 excludeFilter 注释。
使用注释 @Profile
使应用程序配置和 bean 在某些环境中可用。
您可以在 Spring Boot 2.4.0 reference documentation: 3. Profiles
找到更多信息Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component, @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded
将每一年都视为一个单独的环境。
@Component
@Profile("2020")
public class CustomRefactor2020 implements RefactorAwareEntryPoint {
// Code implementation
}
@Component
@Profile("2021")
public class CustomRefactor2021 implements RefactorAwareEntryPoint {
// Code implementation
}
除了我们同事提供的答案之外,请考虑 spring 称为“Stereotype annotations”的功能。这就是在 spring.
中定义像@Service
这样的 well-known 注释的方式
通常,您使用 @Component
注释标记 class 的事实允许您将 class 作为 spring bean 加载,因为注释 class 成为一个名为“组件扫描”的过程的主题 - 当您启动应用程序上下文时会发生一个过程。
自 spring 4 以来,有一个条件接口,基本上可以实现与您所说的 @Enabled(YEAR.2020)
.
您可以使用 built-in“@ConditionalOnProperty”将 2020 年映射到 属性,甚至可以实现 custom conditional logic。我假设您已经将自定义条件实现为 @ConditionalOnYear
现在,有趣的是(这是我在 post 开头提到的“刻板印象”功能)是您可以使用自定义“条件”创建自己的“组件”注释" 逻辑并使用它"就好像"它是一个普通的 bean:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ConditionalOnYear(2020)
@Component
public @interface Year2020OnlyComponent {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Year2020OnlyComponent
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
您还可以通过巧妙地使用 @AliasFor
注释来改进它,例如:
@SinceYearComponent(2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
但这有点超出了这个问题的范围 - 所以我在这里只提到一个方向。
当然,即使没有这个“刻板印象”注释功能,也可以只使用您建议的两个注释:
@Component
@SinceYear(2020) // a custom conditional
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
- 正如其他人所提到的,您始终可以使用
@Profile
注释来 enable/disable 个人资料。 - 另一种选择是
excludeFilter