[英]How can I disable creating bean with @Component annotation in Spring?
I have some common interface for refactoring logic in my project.我的项目中有一些用于重构逻辑的通用接口。 It looks about like this:
它看起来像这样:
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();
}
And than, when I need to write some refactoring - I implement this interface with methods, mark class like @Component
, and Spring in loop evaluate each interface implementation and register it in database.然后,当我需要编写一些重构时 - 我用方法实现这个接口,标记类
@Component
,并且 Spring 循环评估每个接口实现并将其注册到数据库中。 But we have a lot of refactors (every year - 200-300 new).但是我们有很多重构(每年 - 200-300 个新)。 It's hard to disable old implementations manualy, and we have a lot of beans in our spring-context.
手动禁用旧的实现很难,而且我们的 spring 上下文中有很多 bean。 Can we do something, for example, use some annotation - which will disable component creation by some condition?
我们可以做些什么,例如,使用一些注释——这将在某些条件下禁用组件创建?
For example:例如:
@Component
@Enabled(YEAR.2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
And this annotation will work like this (a pseudocode):这个注解会像这样工作(伪代码):
if (YEAR.2020) {
create bean -> new CustomRefactor()
}
And when it will be YEAR.2021
- we will have no beans from YEAR.2020
in spring-context.什么时候是
YEAR.2021
- 在春季背景下,我们将没有来自YEAR.2020
bean。
Use the annotation @Profile
that makes application configuration and beans available in certain environments.使用注释
@Profile
使应用程序配置和 bean 在某些环境中可用。
You can find more at Spring Boot 2.4.0 reference documentation: 3. Profiles您可以在Spring Boot 2.4.0 参考文档中找到更多信息:3. Profiles
Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments.
Spring Profiles 提供了一种分离应用程序配置部分并使其仅在某些环境中可用的方法。 Any @Component, @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded
任何@Component、@Configuration 或@ConfigurationProperties 都可以用@Profile 标记以限制加载时
Consider each year as a separate environment.将每年视为一个单独的环境。
@Component
@Profile("2020")
public class CustomRefactor2020 implements RefactorAwareEntryPoint {
// Code implementation
}
@Component
@Profile("2021")
public class CustomRefactor2021 implements RefactorAwareEntryPoint {
// Code implementation
}
In addition to the answers provided by our colleagues, consider the feature of spring called "Stereotype annotations".除了我们同事提供的答案,请考虑 spring 称为“Stereotype annotations”的特性。 This is how well-known annotations like
@Service
are defined in spring.这就是像
@Service
这样著名的注解在 spring 中定义的方式。
In general, the fact that you mark your class with @Component
annotation allows you to load the class as a spring bean because the annotated class becomes a subject to a process called "component scanning" - a process happens when you start the application context.通常,使用
@Component
批注标记类这一事实允许您将该类作为 spring bean 加载,因为带批注的类成为称为“组件扫描”过程的主题 - 当您启动应用程序上下文时会发生一个过程。
Since spring 4 there is a conditional interface that basically makes possible implementing a logic similar to what you refer to as @Enabled(YEAR.2020)
.从 spring 4 开始,有一个条件接口基本上可以实现类似于您所说的
@Enabled(YEAR.2020)
的逻辑。
You might use a built-in "@ConditionalOnProperty" to map the 2020 year to property or even implement a custom conditional logic .您可以使用内置的“@ConditionalOnProperty”将 2020 年映射到属性,甚至实现自定义条件逻辑。 I'll assume that you've implemented a custom conditional as
@ConditionalOnYear
我假设您已将自定义条件实现为
@ConditionalOnYear
Now, what's interesting (and this is a "stereotype" feature that I've mentioned at the beginning of the post) is that you may create your own "component" annotation with a custom "conditional" logic and use it "as if" its a regular 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
}
You can also improve that by clever usage of @AliasFor
annotation to be something like:您还可以通过巧妙地使用
@AliasFor
注释来改进它,例如:
@SinceYearComponent(2020)
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
But this is kind of out of scope for this question - so I just mention a direction here.但这有点超出了这个问题的范围 - 所以我在这里只提到一个方向。
Of course, it's possible to merely use two annotations as you've suggested even without this "Stereotype" annotation feature:当然,即使没有此“定型”注释功能,也可以仅使用您建议的两个注释:
@Component
@SinceYear(2020) // a custom conditional
public class CustomRefactor implements RefactorAwareEntryPoint {
// Code implementation
}
Check out the BeanFactoryPostprocessor interface.查看 BeanFactoryPostprocessor 接口。 Probably you can remove a bean before it's creation.
可能您可以在创建 bean 之前将其删除。
Else you might implement your own BeanFactory and create the ApplicationContext with your implementation.否则,您可能会实现自己的 BeanFactory 并使用您的实现创建 ApplicationContext。
您可以使用 spring boot 提供的 excludeFilter 注释。
@Profile
annotation to enable/disable profiles.@Profile
注释来启用/禁用配置文件。excludeFilter
excludeFilter
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.