Spring Java配置与组件扫描注释

Spring Java配置与组件扫描注释,spring,Spring,Java配置允许我们在配置文件中管理bean的创建。带注释的@组件,@服务与组件扫描一起使用的类也执行相同的操作。然而,我担心同时使用这两种机制 在同一个项目中是否应该避免Java配置和带注释的组件扫描?我这样问是因为在以下情况下,结果不清楚: @Configuration public class MyConfig { @Bean public Foo foo() { return new Foo(500); } } ... @Component p

Java配置允许我们在配置文件中管理bean的创建。带注释的
@组件
@服务
与组件扫描一起使用的类也执行相同的操作。然而,我担心同时使用这两种机制

在同一个项目中是否应该避免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;

    ...
}
那么,在上述情况下,消费者会得到一个值为500或0的Foo实例吗?我已经在本地进行了测试,看起来Java配置的Foo(值为500)是一致创建的。然而,我担心我的测试不够彻底,不能得出结论


真正的答案是什么?在同一类型的@component bean上同时使用Java配置和组件扫描似乎是一件坏事。

在同一项目中使用Java配置和带注释的组件扫描是完全有效的,因为它们服务于不同的目的

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

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

您可以使用
@Bean
执行以下操作。但是,对于
@组件

@Bean
public MyService myService(boolean someCondition) {
    if(someCondition) {
      return new MyServiceImpl1();
    }else{
        return new MyServiceImpl2();
    }
}
我还没有真正遇到需要对同一类型的bean进行Java配置和组件扫描的情况

根据,

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


因此,根据这一点,它返回的是正确的Foo(值为500)。

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

当您显式地创建类类型的bean时,在组件扫描中包含类是没有好处的。组件扫描可以很容易地针对特定的类和包。如果您相应地设计了包,那么您可以只对没有“特殊”bean类的包进行组件扫描(或者在扫描时使用更高级的过滤器)


在这种情况下,我没有找到任何关于bean定义优先级的清晰信息。通常情况下,处理这些数据的顺序是确定的和相当稳定的,但如果没有记录,可能会在将来的Spring版本中发生变化。

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

您有一个定制的spring starter库,它有自己的
@Configuration
类和
@Bean
定义,但是如果此库中有
@Component/@Service
,您将需要从您的服务中显式地
@ComponentScan
这些包,因为默认的
@ComponentScan
(请参见
@springbootplication
)将从主类执行组件扫描,扫描到应用程序的所有子包,但不扫描外部库中的包。为此,您只需在外部库中具有
@Bean
定义,并通过应用程序主库上使用的
@EnableSomething
注释注入这些外部配置ass(使用
@Import(YourConfigurationAnnotatedClass.class)
或使用
spring.factories
,以防总是需要使用/注入外部配置

当然,此库中可以有
@Components
,但在某些情况下显式使用
@ComponentScan
注释可能会导致意外行为,因此我建议避免这种情况


因此,为了回答您的问题->您可以有两种定义bean的方法,仅当它们在您的应用程序内,但bean定义在您的应用程序外(例如库)应该在
@Configuration
类中用
@Bean
显式定义。

我更进一步地说,Java配置的存在只是因为组件扫描。否则XML就更简洁了。(PS:我不是在证明组件扫描是正确的)。@StanislavBashkyrtsev不同意更简洁(您喜欢写出完全限定名吗?),而且XML更容易出错,因为它不像Java那样在键入时进行静态检查IDE@CoderinoJavarino,您喜欢先将依赖项显式地注入到创建bean的方法中,然后注入到该bean的构造函数中吗(如果bean位于不同的上下文类中)?95%是控件间距,所以我不介意,你知道你链接到了古代文档吗?