如何使用Annotations覆盖xml中定义的springbean



我在spring.xml中定义了一个现有的bean overrideBean,我想使用注释覆盖它。我尝试了以下方法来覆盖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配置中的bean总是被实例化,并由context.getBean调用返回。

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

通常xml注册的bean具有优先级。因此,您可以用xml配置的bean覆盖带注释的bean,但您正试图用另一种方式来实现。您是否可以不使用不同的bean名称,并使用@Qualifier注释在多个候选者中选择它?

大多数情况下,将xml与自动扫描相结合很容易出错。

我使用的是一个通过xml配置的旧应用程序(spring3.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;
    }
}

最新更新