Beans & Dependency Injection
What a bean is
A bean is an object the container creates, configures and hands out. You never call new
on it yourself.
| Stereotype | Meaning |
|---|---|
@Component | any bean |
@Service | business logic |
@Repository | data access (adds exception translation) |
@RestController | web endpoint returning data |
@Configuration | class that declares @Bean methods |
All four of the first are @Component underneath — the name documents intent.
Constructor injection
One constructor, final fields, no framework annotation in sight — that class is testable
with plain new.
Avoid field injection
@Autowired private Foo foo; hides dependencies, breaks final, and forces reflection in
tests. Use the constructor.
Beans from a configuration class
Use @Bean for types you do not own:
The method name is the bean name; parameters are injected.
Choosing between candidates
Inject List<Notifier> or Map<String, Notifier> to get all of them.
Conditional beans
This is exactly how auto-configuration backs off in favour of your own beans.
Scope and lifecycle
Beans are singletons by default — one instance per context, shared by every thread. Keep them stateless.
For startup work with access to arguments:
★ Exercises
- Write a
RandomQuoteServiceand inject it into a controller. - Add a second
Notifierimplementation and select one with@Qualifier. - Inject
List<Notifier>and call every implementation. - Add a
@PostConstructlog line and watch the order of construction on startup. - Why does a singleton bean holding a mutable field cause bugs?