Question 26 · Section 5

What Does the @Autowired Annotation Do?

4. Avoid static fields 5. Collection -> all beans of type 6. AOT -> reflection replaced with direct code

Language versions: English Russian Ukrainian

Junior Level

@Autowired tells Spring to inject a dependency.

@Service
public class OrderService {

    @Autowired  // Spring finds and injects OrderRepository itself
    private OrderRepository repo;
}

Where it works:

  • Constructor
  • Fields
  • Setters

Rule:

  • One bean of the type -> injects it
  • Several -> error or @Qualifier

Middle Level

AutowiredAnnotationBeanPostProcessor

@Autowired processing:
  1. Scans fields/methods/constructors
  2. Creates InjectionMetadata (cache)
  3. Finds suitable beans
  4. Injects via reflection

Search Algorithm

1. By type (byType) - Spring finds all beans of this type
2. If several - @Qualifier filters by name
3. If no @Qualifier - checks @Primary (global "default" marker)
4. If no @Primary - by variable name (byName)
@Service
public class OrderService {
    private final OrderRepository repo;

    // Single constructor -> @Autowired not needed!
    public OrderService(OrderRepository repo) {
        this.repo = repo;
    }
}

Collection Injection

// All beans of PaymentService type
@Autowired
List<PaymentService> payments;

// Map: bean name -> bean
@Autowired
Map<String, PaymentService> paymentMap;

Senior Level

ObjectProvider

@Autowired
ObjectProvider<PaymentService> provider;

// Lazy retrieval
PaymentService service = provider.getIfAvailable();

// Stream of all beans
provider.stream().forEach(...);

// Cycle resolution!

Reflection Overhead

Field Injection -> setAccessible(true) -> reflection
  -> + overhead on initialization

Constructor Injection -> direct call
  -> Faster

AOT (GraalVM) -> reflection -> direct code
  -> No reflection overhead (setAccessible). Dependencies resolved at compile time.

Production Experience

Real scenario: static field

@Autowired
private static Repo repo;  // Does NOT work!

// Spring injects into instances, not classes
// -> repo = null

Best Practices

  1. Constructor -> by default
  2. @Autowired not needed for single constructor
  3. ObjectProvider -> for cycles and lazy
  4. Avoid static fields
  5. Collection -> all beans of type
  6. AOT -> reflection replaced with direct code

Summary for Senior

  • AutowiredAnnotationBeanPostProcessor (AABPP) -> @Autowired processing
  • Constructor -> faster, final fields
  • ObjectProvider -> lazy, cycles
  • static -> does not work
  • Collection -> all beans of type
  • AOT -> no reflection in Native Image

Interview Cheat Sheet

Must know:

  • @Autowired is processed by AutowiredAnnotationBeanPostProcessor - scans fields/methods/constructors
  • Algorithm: byType -> @Qualifier -> @Primary -> byName -> error
  • Constructor Injection - recommended approach; with a single constructor, @Autowired is not needed
  • Collection injection: List - all beans of type, Map<String, T> - bean name -> bean
  • ObjectProvider - lazy retrieval, stream of all beans, resolving circular dependencies
  • @Autowired on static fields does NOT work - Spring injects into instances, not classes
  • Constructor Injection is faster than Field Injection: direct call vs reflection (setAccessible)

Common follow-up questions:

  • What happens if there are two beans of the same type without @Qualifier? - NoUniqueBeanDefinitionException (unless there is @Primary or name match).
  • How to resolve a circular dependency? - ObjectProvider.getIfAvailable() or setter/field injection instead of constructor.
  • Why is Constructor Injection recommended? - Immutable fields (final), no reflection, easier to test, explicit dependencies.
  • Does @Autowired work in GraalVM Native Image? - Yes, but reflection is replaced with direct code during AOT compilation.

Red flags (DO NOT say):

  • “@Autowired on static field works” - no, Spring does not inject into static fields.
  • “Spring searches by name first” - no, first byType, then byName.
  • “Field Injection is better than Constructor Injection” - opposite, constructor gives immutability and testability.
  • “@Autowired is always required” - no, with a single constructor Spring injects automatically.

Related topics:

  • [[27. What to do if there are multiple beans of the same type]]
  • [[28. What is Qualifier]]
  • [[24. What is a Configuration class]]
  • [[25. Difference between Component Service Repository Controller]]