Why Changing @Resource Field Names Breaks Spring Bean Injection
This article explains how Spring's @Resource injection resolves beans by name first and then by type, why mismatched field names or bean registration order cause NoSuchBeanDefinitionException, and how to correctly configure DAO and CommonDAO beans to avoid injection failures.
Problem Description
Using Spring 5.3.23, a basic configuration defines a DAO interface, its implementation CommonDAO , and registers a DAO bean in AppConfig . CommonService injects both DAO and CommonDAO with @Resource . The program runs without error when both beans are injected.
Issue Summary
Various modifications to the injection cause inconsistent behavior:
Injecting only CommonDAO results in NoSuchBeanDefinitionException .
Renaming the field from commonDAO to dao makes the injection succeed.
Changing the order of fields ( CommonDAO then DAO ) makes the injection fail again.
Altering the bean registration order in AppConfig also affects success.
Root Cause Analysis
The @Resource annotation is processed by CommonAnnotationBeanPostProcessor . It first attempts to locate a bean by the field name (bean name). If a bean with that name does not exist, it falls back to type‑based lookup.
<code>public class CommonAnnotationBeanPostProcessor {
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) {
Object resource;
if (factory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
DependencyDescriptor descriptor = element.getDependencyDescriptor();
// If bean name not found, fall back to type match
if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
} else {
// Bean name exists, resolve directly
resource = beanFactory.resolveBeanByName(name, descriptor);
autowiredBeanNames = Collections.singleton(name);
}
}
return resource;
}
}
</code>The subsequent lookup process involves AbstractAutowireCapableBeanFactory and DefaultListableBeanFactory , which first try to find a bean by name in the singleton pool and, if not found, search by type using BeanFactoryUtils.beanNamesForTypeIncludingAncestors .
<code>public abstract class AbstractAutowireCapableBeanFactory {
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
return getBean(name, descriptor.getDependencyType());
}
}
public abstract class AbstractBeanFactory {
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
}
public class DefaultListableBeanFactory {
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
Object result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
return result;
}
protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType,
DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());
return ...;
}
}
</code>When CommonService injects DAO dao , the bean name dao matches the registered bean, so injection succeeds. For CommonDAO , there is no bean named commonDAO in the container; the processor therefore falls back to type lookup. If a DAO bean has already been created and stored in the singleton pool, the type lookup can succeed indirectly, which explains why certain registration orders work.
Thus, the injection failures are caused by the bean‑name‑first strategy of @Resource . Aligning the field name with the bean name (e.g., renaming the field to dao ) or ensuring the required bean is created earlier resolves the issue.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.