在运行应用程序之前,检测/测试@Autowired没有唯一的bean

时间:2012-11-28 02:10:37

标签: java spring autowired

我正在使用Java + Spring进行一些编码。像,

public interface PeopleService {}
public class CustomerService implemented PeopleService {}
public class EmployeeService implemented PeopleService {}

如果我在这样的代码中使用@Autowired,

@Autowired
protected PeopleService peopleService;

应用程序抛出异常“没有定义类型为[xxxxxxxx]的唯一bean:预期的单个匹配bean但找到了2.”在运行时。通过添加@Qualifier(“xxxxxx”)可以轻松解决问题。但是,此问题的烦人部分是异常仅在运行时弹出。通过这种方式,如果我不事先手动检查注释。一旦应用程序达到自动装配点,它就会抛出异常。

我不是手动检查的粉丝。只是想知道,在运行应用程序之前是否存在测试/检测此类异常的智能方法(例如在应用程序初始化期间或编译期间)?

非常感谢。


修改

最后,我刚刚提出了一个测试解决方案,该测试将找到扩展BasicService的所有类,并逐个初始化它们以测试每个类中自动装配bean的唯一性。

@Test
public void autowireValidationForAllSubclassOfBaseService() {
    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
    provider.addIncludeFilter(new AssignableTypeFilter(BasicService.class));

    Set<BeanDefinition> serverResources = provider.findCandidateComponents("path/class");
    AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

    for (BeanDefinition serverResource : serverResources) {
        try {
            Class<? extends BasicService> serverResourceClass =
                    (Class<? extends BasicService>) Class.forName(serverResource.getBeanClassName());
            Object bean = beanFactory.createBean(serverResourceClass, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
            beanFactory.initializeBean(bean, serverResourceClass.getSimpleName());
        } catch (Exception e) {
            Assert.assertTrue(false, "Autowired might not be handled properly " + e.getMessage());
        }
    }
}

这可能不是最好的方法,但我现在很满意,因为它可以正常运行并检测所有可能的自动装配问题。

3 个答案:

答案 0 :(得分:2)

尝试先添加@Service 公共类CustomerService实现了PeopleService {}

答案 1 :(得分:0)

好吧,您不需要使用@Autowired。您始终可以通过xml或java进行显式连接。

要连接以下课程,您可以:

public class MyBean {
    private PeopleService peopleService;
    public MyBean(PeopleService peopleService) {
        this.peopleService = peopleService;
    }
}

XML:

<bean id="customerService" class="the.package.containing.customerservice.CustomerService"/>

<bean id="employeeService" class="the.package.containing.employeeService.EmployeeService"/>

<bean id="myBean" class="the.package.containing.mybean.MyBean">
    <constructor-arg ref="employeeService"/>
</bean>

爪哇:

@Configuration
public class AppConfig {
    @Bean
    public PeopleService customerService() {
        return new CustomerService();
    }

    @Bean
    public PeopleService employeeService() {
        return new EmployeeService();
    }

    @Bean
    public MyBean myBean() {
        return new MyBean(customerService());
    }
}

由于您似乎是在编译时类型安全之后,我建议使用基于Java的方法,因为它为您提供了编译时保证。

答案 2 :(得分:0)

最后,我刚刚提出了一个测试解决方案,该测试将找到扩展BasicService的所有类,并逐个初始化它们以测试每个类中自动装配bean的唯一性。

@Test
public void autowireValidationForAllSubclassOfBaseService() {
    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
    provider.addIncludeFilter(new AssignableTypeFilter(BasicService.class));

    Set<BeanDefinition> serverResources = provider.findCandidateComponents("path/class");
    AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

    for (BeanDefinition serverResource : serverResources) {
        try {
            Class<? extends BasicService> serverResourceClass =
                    (Class<? extends BasicService>) Class.forName(serverResource.getBeanClassName());
            Object bean = beanFactory.createBean(serverResourceClass, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
            beanFactory.initializeBean(bean, serverResourceClass.getSimpleName());
        } catch (Exception e) {
            Assert.assertTrue(false, "Autowired might not be handled properly " + e.getMessage());
        }
    }
}

这可能不是最好的方法,但我现在很满意,因为它可以正常运行并检测所有可能的自动装配问题。