2

我正在使用 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());
        }
    }
}

这可能不是最好的方法,但我现在对它很满意,因为它可以工作并在真正运行它之前检测所有可能的自动连线问题。

4

3 回答 3

2

尝试在公共类 CustomerService 实现 PeopleService {} 之前添加 @Service

于 2012-11-28T03:06:36.837 回答
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());
        }
    }
}

这可能不是最好的方法,但我现在对它很满意,因为它可以工作并在真正运行它之前检测所有可能的自动连线问题。

于 2012-11-29T05:43:41.977 回答
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 的方法,因为它为您提供了编译时保证。

于 2012-11-28T02:42:56.180 回答