The sample code like below:

I defined a bean with scope prototype


@Configuration
public class BeanConfiguration {

    @Bean
    @Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
    public MessageService configureEmailMessageService() {
        return new EmailMessageService();
    }
}

I am injecting the bean using Match By Type.

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfiguration.class);
        MessageService email = context.getBean(EmailMessageService.class);
        System.out.println(email.hashCode());
    }

While executing this, I am getting

No qualifying bean of type 'com.xxx.bean.services.EmailMessageService' available

But if I remove the bean scope, the mentioned code works fine.

Looks like if this bean is initialized on runtime(like scope prototype, or has lazy annotation), Spring cannot find the interface bean definition by the implementation type. But if we eagerly initialize during service startup, Spring can get bean by the implementation type, even though the bean type is interface type. Not sure if it is expected by Spring, but looks like an issue to use.

Comment From: snicoll

The declared type of the bean is MessageService, not EmailMessageService. It's the other way around. There are certain arrangements where the framework can go the extra mile and refine the type based on the instance but this is not always possible (as in your case).

It is recommended to put the most precise type at the @Bean definition level.