在库中定义 Spring bean 并将它们从 ComponentScan 中排除

问题描述

我正在为两个应用程序 A 和 B 编写一个库。应用程序 A 使用 XML 定义 bean(没有组件扫描),而 B 使用注释和组件扫描。我想让库定义一些 A 和 B 都可以包含的 bean。但是,A 和 B 应该在特定 Spring 配置文件中启动它们时包含这些 bean(假设 dplyr::arrange)。

TLDR 问题是:有没有办法在不引用库中的 df %>% dplyr::group_by(Site_name) %>% dplyr::summarise(n = sum(Race %in% "Missing"),perc = round(n/n()*100)) %>% dplyr::arrange(perc) %>% ggplot(aes(Site_name,perc)) + geom_col(position = 'dodge',fill = "#0000FF",stat="identity") + coord_flip() + geom_text( aes(label=perc),vjust=0,color="black",position = position_dodge(0.9),size=3.5 ) 并且不必从 B 的组件扫描中明确排除库的情况下执行上述操作?

目前,库中的bean被定义为@Configuration类中的@Bean方法,如下所示:

my_profile

现在在应用程序 A 中,在 XML 中,我可以这样做:

my_profile

这行得通。 在使用注释的应用程序 B 中,我希望做这样的事情:

@Configuration
open class LibraryConfig {
  @Bean
  open fun libraryBean() = ...
}

但是由于LibraryConfig 也是用@Configuration 注释的,它会总是被组件扫描发现。所以这种使其有条件的方法不起作用。

我考虑过的方法

  1. 只需将配置文件包含在 LibraryConfig 的 @Profile 中。我不想这样做,因为图书馆不应该知道其消费者的个人资料。
  2. 从项目 B 的@ComponentScan 中明确排除 LibraryConfig。这里的缺点是我们也有项目 C D 和 E,它们使用 <beans profile="my_profile"> <bean class="com.package.LibraryConfig" /> </beans> 。无论如何,我希望能够将库包含在那里,而不必明确排除其中的一部分。

所以我正在寻找一种方法来创建一个只能显式包含的“配置”类。或者任何其他优雅的方式来做上述事情。可以吗?

解决方法

可能有一些方法可以从项目 A 或 B 的组件扫描中排除库包,而无需明确说明要排除该包。

为您的库使用不同的包根目录
最直接的选择是为库使用与项目使用不同的包根目录。由于@SpringBootApplication注解是用@ComponentScan元注解,如果@ComponentScan的属性basePackageClassesbasePackages没有指定,注解的包名类作为根包用于组件扫描 (source):

配置用于@Configuration 类的组件扫描指令。提供与 Spring XML 的 context:component-scan 元素并行的支持。可以指定 basePackageClasses() 或 basePackages()(或其别名 value())来定义要扫描的特定包。如果没有定义特定的包,将从声明该注解的类的包开始扫描。

例如,如果 @SpringBootApplication 注释的根类位于包 com.example.somepackage 中:


package com.example.somepackage;

@SpringBootApplication
public class DemoApplication {
    ...
}

基础包根 com.example.somepackage 将用作组件扫描的根。使用 com.example.library 而不是 com.example.somepackage.library 应该将库排除在组件扫描中。

利用库中的 ConditionalOn 注释
如果上述方法不起作用并且在组件扫描过程中仍然自动包含配置,则与使用配置文件相比,侵入性稍低的方法是在您的配置类中添加 @ConditionalOnX 注释,例如:

ConditionalOnProperty

@Configuration
@ConditionalOnProperty(prefix = "yourlibrary",name = "enabled",havingValue="true")

依赖库的项目现在需要包含属性 yourlibrary.enabled=true

有关多个 @ConditionalOn 注释的更多信息可以在 here 中找到。