What does required=true vs required=false on @Autowired mean, and how else can you model an optional dependency?
answer
- required=true default -> fail fast
- required=false -> null / method skipped
- Optional<T> = empty when absent
- ObjectProvider.getIfAvailable()
- empty collection never throws
basics
~20 srequired=true (the default) means the bean must exist or startup fails. required=false means Spring skips injection and leaves the field null if no matching bean is found. You can also declare the dependency as Optional<T> or use @Nullable.
solid answer
~40 sBy default @Autowired is required=true: if no candidate bean matches, Spring throws NoSuchBeanDefinitionException and the context fails to start. Setting required=false makes the dependency optional — with a missing bean, a field stays null and an annotated method is simply not called. On a constructor, required=false is unusual because Spring must still instantiate the object. More idiomatic ways to express optionality: declare the injection point as Optional<Dependency> (empty when absent), add @Nullable (Spring injects null without failing), or inject ObjectProvider<Dependency> and call getIfAvailable(). Note a subtlety: with multiple constructors you may mark at most one @Autowired(required=true); several optional constructors let Spring pick a greediest satisfiable one. Prefer Optional/ObjectProvider over required=false for clarity and null-safety.
code
java · 24 lines@Service
class NotificationService {
// Optional dependency, idiomatic: empty when no MetricsSink bean exists.
private final Optional<MetricsSink> metrics;
// Lazy, absence- and multiplicity-aware handle.
private final ObjectProvider<AuditLogger> auditLoggers;
NotificationService(Optional<MetricsSink> metrics,
ObjectProvider<AuditLogger> auditLoggers) {
this.metrics = metrics;
this.auditLoggers = auditLoggers;
}
void send(String msg) {
metrics.ifPresent(m -> m.increment("sent"));
AuditLogger logger = auditLoggers.getIfAvailable();
if (logger != null) logger.record(msg);
}
}
// Alternative on a setter/field:
// @Autowired(required = false) private CacheManager cacheManager; // may be nullgo deeper
Know true = must exist, false = may be null.
Contrast field/method/constructor behaviour and name Optional/@Nullable/ObjectProvider.
Explain the greediest-constructor rule and that required doesn't touch ambiguity.
Advocate Optional/ObjectProvider for null-safety and lazy resolution, and reason about collection injection semantics.
### The `required` attribute `@Autowired` has one attribute, `required`, defaulting to **true**. - **required=true**: the injection point *must* be satisfiable. If **no** matching bean exists, `AutowiredAnnotationBeanPostProcessor` raises `NoSuchBeanDefinitionException` and the `ApplicationContext` **fails to start** (fail-fast). This is usually what you want for genuine collaborators. - **required=false**: the dependency is **optional**. Behaviour differs by injection point: - **Field**: left at its default (`null`) if no candidate. - **Method/setter**: the method is **not invoked at all** when a required argument is unsatisfiable. - **Constructor**: technically allowed but atypical — Spring still needs to build the object. With **multiple constructors**, mark them `@Autowired(required=false)` and Spring chooses the **greediest constructor whose dependencies are all satisfiable**; at most **one** constructor may be `required=true`. ### Idiomatic alternatives (preferred) Rather than `required=false`, express optionality in the **type**: 1. **`java.util.Optional<T>`** — Spring injects `Optional.empty()` when no bean matches, `Optional.of(bean)` otherwise. Null-safe and self-documenting. 2. **`@Nullable`** (e.g. `org.springframework.lang.Nullable`) on the parameter/field — Spring injects `null` instead of failing, keeping `@Autowired` at its default. 3. **`ObjectProvider<T>`** (`org.springframework.beans.factory.ObjectProvider`) — a lazy handle. Call `getIfAvailable()`, `getIfUnique()`, or `stream()`. Great when the dependency is optional *and* you want to defer or handle multiplicity yourself, avoiding eager resolution and startup-ordering issues. ### Collections are a special case `@Autowired List<Handler>` or `Map<String, Handler>` injects **all** matching beans. An **empty** collection is injected when none exist — Spring does **not** throw here even with `required=true`, because an empty collection is a valid result. ### Gotchas - `required=false` gives you a **null** field — every use site must null-check. `Optional`/`ObjectProvider` are safer. - Optionality is about **absence of a bean**, not about **ambiguity**: two candidates still throw `NoUniqueBeanDefinitionException` regardless of `required`. - Kotlin nullable types (`Dependency?`) are treated as optional injection points. ### When to use Use the default required=true for mandatory collaborators (fail fast). Reach for `Optional`/`ObjectProvider` when a feature bean may be absent in some profiles/configurations.
- Does required=false help when two beans of the type exist?No. required governs the zero-candidate case. Two candidates still throw NoUniqueBeanDefinitionException because the point is ambiguous, not absent — you need @Primary/@Qualifier to disambiguate.
- Why prefer Optional or ObjectProvider over required=false?They make optionality explicit in the type and avoid raw null. ObjectProvider is also lazy — it defers resolution and can handle absence, uniqueness, and multiple candidates via getIfAvailable/getIfUnique/stream.
saying these in an interview costs you the question
- Saying required=false silences NoUniqueBeanDefinitionException — it only affects the missing-bean case
- Thinking an empty @Autowired List throws when no beans match
- Marking two constructors @Autowired(required=true)
- Assuming a required=false setter is still called with null