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.
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.
DaTaobao Tech
Official account of DaTaobao Technology
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.