How Does Spring’s @Autowired Work Under the Hood? A Deep Dive
This article explores the various ways to use Spring’s @Autowired annotation—including constructor, setter, field, and collection injection—examines its purpose, and provides a detailed analysis of its implementation in the Spring framework by dissecting the source code and related reflection mechanisms.
Preface
When developing with Spring, configuration can be done via XML or Java config. As Spring Boot gains popularity, Java config and its annotations, especially @Autowired, become increasingly common for injecting defined beans.
Usage of @Autowired
Common injection scenarios include:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}Setter injection:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}Method injection with multiple parameters:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}Field injection (most frequently used) and mixed constructor‑field injection are also demonstrated.
Advanced injection examples include arrays, Set, and Map collections:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
} public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
} public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}What Does @Autowired Actually Do?
@Autowiredbelongs to Spring’s container‑configuration annotations. It signals the container to automatically wire a bean of the required type into the annotated field, constructor, method, or parameter.
How @Autowired Is Implemented
Java annotations are metadata; their behavior is provided by external processors. Spring’s implementation resides in AutowiredAnnotationBeanPostProcessor. The core method buildAutowiringMetadata scans a class’s fields and methods via reflection, identifies those annotated with @Autowired, and creates an InjectionMetadata object containing InjectedElement entries.
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
// Scan fields
ReflectionUtils.doWithLocalFields(targetClass, field -> {
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
// Scan methods
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
return;
}
if (method.getParameterCount() == 0) {
logger.warn("Autowired annotation should only be used on methods with parameters: " + method);
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
} while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}The resulting InjectionMetadata is used during bean post‑processing to inject dependencies. For fields, Spring makes the field accessible and sets its value; for methods, it invokes the method with the resolved bean instance.
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable {
for (InjectedElement element : injectedElements) {
element.inject(target, requestingBeanName, pvs);
}
}Field injection essentially performs field.set(target, getResourceToInject(...)), while method injection calls method.invoke(target, getResourceToInject(...)). The getResourceToInject method looks up the appropriate bean from the application context.
Key Takeaways
• @Autowired is a runtime‑retained annotation that enables automatic wiring of beans.
• Spring discovers annotated members via reflection, builds metadata, and injects dependencies during the bean lifecycle.
• Static fields are not supported because dependency injection is intended for instance members, preserving testability and multiple‑instance semantics.
• Understanding the underlying implementation helps developers use the annotation more effectively and troubleshoot wiring issues.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
