简体   繁体   English

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

[英]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 注释。

  1. As mentioned by others you can always use @Profile annotation to enable/disable profiles.正如其他人所提到的,您始终可以使用@Profile注释来启用/禁用配置文件。
  2. Another option is excludeFilter另一种选择是excludeFilter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在没有 spring @Component 或 @Bean 注释的情况下在我的项目中运行不同项目的 servlet-filter - How can I run servlet-filter of a different project in my project without spring @Component or @Bean annotation Spring bean没有使用@Component注释进行自动装配 - Spring bean not autowiring with @Component annotation Spring 3.0注释bean组件扫描 - Spring 3.0 annotation bean Component Scan 我怎样才能告诉Spring扫描给定的注释,而不用@Component注释该注释? - How can I tell Spring to scan for a given annotation without annotating that annotation with @Component? 没有符合条件的 bean,但我添加了 @Component 注释 - No qualifying bean, but I added @Component annotation 如何禁用在IntelliJ IDEA中显示Spring @Value注释的值? - How can I disable showing the value of a Spring @Value annotation in IntelliJ IDEA? 在触发应用程序事件时创建bean时,如何避免Spring中的死锁? - How can i avoid a deadlock in Spring when creating a bean while triggering an application event? 如何在Spring注释配置中为bean指定父级? - How to specify parent for bean in Spring annotation config? 使用Spring,如何将子bean注入父bean? - With Spring, how can I inject a child bean in a parent bean? 使用 @Bean Spring 注释创建 bean 时出现异常 - Getting Exception while creating beans using @Bean Spring annotation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM