我有一个带有Spring容器的项目。假设此项目名为my-common-library
,并使用名称空间my.common
。它会扫描此命名空间中的所有组件,如common-context.xml
中所示,如下所示
<beans ...>
<context:component-scan base-package="my.common"/>
</beans>
此扫描会检测用@MyComponent
注释的类。
现在我想尽可能完全重用这个项目。假设我开始在命名空间my-client
中使用的新项目my.client
。 my-client
主要由使用@MyComponent
注释的组件组成。
在理想世界中,我只会添加依赖项my-common-library
,并且将扫描并注册所有@MyComponent
。唯一的问题是原始my-common-library
未知新命名空间。
我知道的一个解决方案是将更新后的common-context.xml
添加到my-client
,看起来像
<beans ...>
<context:component-scan base-package="my.common,my.client"/>
</beans>
这肯定有用,但似乎很脆弱。是否有更优雅的解决方案?
答案 0 :(得分:10)
在我看来,尝试通过组件扫描从库实现组件注册总是很脆弱。
如果您只是重用代码,我建议明确导入my-common-library
依赖项。例如,使用基于Java的Spring配置:
@Configuration
@ComponentScan("my.common")
public class MyCommonLibraryConfig {
}
在'my-client`上:
@Configuration
@Import(MyCommonLibraryConfig.class)
@ComponentScan("my.client")
public class MyClientConfig {
}
由于my-client
始终取决于my-library
,因此最好明确定义依赖关系。
另一方面,如果您真正想要的是实现类似插件系统的东西,那么您将需要使用一些基于包的约定来发现依赖关系,因为使用依赖关系的组件在运行之前不知道它的依赖关系-时间。
在这种情况下,我建议定义一个注册包名称,例如my.plugin
,然后依赖于插件的组件的Spring配置只需要在my.plugin
上定义组件扫描,并且每个插件只需要在同一个@Components
包中定义其@Configurations
或其my.plugin
bean。
如果需要更多控制,可以在组件扫描中添加一个过滤器,以便只注册带有特定注释的bean。例如,假设您定义了@MyPlugin
注释:
@ComponentScan(
basePackages = {"my.plugin"},
includeFilters = @ComponentScan.Filter(
value= MyPlugin.class,
type = FilterType.ANNOTATION
)
)
答案 1 :(得分:1)
我认为 Ricardo Veguilla 提出了不错的选择。但另一种(有时更好)的方法是为此目的使用弹簧启动器。您可以在依赖项内的 spring.factories 文件中声明 bean,并在主代码外预先配置所需的 bean。