Java配置与组件扫描注释

时间:2017-12-04 21:38:19

标签: spring spring-config

Java配置允许我们在配置文件中管理bean创建。带注释的@Component,与组件扫描一起使用的@Service类也是如此。但是,我担心同时使用这两种机制。

在同一个项目中是否应避免Java配置和带注释的组件扫描?我问,因为在以下情况中结果不清楚:

@Configuration
public class MyConfig {
    @Bean
    public Foo foo() {
        return new Foo(500);
    }
}

...

@Component
public class Foo {
    private int value;

    public Foo() {
    }
    public Foo(int value) {
        this.value = value;
    }
}

...

public class Consumer {
    @Autowired
    Foo foo;

    ...
}

那么,在上述情况下,Consumer会获得一个500值或0值的Foo实例吗?我在本地进行了测试,看起来Java配置的Foo(值为500)是一致的。但是,我担心我的测试不够透彻,无法确定。

真正的答案是什么?在相同类型的@Component bean上使用Java config 组件扫描似乎是一件坏事。

3 个答案:

答案 0 :(得分:1)

通常,在同一应用程序上下文中组件扫描和显式bean定义没有任何问题。我倾向于尽可能使用组件扫描,并使用@Bean方法创建需要更多设置的少数bean。

当您明确创建其类型的bean时,在组件扫描中包含类没有任何好处。组件扫描可以轻松地针对某些类和包。如果你相应地设计你的包,你可以只扫描没有“特殊”bean类的包(或者在扫描时使用更高级的过滤器)。

在这种情况下,我没有找到关于bean定义优先级的任何明确信息。通常会有一个确定性且相当稳定的顺序来处理这些顺序,但是如果没有记录它可能可能在未来的某个Spring版本中发生变化。

答案 1 :(得分:1)

我认为您的担忧更像是由以下用例引起的:

您有一个自定义的spring-starter-library,它具有自己的<div class="hero-container-2"> <span id="contactus"></span> <p><span id="contactus">Itching to ask us a question about the club? Want to pick our brains about training, competing or joining? (We usually react quickly, but it might take us a handful of days to reply).</span></p> <div class="buttom"> <span id="contactus">Contact Us</span> </div> </div>类和@Configuration定义,但如果此库中有@Bean,则需要显式{{ 1}}这些包来自您的服务,因为默认的@Component/@Service(请参见@ComponentScan)将从主类执行组件扫描,直到您应用的所有子包,但外部包图书馆。为此,您只需要在外部库中拥有@ComponentScan定义,并通过应用主类上使用的@SpringBootApplication注释(使用@Bean或使用{ {1}},以防您始终需要使用/注入外部配置。

当然,您可以在该库中使用@EnableSomething,但是在某些情况下显式使用@Import(YourConfigurationAnnotatedClass.class)注释可能会导致意外行为,因此我建议避免这种情况。

因此,要回答您的问题->仅当它们在您的应用程序内部时,您才可以使用两种方法来定义bean,但是应在应用程序外部(例如库)中使用spring.factories来明确定义bean定义。 @Components类。

答案 2 :(得分:0)

在同一个项目中进行Java配置和带批注的组件扫描是完全有效的,因为它们服务于不同的目的。

@Component@Service,@Repository等)用于自动检测和自动配置bean。

@Bean注释用于显式声明单个bean,而不是让Spring自动执行它。

您可以使用@Bean执行以下操作。但是,@Component

无法做到这一点
@Bean
public MyService myService(boolean someCondition) {
    if(someCondition) {
      return new MyServiceImpl1();
    }else{
        return new MyServiceImpl2();
    }
}

还没有真正遇到需要同一类型的bean上的Java配置和组件扫描的情况。

根据spring documentation

  

要声明bean,只需使用@Bean批注注释方法即可。   当JavaConfig遇到这样的方法时,它将执行该方法   并将返回值注册为BeanFactory中的bean。通过   默认情况下,bean名称将与方法名称

相同

所以,按照这个,它返回正确的Foo(值为500)。