我只能通过@ComponentScan 获取另一个@Configuration 吗?

Can I get another @Configuration only through @ComponentScan

我使用的是spring-boot 2.0.4;我有一堆服务,它们有一个共同的配置 class,标有 @Configuration。 我想将其移至具有此 @Configuration 的公共依赖项,并且根据需要,任何微服务都可以使用 @ComponentScan 从依赖项激活此配置。

我已经为@Component classes 做了这个,并且工作正常。我通过将它添加到@ComponentScan 来激活我需要的任何特定组件。如何以类似的方式(根据需要)激活配置。

以下是代码示例:

常用配置:

package abc.department.common.configs.mongo
@Component
public class AbcMongo {
    @Bean
    public MongoTemplate mongoTemplate() {
        // ... create MongoTemplate.
        return createdMongoTemplate;
    }
}

这里是一个 class,它使用了上面的依赖:

@Configuration
@ComponentScan("abc.department.common.configs.mongo")
public class MyServiceConfigs {
}

同样,我想做这样的事情:

package abc.department.common.configs.security.web
@Configuration
@EnableWebSecurity
public class AbcWebSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ... do common configs;
    }
}

现在,如果服务需要网络安全配置,它可能会像:

    @Configuration
  @ComponentScan({"abc.department.common.configs.mongo","abc.department.common.configs.security.web"})
    public class MyServiceConfigs {
    }

@Configuration是指定bean的意思,例如:

@Configuration 
public class MyMongoConfiguration {

    @Bean
    public MongoTemplate mongoTemplate() {
       return new ...
    }
    @Bean
    public MySampleBean mySampleBean(MongoTemplate tpl) {
       return new MySampleBean(tpl);
    }
}

但如果是这样,您为什么还需要使用 @Component(至少对于您创建的 bean)? 配置是 Spring 框架用来加载其他 bean 的特殊 bean,它可以被视为组件扫描的 "substitution"/替代技术。

我相信,如果你有一些加载一堆 "infrastructure beans" 的基础设施配置(如果我没看错的话是共享 jar),那么使用这个 jar 的服务应该只说 "Hey, I want to load this configuration"而不是扫描那个罐子的包装结构内部。为什么我这么认为?

  • 如果您决定将新 bean 添加到基础设施中的新包中,外部服务是否应该更改其代码并定义一个额外的文件夹进行扫描怎么办? - 可能没有。
  • 如果您决定将基础设施转移到另一个包裹怎么办?

现在 Spring 想到了两种简单的方法:

方式一:使用@Import注解

@Configuration  // this is from "shared artifact" 
class MyInfraConfiguration {

}

@Configuration // this is from an "applicative service" that uses the infra jar in dependencies 
@Import(MyInfraConfiguration.class)
class ServiceAConfiguration {
}

方式二:使用Spring工厂机制

第一种方法有一个缺点:您需要知道服务中的基础配置到底是什么。如果您认为这是一个缺点,请考虑使用 spring 个工厂。

Spring factories 允许在一些文件中注册基础配置,这样 spring boot 会自动将它加载到服务一中,你甚至不需要在服务配置,只要在infra jar中添加一个依赖就可以了。

在基础组件中创建:

META-INF/spring.factories

并在此处添加:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycompany.myinfra.whatever.InfraConfiguration

就是这样。 现在,如果您想在基础配置中自定义 bean 的加载,例如仅在某些属性可用时才创建 Mongo 相关模板,您可能需要使用 @Conditional。现在,虽然这超出了这个问题的范围,但我提到这一点是因为结合 spring 工厂,这可以创建一种非常灵活的方式来管理您的配置