首页 > 解决方案 > 如何在保留参数的同时覆盖spring bean?

问题描述

我有两个项目,库和应用程序。库定义了一个 CommonService 接口,我想在应用程序中覆盖它。我使用 Spring XML 进行配置。库代码:

public interface CommonService {
  String service();
}

public class CommonServiceImpl implements CommonService {

  private String message;
  // + getter/setter

  @Override
  public String service() {
    return "Message: " + getMessage();
  }

}

申请代码:

public class OverriddenServiceImpl extends CommonServiceImpl {

  @Override
  public String service() {
    return "Overridden: " + super.service();
  }
}

库配置(lib-config.xml):

  <bean id="commonService" class="spring.context.test.library.CommonServiceImpl">  
    <property name="message" value="Hello!" />
  </bean>

应用程序配置(app-config.xml):

  <import resource="classpath:/lib-config.xml"/>
  <bean id="commonService" 
    class="spring.context.test.application.OverriddenServiceImpl">  
  </bean>

测试:

  @Test
  void testLibraryXML() {
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/lib-config.xml");
    CommonService commonService = context.getBean("commonService", CommonService.class);
    assertEquals("Message: Hello!", commonService.service());
  }

  @Test
  void testApplicationXML() {
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/app-config.xml");
    CommonService commonService = context.getBean("commonService", CommonService.class);
    // FIXME!! this gives Overridden: Message: null
    assertEquals("Overridden: Message: Hello!", commonService.service());
  }

问题在于 testApplicationXML:commonService 应该返回“覆盖:消息:Hello!”,但它返回“覆盖:消息:null”。

我已将所有代码放到 github(为简单起见,库和应用程序都在一个项目中): https ://github.com/mateattila/spring-test-sandbox

我发现 Spring 实例化了 OverriddenServiceImpl 但没有从以前的定义中继承参数。我尝试过使用 bean 继承,但在这种情况下,我必须使用不同的 bean id,我想避免它。我尝试使用基于注释的配置并且它可以工作,但它会产生很多开销(请参阅 OverriddenConfiguration 和 testApplicationAnnotation)。

任何想法如何用 Spring 处理这个要求?我也对如何扩展 Spring 使其像这样工作感兴趣。

标签: javaspringparametersconfigurationoverriding

解决方案


在跟进@M.Deinum 的评论后,我找到了非常简单的解决方案:使用 bean 名称而不是 bean id。名称覆盖工作正常。我已将修复提交到github 存储库,无论如何,这里是:

lib-config.xml:
    <bean id="commonService" name="service"
          class="spring.context.test.library.CommonServiceImpl">  
        <property name="message" value="Hello!" />
    </bean>

app-config.xml:
    <bean id="commonService2" name="service" 
          class="spring.context.test.application.OverriddenServiceImpl"
          parent="commonService">  
    </bean>

通过测试:

  @Test
  void testApplicationXML_FIXED() {
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/app-config.xml");
    CommonService commonService = context.getBean("service", CommonService.class);
    assertEquals("Overridden: Message: Hello!", commonService.service());
  }

推荐阅读