Same class implementing 2 interface in springboot bean context

Viewed 20

I'm facing something annoying when using springboot. I have implemented a class implementing 2 interfaces. Then I declare, in a configuration class, which bean use for each of these interfaces.

When I start springboot, It fails because I have twice the same bean in the context. Indeed I have two times the instanciated class in memory but I would expect that springboot would be able to make a difference.

Here is an example of my problem.

public interface IOne {
    void functionOne();
}

public interface ITwo {
    void functionTwo();
}

public class Impl implements IOne, ITwo {

    @Override
    public void functionOne() {
        System.out.println("Hello One");

    }

    @Override
    public void functionTwo() {
        System.out.println("Hello Two");
    }
}

@Configuration
public class Config {

    @Bean
    public IOne configTest() {
        return new Impl();
    }

    @Bean
    public ITwo configOther() {
        return new Impl();
    }
}

@Service
public class ServiceOne {

    @Autowired
    ITwo two;

    @Autowired
    IOne one;

    @PostConstruct
    public void init() {
        one.functionOne();
        two.functionTwo();
    }
}

Could somebody explain to me why springboot is behaving like that ? And if there is a way to perform what I want to do without using @Qualifier or something related.

Thanks in advance

1 Answers

Once your configTest and configOther beans have been created, Spring knows that they're an Impl and can be autowired as either an IOne or ITwo. There's no way of altering this behaviour as Spring will always use as much type information as it can, not just the information that's available from the bean definition.

In your example, there's no apparent need for two separate instances of Impl. You could define a single Impl bean instead:

@Bean
public Impl implBean() {
    return new Impl();
}

This same instance can then be injected into ServiceOne as both an IOne and an ITwo.

If you absolutely need IOne and ITwo to be satisfied using separate beans, you'll either have to use qualifiers or split your Impl into two classes; one that implements IOne and one that implements ITwo.

Related