Backend Development 12 min read

Spring Bean Injection Issues and Dependency Injection Priorities

In a project with two applications, a Tair bean defined via JavaConfig works in one app but fails in the other because Spring’s injection rules prioritize type over name, causing ambiguity; using explicit bean naming with XML, adding @Qualifier, or switching to @Resource resolves the issue.

DaTaobao Tech
DaTaobao Tech
DaTaobao Tech
Spring Bean Injection Issues and Dependency Injection Priorities

During development of a project that contains two applications (A and B), a Tair bean configured in a shared fat client works in application A but fails to be injected in application B.

Background : Spring allows bean configuration via three main approaches – XML files, annotation‑based configuration, and JavaConfig.

XML file configuration

Annotation configuration (e.g., @Component, @Service, @Repository, @Controller)

JavaConfig using @Configuration classes and @Bean methods

Annotation Auto‑Wiring

The most common annotations for dependency injection are:

@Autowired – Spring‑specific, injects by type, can be used on constructors, methods, fields, or parameters.

@Resource – JDK standard (JSR‑250), defaults to injection by name, can fall back to type.

@Inject – part of JSR‑330, similar to @Autowired, type‑based.

Key differences:

@Autowired supports required=false for optional dependencies; @Resource does not.

@Resource performs name‑based injection first, then type if no matching name is found.

@Inject behaves like @Autowired (type‑based) and does not support the required attribute.

Spring Dependency‑Injection Priority Rules

When using @Resource :

If @Resource(name="beanName") is specified, Spring matches by bean name first; @Primary is ignored.

If no name is given, Spring tries to match the field or property name.

If name matching fails, Spring falls back to type matching. If multiple beans of the same type exist, the bean marked with @Primary is chosen.

When using @Autowired :

Spring first matches by type. If a single candidate exists, it is injected.

If multiple candidates exist, @Qualifier("beanName") can be used to specify the exact bean.

If no qualifier is present, Spring attempts to match by field/property name.

If still ambiguous, the bean marked with @Primary is selected; otherwise a NoUniqueBeanDefinitionException is thrown.

Code Examples

JavaConfig class (original, non‑working in B):

@Configuration
@Slf4j(topic = "config")
public class XxxTairConfig {
    @Value("${spring.tmg.xxx.tair.username:default}")
    private String username;

    @Value("${spring.tmg.xxx.tair.namespace:default}")
    private Integer namespace;

    @Bean(initMethod = "init")
    public TairManager tmgXxxTairManager() {
        MultiClusterTairManager manager = new MultiClusterTairManager();
        manager.setUserName(username);
        manager.setDynamicConfig(true);
        return manager;
    }

    @Bean
    public TairAccessor tmgXxxTairAccessor(TairManager tmgXxxTairManager) {
        TairAccessorImpl accessor = new TairAccessorImpl();
        accessor.setTairManager(tmgXxxTairManager);
        accessor.setNamespace(namespace);
        return accessor;
    }
}

XML configuration (works in both applications):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="tmgXxxTairManager" class="com.taobao.tair.impl.mc.MultiClusterTairManager" init-method="init">
        <property name="userName"><value>yourUserName</value></property>
        <property name="timeout"><value>50</value></property>
    </bean>
    <bean id="tmgXxxTairAccessor" class="com.alibaba.tmallg.gcommon.tair.TairAccessorImpl">
        <property name="tairManager" ref="tmgXxxTairManager"/>
        <property name="namespace" value="yourNamespace"/>
    </bean>
</beans>

Fixed JavaConfig using @Qualifier to avoid ambiguity:

@Configuration
@Slf4j(topic = "config")
public class XxxTairConfig {
    // ... same fields as before ...
    @Bean(initMethod = "init")
    public TairManager tmgXxxTairManager() { /* same as above */ }

    @Bean
    public TairAccessor tmgXxxTairAccessor(@Qualifier("tmgXxxTairManager") TairManager tmgXxxTairManager) {
        TairAccessorImpl accessor = new TairAccessorImpl();
        accessor.setTairManager(tmgXxxTairManager);
        accessor.setNamespace(namespace);
        return accessor;
    }
}

Solution

When a bean defined via JavaConfig does not get injected as expected, switch to XML configuration or explicitly specify the target bean with @Qualifier . Using @Resource often avoids the ambiguity because it defaults to name‑based injection.

Conclusion: For reliable bean injection in Spring, prefer explicit bean naming (XML or @Qualifier ) or use @Resource to reduce the risk of injecting an unintended bean.

Javaspringannotationsdependency injectionBean Configuration
DaTaobao Tech
Written by

DaTaobao Tech

Official account of DaTaobao Technology

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.