5

我有一个带有 Spring 容器的项目。假设这个项目被调用my-common-library并使用 namespace my.common。它扫描此命名空间中的所有组件,common-context.xml如下所示

<beans ...>
    <context:component-scan base-package="my.common"/>
</beans>

除其他事项外,此扫描检测使用 注释的类@MyComponent

现在我想尽可能充分地重用这个项目。假设我开始了一个my-client在 namespace 中使用的新项目my.clientmy-client主要由带有注释的组件组成@MyComponent

在理想的世界中,我只需添加依赖项my-common-library,所有@MyComponents 都将被扫描和注册。唯一的问题是新的命名空间对原来的my-common-library.

我知道的一种解决方案是添加一个common-context.xml看起来my-client像的更新

<beans ...>
    <context:component-scan base-package="my.common,my.client"/>
</beans>

这肯定会奏效,但似乎很脆弱。有没有更优雅的解决方案?

4

2 回答 2

15

在我看来,尝试通过组件扫描从库中实现组件注册总是很脆弱。

如果您只是重用代码,我建议显式导入my-common-library依赖项。例如,使用基于 Java 的 Spring 配置:

@Configuration
@ComponentScan("my.common") 
public class MyCommonLibraryConfig {


}

在“我的客户”上:

@Configuration
@Import(MyCommonLibraryConfig.class)
@ComponentScan("my.client") 
public class MyClientConfig {

}

由于my-client总是依赖于my-library,因此最好明确定义依赖关系。

另一方面,如果你真正想要的是实现类似插件系统的东西,那么你将需要使用一些基于包的约定来发现依赖关系,因为使用依赖关系的组件直到运行时才知道它的依赖关系。

在这种情况下,我建议定义一个注册包名称,例如my.plugin,然后依赖插件的组件的 Spring 配置只需要定义组件扫描my.plugin,每个插件只需在同一个包中定义其@Components或它的bean。@Configurationsmy.plugin

如果你想要更多的控制,你可以在组件扫描中添加一个过滤器,这样你就可以只注册带有某个注解的 bean。例如,假设您定义了一个@MyPlugin注解:

@ComponentScan(
   basePackages = {"my.plugin"},
   includeFilters = @ComponentScan.Filter(
      value= MyPlugin.class, 
      type = FilterType.ANNOTATION
   )
)
于 2014-08-20T01:22:31.960 回答
1

我认为 Ricardo Veguilla 提出了不错的选择。但另一种(有时更好)方法是为此目的使用弹簧启动器。您可以在依赖项中的 spring.factories 文件中声明您的 bean,并在主代码之外预配置所需的 bean。

于 2020-12-21T19:22:36.577 回答