我可以覆盖使用类路径扫描定义的spring bean定义吗?

时间:2017-01-04 10:25:16

标签: java spring plugins

我有一个应用程序,它具有一个非常简单的插件体系结构,通过使用spring类路径扫描注册其他行为("安装"插件通过将plugin.jar放在类路径上)。

这适用于注册其他bean,它也适用于注册这样的钩子:

// core.jar:
@Component
class CoreClass {
  public void addListener(Listener listener) { /* ... */ }
}

// plugin.jar
@Component
class Plugin {
  public Plugin(CoreClass coreClass) {
    coreClass.addListener(new PluginListener());
  }
}

然而,有时更换整个bean更合适。这可能如下所示:

// core.jar:
@Component("someBean")
class CoreClass implements CoreInterface {
  @Override
  public void doStuff();
}

// plugin.jar
@Component("someBean")
@Order(HIGHEST_PRECEDENCE)
class Plugin implements CoreInterface {
  @Override
  public void doStuff();
}

在这种情况下,我希望在启动期间通过类路径扫描发现PluginCoreClass,但是应忽略CoreClass,因为bean someBean具有另一个具有更高优先权的定义。

我知道我可以使用XML(<import resource="classpath*:plugin-spring.xml" />)来做到这一点,因为XML允许覆盖定义。但这也可以使用注释吗?

编辑:请注意,我有时会有多个相同类型的bean实例(具有不同的属性),我注入了基于名称的实例。因此,我实际上需要用某个名称覆盖bean。

1 个答案:

答案 0 :(得分:0)

可能使用的解决方案:

<强> @Primary

表示当多个候选者有资格自动装配单值依赖项时,应优先考虑bean。如果只是一个主要的&#39; bean存在于候选者之间,它将是自动装配的值。

此注释在语义上等同于Spring XML中元素的主要属性。

可以在任何直接或间接使用@Component注释的类或使用@Bean注释的方法上使用。

@Configuration  
@ImportResource( { "classpath*:core-spring.xml", "classpath*:plugin-spring.xml" } )  
public class ConfigClass { } 

Alt Actions Docs

或者您可以使用:

ConflictingBeanDefinitionException

我怀疑注释问题不清楚要覆盖哪个顺序,如果你定义了符号相同的名称,你最终会使用@Component spring将不允许你拥有@Bean或{{ 1}}同名。在xml中,您可以管理覆盖顺序,这就是您可以在xml上执行此操作的原因。在注释中你不能这样做。

任何给定的 Spring上下文只能有一个bean用于任何给定的id或名称。对于XML id属性,这由架构验证强制执行。在name属性的情况下,这由Spring的逻辑强制执行。

但是,如果上下文是由两个不同的XML描述符文件构造的,并且两个文件都使用了一个id,那么将会覆盖&#34;覆盖&#34;另一个。确切的行为取决于文件在上下文加载时的顺序。

尽管可能,但不建议这样做。它容易出错且容易出错,如果你更改了一个而不是另一个的ID,你将无法从Spring获得帮助。

但是,如果上下文是由两个不同的XML描述符文件构造的,并且两个文件都使用了一个id,那么将会覆盖&#34;覆盖&#34;另一个。确切的行为取决于文件在上下文加载时的顺序。