首页 > 解决方案 > SpringBoot:如何注入两个具有相同名称的类

问题描述

在我的应用程序中,我有两个具有相同名称的类,但当然在不同的包中。

这两个类都需要在应用程序中注入;不幸的是,我收到以下错误消息:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'myFeature' for bean class [org.pmesmeur.springboot.training.service.feature2.MyFeature] conflicts with existing, non-compatible bean definition of same name and class [org.pmesmeur.springboot.training.service.feature1.MyFeature]

我的问题可以通过以下示例重现:

@Component
@EnableConfigurationProperties(ServiceProperties.class)
public class MyService implements IService {

    private final ServiceProperties serviceProperties;
    private final IProvider provider;
    private final org.pmesmeur.springboot.training.service.feature1.IMyFeature f1;
    private final org.pmesmeur.springboot.training.service.feature2.IMyFeature f2;


    @Autowired
    public MyService(ServiceProperties serviceProperties,
                     IProvider provider,
                     org.pmesmeur.springboot.training.service.feature1.IMyFeature f1,
                     org.pmesmeur.springboot.training.service.feature2.IMyFeature f2) {
        this.serviceProperties = serviceProperties;
        this.provider = provider;
        this.f1 = f1;
        this.f2 = f2;
    }
    ...

package org.pmesmeur.springboot.training.service.feature1;

public interface IMyFeature {

    void print();

}

package org.pmesmeur.springboot.training.service.feature1;

import org.springframework.stereotype.Component;

@Component
public class MyFeature implements IMyFeature {

    @Override
    public void print() {
        System.out.print("HelloWorld");
    }

}

package org.pmesmeur.springboot.training.service.feature2;

public interface IMyFeature {

    void print();

}

package org.pmesmeur.springboot.training.service.feature2;

import org.springframework.stereotype.Component;


@Component
public class MyFeature implements IMyFeature {

    @Override
    public void print() {
        System.out.print("FooBar");
    }

}

如果我为我的班级使用不同的名字MyFeature,我的问题就消失了!!!

我习惯使用 Guice,这个框架没有这种问题/限制

似乎spring依赖注入框架只使用类名而不是包名+类名来选择它的类。

在“现实生活”中,我在一个更大的项目中遇到了这个问题,我强烈希望不必重命名我的课程:有人可以帮助我吗?

最后一点,我宁愿避免“技巧”,例如 @Qualifier(value = "ABC")在注入我的类时使用:在我的示例中,找到正确的实例应该没有歧义, MyFeature因为它们没有实现相同的接口

标签: springspring-bootdependency-injectionguice

解决方案


简单地重新实现BeanNameGenerator为通过名称声明/实例化的 bean 添加了一个新问题

@Component("HelloWorld")
class MyComponent implements IComponent {
...
}

@Qualifier(value = "HelloWorld") IComponent component

我通过扩展AnnotationBeanNameGenerator和重新定义方法解决了这个问题buildDefaultBeanName()

static class BeanNameGeneratorIncludingPackageName extends AnnotationBeanNameGenerator {

    public BeanNameGeneratorIncludingPackageName() {
    }

    @Override
    public String buildDefaultBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry beanDefinitionRegistry) {
        return beanDefinition.getBeanClassName();
    }

}

推荐阅读