使用注释覆盖Bean配置

时间:2012-07-09 00:48:52

标签: spring annotations classpath override spring-annotations

使用案例:我通过类路径扫描@ComponentScan配置了我的容器。对于我的测试配置,我需要能够模拟特定的bean。

由于加载顺序,使用@Configuration时,通过类路径扫描加载的bean不会正确覆盖。以下代码示例演示了此问题。 BaseExample.java显示了如何通过配置覆盖bean。 ScanExample.java显示覆盖了通过@ComponentScan加载的bean(参见最后的注释)。

bitbucket上有一个演示项目。

// BaseExample.java

package com.glassworks.mock;

import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.common.base.Joiner;

public class BaseExample {
    private static final Logger log = LoggerFactory.getLogger(BaseExample.class);
    private static AnnotationConfigApplicationContext ctx;

    public static void main(String args[]) {
        ctx = new AnnotationConfigApplicationContext(Config.class, OverrideConfig.class);

        String beans[] = ctx.getBeanDefinitionNames();
        log.info("{} beans found: {}", beans.length, Joiner.on(",").join(beans));

        for(String bean : beans) {
            log.info("{}: {}", bean, ctx.getBean(bean));
        }
    }

    @Configuration
    public static class Config {
        @Bean
        public AccountDao accountDao() {
            log.debug("Creating accountDao [Config]");
            return new AccountDao();
        }
    }

    @Configuration
    public static class OverrideConfig {
        @Bean
        public Object accountDao() {
            log.debug("Creating accountDao [OverrideConfig]");
            return Mockito.mock(AccountDao.class);
        }
    }

}

输出: 21:05 INFO | com.glassworks.mock.BaseExample | accountDao:模拟AccountDao,hashCode:666537607

[// ScanExample.java

package com.glassworks.mock;

import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.google.common.base.Joiner;

public class ScanExample {
    private static final Logger log = LoggerFactory.getLogger(ScanExample.class);
    private static AnnotationConfigApplicationContext ctx;

    public static void main(String args[]) {
        ctx = new AnnotationConfigApplicationContext(Config.class, OverrideConfig.class);

        String beans[] = ctx.getBeanDefinitionNames();
        log.info("{} beans found: {}", beans.length, Joiner.on(",").join(beans));

        for(String bean : beans) {
            log.info("{}: {}", bean, ctx.getBean(bean));
        }
    }

    @Configuration
    @ComponentScan("com.glassworks.services")
    public static class Config {

    }

    @Configuration
    public static class OverrideConfig {
        @Bean
        public AccountDao accountDao() {
            log.debug("Creating accountDao [OverrideConfig]");
            return Mockito.mock(AccountDao.class);
        }
    }

}

输出: 21:08 INFO | com.glassworks.mock.ScanExample | accountDao:com.glassworks.services.AccountDao@48805ebb

// AccountDao.java
package com.glassworks.services;

import org.springframework.stereotype.Repository;

@Repository
public class AccountDao {

}

注意 值得注意的是,在将日志设置为调试的情况下,Spring表示它正在跳过定义。这似乎是一个错误。

21:09 DEBUG | o.s.c.a.ConfigurationClassBeanDefinitionReader |跳过[BeanMethod:name = accountDao,declaringClass = com.glassworks.mock.ScanExample $ OverrideConfig]的加载bean定义:bean“accountDao”的定义已经存在。这可能是由于XML中的覆盖。

0 个答案:

没有答案