2013-08-23 53 views
6

我有一个现有的豆定义spring.xml,我想使用注释重写。我曾尝试以下覆盖豆:如何重写使用注解在xml中定义的spring bean?

@Configuration 
@ImportResource({"/spring.xml"}) 
public class Main { 

    public static void main(String[] args) { 
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DdwMain.class); 

     Object o = context.getBean("overrideBean"); 
     // o should be null but it is not 
    } 

    @Bean(name="overrideBean") 
    public OverrideBean overrideBean() { 
     return null; 
    } 

} 

spring.xml配置使用上面的代码中的豆总是实例化和由context.getBean调用返回。

可以通过在@ImportResource中包含另一个XML配置文件来覆盖该bean,但是我希望找到一个使用注释的解决方案将更清晰。

+0

为什么您的'Main'类是Spring'@ Configuration'类?如果使用不同的'@ Configuration'类实例化Spring上下文会发生什么? – 2013-08-23 13:50:10

+2

'ImportResource'只有在读取了'@ Configuration'类的所有bean定义后才能完成。所以定义替换的方式与你所期望的相反。我可以想象你可以在Spring Jira中找到相关的功能请求。 –

+4

https://jira.springsource.org/browse/SPR-7341 –

回答

3

通常xml注册的bean有优先权。所以你可以使用xml配置的重写带注释的bean,但你试图以相反的方式来做到这一点。您是否可以不使用不同的bean名称,并使用@Qualifier注释在多个候选项中选择它?

大部分时间将xml与自动扫描结合起来很容易出错。

+1

是的,我同意你的意见。我打算写在这里:) –

+0

** @ Qualifer **没有帮助。覆盖一个bean可以防止第一个bean存在。 @Qualifier只是帮助自动装配。 xml和自动扫描注释更正确。 –

+0

这就是对的。这只是一个想法,因为我认为你可能有一些你不能控制来自某个库的bean ......所以你可以重写行为,然后通过@Qualifier注释选择你的用户定义的bean。 –

4

我正在通过xml配置的旧版应用程序(spring 3.1.1)中工作,但我需要对某些配置进行随机配置以进行测试,而不会偏离生产配置太远。我的方法是使用BeanPostProcessor。

package myapp.test; 

import javax.servlet.ServletContext; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Import; 
import org.springframework.context.annotation.ImportResource; 
import org.springframework.mock.web.MockServletContext; 
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; 

import myapp.spring.config.ComplexSpringConfiguration; 

/** 
* Closely resembles production configuration for testing 
* @author jim 
*/ 
@Configuration 
@ImportResource("file:src/main/webapp/WEB-INF/spring-servlet.xml") 
@Import(ComplexSpringConfiguration.class) 
public class TestConfig { 
    final Logger logger = LoggerFactory.getLogger(getClass()); 

    static { 
     System.setProperty("env.test", "system"); 
    } 

    //Override templateLoaderPath with something amenable to testing 
    @Bean 
    public BeanPostProcessor beanPostProcessor(){ 
     return new BeanPostProcessor(){ 
      @Override 
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
       //Override templateLoaderPath with something amenable to testing 
       if(beanName.equals("freemarkerConfig")) { 
        logger.debug("overriding bean with name:" + beanName); 
        FreeMarkerConfigurer fc = new FreeMarkerConfigurer(); 
        fc.setTemplateLoaderPath("file:src/main/webapp/WEB-INF/freemarker"); 
        bean = fc; 
       } 
       return bean; 
      } 

      @Override 
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
       return bean; 
      } 
     }; 
    } 

    @Bean 
    public ServletContext servletContext(){ 
     MockServletContext mockContext = new MockServletContext(); 
     mockContext.setContextPath("/myapp"); 
     return mockContext; 
    } 
}