Does Spring @Autowired inject beans by name or by type?

Lidovic picture Lidovic · May 20, 2015 · Viewed 17k times · Source

I am reading beginning spring (wiley press) book. In chapter 2 there is an example about Java configuration and @Autowired. It provides this @Configuration class

@Configuration
public class Ch2BeanConfiguration {

    @Bean
    public AccountService accountService() {
        AccountServiceImpl bean = new AccountServiceImpl();
        return bean;
    }

    @Bean
    public AccountDao accountDao() {
        AccountDaoInMemoryImpl bean = new AccountDaoInMemoryImpl();
        //depedencies of accountDao bean will be injected here...
        return bean;
    }

    @Bean
    public AccountDao accountDaoJdbc() {
        AccountDaoJdbcImpl bean = new AccountDaoJdbcImpl();
        return bean;
    }
}

and this regular bean class

public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    ...
}

When I run the code, it works. But I expected an exception because I have defined 2 beans with the same type in the configuration.

I realized it works like this:

  • if Spring encounters multiple beans with same type it checks field name.
    • if it finds a bean with the name of the target field, it injects that bean into the field.

Isn't this wrong? Is there a bug in Spring's handling of Java configuration?

Answer

Sotirios Delimanolis picture Sotirios Delimanolis · May 20, 2015

The documentation explains this

For a fallback match, the bean name is considered a default qualifier value. Thus you can define the bean with an id "main" instead of the nested qualifier element, leading to the same matching result. However, although you can use this convention to refer to specific beans by name, @Autowired is fundamentally about type-driven injection with optional semantic qualifiers. This means that qualifier values, even with the bean name fallback, always have narrowing semantics within the set of type matches; they do not semantically express a reference to a unique bean id

So, no, it's not a bug, that is the intended behavior. The bean id (name) will be used as a fallback if a by-type autowiring doesn't find a single matching bean.