When writing Spring-enabled JUnit tests, I often make use of the
@Autowired annotation to inject my test with various beans from my test context. After much tinkering around with various test configurations, I noticed that the placement of the
@Autowired annotation affects the behavior of the injection, which piqued my curiosity.
With a private field and its corresponding setter method annotated with
@Autowired, I observed the expected behavior: the setter is called during initialization of the Spring context, and the dependency injected as usual.
I noticed that when I have an
@Autowired-annotated private field, it is injected with its appropriate bean with or without a corresponding setter method. Even more perplexing was that the setter is never called when I provided it. How is this field being injected?
With my Eclipse debugger in hand, I took a dive into Spring's source code to investigate. Right off the bat I noticed the
AutowiredAnnotationBeanPostProcessor class, which seems to do much of the heavy lifting of processing annotated beans. More specifically, it implements an inner class:
AutowiredFieldElement. This class acts as a helper, called by
postProcessAfterInstantiation() method to perform the field injection that I have until now overlooked.
This method traces back to the
InstantiationAwareBeanPostProcessor, the Javadoc of which speaks directly of the intended use for field injection.
Drilling down into the AutowiredFieldElement class, I found that injection of private fields without setter methods is actually a relatively simple excercise of the Java Reflection API. Specifically, through a combination of Field.setAccessible() and Field.set(), the private field is injected with the corresponding bean.