Woche 1, Tag 3 — Beans und Bean-Definitionen
Ziel
Heute verstehst du, was eine Spring Bean wirklich ist.
Die Kernfragen:
- Was ist eine Spring Bean?
- Was ist eine
BeanDefinition? - Wie registriert Spring Beans?
- Was ist der Unterschied zwischen
@Componentund@Bean? - Was ist der Unterschied zwischen
@Component,@Service,@Repositoryund@Controller? - Wann nutzt du welche Annotation?
- Welche typischen Prüfungsfallen gibt es zu Beans?
1. Kurz-Wiederholung von Tag 2
Am Tag 2 hast du gelernt:
ApplicationContextist der zentrale Spring-Container.ApplicationContextverwaltet Spring Beans.BeanFactoryist der Basis-Container.ApplicationContexterweitertBeanFactory.BeanDefinitionist das Rezept.- Bean ist das echte Objekt.
Merksatz:
BeanDefinition ist das Rezept. Bean ist das Objekt.
Heute gehst du tiefer in Beans.
2. Was ist eine Spring Bean?
Eine Spring Bean ist ein vom Spring IoC-Container verwaltetes Objekt.
Kurzdefinition:
Eine Spring Bean ist ein Objekt, das Spring erzeugt, konfiguriert, verdrahtet und verwaltet.
Beispiel:
@Service
public class OrderService {
}
Wenn Spring diese Klasse findet und ein Objekt daraus erzeugt, ist das Objekt eine Spring Bean.
3. Normales Java-Objekt vs. Spring Bean
Normales Java-Objekt
OrderService orderService = new OrderService();
Dieses Objekt erzeugst du manuell.
Spring verwaltet es nicht.
Spring kann nicht automatisch:
- Abhängigkeiten injizieren
- Lifecycle-Callbacks aufrufen
@Transactionalanwenden- Security-Proxies legen
- Zerstörung steuern
Spring Bean
@Service
public class OrderService {
}
Spring erzeugt und verwaltet dieses Objekt.
Spring kann:
- Abhängigkeiten injizieren
- den Lifecycle steuern
- AOP-Proxies anwenden
- Transaktionen anwenden
- Security anwenden
- dieselbe Singleton-Instanz wiederverwenden
4. Prüfungsdefinition
Für die Prüfung:
Eine Spring Bean ist ein Objekt, dessen Lebenszyklus vom Spring IoC-Container verwaltet wird. Spring erzeugt das Objekt, injiziert Abhängigkeiten, konfiguriert es und kann zusätzliches Verhalten anwenden: Lifecycle-Callbacks, AOP-Proxies, Transaktionen und Security.
5. Was verwaltet Spring genau?
Wenn Spring eine Bean verwaltet, kann er steuern:
1. Objekterzeugung
2. Dependency Injection
3. Konfiguration
4. Bean-Name
5. Bean-Scope
6. Initialisierung
7. Zerstörung
8. AOP-Proxy-Wrapping
9. Transaktionsverhalten
10. Security-Methoden-Interception
Beispiel:
@Service
public class PaymentService {
@Transactional
public void pay() {
// business logic
}
}
Spring erzeugt nicht nur PaymentService.
Er kann die Bean auch mit einem Proxy wrappen, damit @Transactional greift.
6. Was ist eine BeanDefinition?
Bevor Spring eine Bean erzeugt, speichert er Metadaten darüber.
Diese Metadaten heißen BeanDefinition.
Kurzdefinition:
Eine
BeanDefinitionist Metadaten, die Spring sagen, wie eine Bean erzeugt und verwaltet werden soll.
Eine BeanDefinition kann enthalten:
- Bean-Klasse
- Bean-Name
- Scope
- Konstruktor-Argumente
- Abhängigkeiten
- Lazy/Eager-Einstellung
- Init-Methode
- Destroy-Methode
- Factory-Methode
- ob die Bean
@Primaryist - Qualifiers
7. BeanDefinition vs. Bean
| Konzept | Bedeutung |
|---|---|
BeanDefinition | Metadaten / Rezept |
| Bean | Das echte Objekt |
Beispiel:
BeanDefinition:
- Klasse: OrderService
- Scope: singleton
- Abhängigkeit: OrderRepository
Bean:
- das echte OrderService-Objekt im Speicher
Merksatz:
BeanDefinitionist das Rezept. Bean ist das fertige Gericht.
8. Wie registriert Spring Beans?
Spring kann Beans auf verschiedene Wege registrieren.
Die zwei wichtigsten:
- Component Scanning
@Bean-Methoden in Konfigurationsklassen
9. Weg 1 — Component Scanning
Spring scannt Packages und sucht Annotationen wie:
@Component
@Service
@Repository
@Controller
@RestController
Beispiel:
@Service
public class OrderService {
}
Spring sieht @Service, legt eine BeanDefinition an und erzeugt später die Bean.
10. Was ist Component Scanning?
Component Scanning heißt:
Spring durchsucht ausgewählte Packages nach Klassen mit Spring-Stereotyp-Annotationen.
Beispiel:
@SpringBootApplication
public class MyApplication {
}
@SpringBootApplication enthält:
@ComponentScan
Standardmäßig scannt Spring das Package der Hauptklasse und alle Unterpackages.
11. Gute Package-Struktur
Gute Struktur:
com.example.app
├── MyApplication.java
├── controller
│ └── OrderController.java
├── service
│ └── OrderService.java
└── repository
└── OrderRepository.java
Liegt MyApplication in:
com.example.app
scannt Spring:
com.example.app.controller
com.example.app.service
com.example.app.repository
Das funktioniert gut.
12. Schlechte Package-Struktur
Schlechte Struktur:
com.example.app
└── MyApplication.java
com.other.service
└── OrderService.java
Liegt die Hauptklasse in com.example.app, scannt Spring com.other.service nicht automatisch.
OrderService wird dann keine Bean.
Prüfungsfalle:
Eine Klasse mit
@Servicewird keine Bean, wenn sie außerhalb des Component Scans liegt.
13. Weg 2 — @Bean-Methode
Der zweite gängige Weg: @Bean.
Beispiel:
@Configuration
public class AppConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
Der Rückgabewert der Methode wird zur Spring Bean.
Spring registriert eine Bean mit dem Namen:
clock
Der Bean-Typ ist:
Clock
14. Wann @Bean nutzen?
Nutze @Bean, wenn:
- die Klasse aus einer Drittanbieter-Lib kommt
- du die Klasse nicht ändern kannst
- die Erzeugung eigene Logik braucht
- du ein Objekt manuell konfigurieren willst
- du Konstruktor-Werte selbst wählen musst
Beispiel:
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
return mapper;
}
}
ObjectMapper kommt von Jackson — nicht aus deiner App.
@Bean passt hier gut.
15. @Component vs. @Bean
Sehr wichtig.
| Thema | @Component | @Bean |
|---|---|---|
| Wo? | Auf Klasse | Auf Methode |
| Wer erzeugt? | Spring erzeugt die Klasse | Methode liefert Objekt |
| Am besten für | Eigene Klassen | Drittanbieter oder Custom Setup |
| Component Scan nötig? | Ja | Konfigurationsklasse muss registriert sein |
| Beispiel | OrderService | Clock, ObjectMapper, RestTemplate |
16. Beispiel: @Component
Nutze @Component oder @Service für eigene App-Klassen.
@Service
public class OrderService {
public void createOrder() {
System.out.println("Order created");
}
}
Einfach und sauber.
17. Beispiel: @Bean
Nutze @Bean, wenn du die Klasse nicht annotieren kannst.
@Configuration
public class TimeConfig {
@Bean
public Clock clock() {
return Clock.systemUTC();
}
}
Du kannst @Component nicht auf Clock setzen — das ist eine Java-Lib-Klasse.
Also erzeugst du sie mit @Bean.
18. Stereotyp-Annotationen
Spring hat mehrere gängige Stereotyp-Annotationen:
@Component
@Service
@Repository
@Controller
@RestController
Alle können Spring Beans registrieren.
Sie signalisieren aber unterschiedliche Rollen.
19. @Component
@Component ist die generische Annotation.
Für allgemeine Spring-verwaltete Klassen.
Beispiel:
@Component
public class SlugGenerator {
}
Bedeutung:
Das ist eine Spring-verwaltete Komponente.
20. @Service
@Service für Service-Layer-Klassen.
Beispiel:
@Service
public class OrderService {
}
Bedeutung:
Diese Klasse enthält Business-Logik.
Der Service-Layer koordiniert typischerweise:
- Validierung
- Business-Regeln
- Repositories
- Transaktionen
- Domain-Logik
21. @Repository
@Repository für Persistence-Layer-Klassen.
Beispiel:
@Repository
public class JdbcOrderRepository {
}
Bedeutung:
Diese Klasse spricht mit der Datenbank oder dem Persistence-System.
Wichtig für die Prüfung:
@Repositorykann Persistence Exception Translation aktivieren.
Datenbank-spezifische Exceptions werden in Springs DataAccessException-Hierarchie übersetzt.
22. @Controller
@Controller für Spring-MVC-Controller, die meist Views zurückgeben.
Beispiel:
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
Typisch für klassische serverseitig gerenderte MVC-Apps.
23. @RestController
@RestController für REST-APIs.
Beispiel:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@GetMapping("/{id}")
public OrderResponse getOrder(@PathVariable Long id) {
return new OrderResponse(id, "Book");
}
}
Wichtig:
@RestController
ist eine Kombination aus:
@Controller
@ResponseBody
Rückgabewerte landen direkt im HTTP-Response-Body — meist als JSON.
24. Vergleichstabelle
| Annotation | Layer | Hauptbedeutung |
|---|---|---|
@Component | generisch | allgemeine Spring Bean |
@Service | Service | Business-Logik |
@Repository | Persistence | DB-Zugriff + Exception Translation |
@Controller | Web MVC | Controller mit Views |
@RestController | REST API | Controller mit Response Body / JSON |
@Configuration | Config | Klasse mit Bean-Methoden |
@Bean | Config-Methode | Rückgabewert wird Bean |
25. Sind @Service und @Repository technisch unterschiedlich?
Technisch sind beide Spezialisierungen von @Component.
Beide können Beans registrieren.
Aber sie sind nicht nur Dekoration.
Wichtiger Unterschied:
@Servicesignalisiert Business-Logik-Rolle.@Repositorysignalisiert Persistence-Rolle und kann Exception Translation unterstützen.
Merksatz:
@Serviceund@Repositorysind beides Component-Stereotypen —@Repositoryhat aber spezielles Verhalten bei Persistence Exception Translation.
26. Standard-Bean-Name
Standardmäßig leitet Spring den Bean-Namen vom Klassennamen ab — erster Buchstabe klein.
Beispiel:
@Service
public class OrderService {
}
Standard-Bean-Name:
orderService
Weiteres Beispiel:
@Component
public class EmailSender {
}
Standard-Bean-Name:
emailSender
27. Eigener Bean-Name
Du kannst einen eigenen Namen setzen.
@Service("mainOrderService")
public class OrderService {
}
Bean-Name:
mainOrderService
Mit @Bean:
@Bean("utcClock")
public Clock clock() {
return Clock.systemUTC();
}
Bean-Name:
utcClock
28. Kann eine Klasse mehrere Beans haben?
Ja — aber nicht direkt mit einer @Component-Klasse.
Mit @Bean kannst du mehrere Beans desselben Typs erzeugen.
Beispiel:
@Configuration
public class ClockConfig {
@Bean
public Clock utcClock() {
return Clock.systemUTC();
}
@Bean
public Clock systemClock() {
return Clock.systemDefaultZone();
}
}
Jetzt hat Spring zwei Clock-Beans:
utcClock
systemClock
Braucht eine andere Bean Clock, weiß Spring vielleicht nicht, welche er injizieren soll.
Das erzeugt Mehrdeutigkeit.
Später löst du das mit:
@Primary
@Qualifier
29. Was passiert bei zwei Beans desselben Typs?
Beispiel:
@Bean
public Clock utcClock() {
return Clock.systemUTC();
}
@Bean
public Clock berlinClock() {
return Clock.system(ZoneId.of("Europe/Berlin"));
}
Und eine andere Klasse braucht:
public TimeService(Clock clock) {
this.clock = clock;
}
Problem:
Spring findet zwei Clock-Beans.
Spring weiß nicht, welche er injizieren soll.
App startet nicht.
Mögliche Lösungen:
- eine Bean als
@Primarymarkieren @Qualifiernutzen- per spezifischem Bean-Namen injizieren
List<Clock>injizieren, wenn du alle Beans willst
30. @Primary
@Primary sagt Spring:
Nimm diese Bean standardmäßig, wenn mehrere Kandidaten existieren.
Beispiel:
@Bean
@Primary
public Clock utcClock() {
return Clock.systemUTC();
}
@Bean
public Clock berlinClock() {
return Clock.system(ZoneId.of("Europe/Berlin"));
}
Jetzt funktioniert das:
public TimeService(Clock clock) {
this.clock = clock;
}
Spring injiziert utcClock.
31. @Qualifier
@Qualifier sagt Spring genau, welche Bean injiziert werden soll.
Beispiel:
public TimeService(@Qualifier("berlinClock") Clock clock) {
this.clock = clock;
}
Spring injiziert:
berlinClock
Auch wenn eine andere Bean @Primary ist — @Qualifier ist spezifischer.
Merksatz:
@Primaryist die Standardwahl.@Qualifierist die exakte Wahl.
32. Kann ich alle Beans eines Typs injizieren?
Ja.
Beispiel:
@Component
public class NotificationService {
private final List<NotificationSender> senders;
public NotificationService(List<NotificationSender> senders) {
this.senders = senders;
}
}
Wenn du hast:
@Component
public class EmailSender implements NotificationSender {
}
@Component
public class SmsSender implements NotificationSender {
}
injiziert Spring beide in die Liste.
Nützlich für Strategy-Patterns.
33. Kann eine Bean optional sein?
Ja.
Optionen:
Optional<MyService>
ObjectProvider<MyService>
@Nullable
Beispiel:
@Component
public class ReportService {
public ReportService(Optional<AuditService> auditService) {
}
}
Für feinere Kontrolle:
@Component
public class ReportService {
private final ObjectProvider<AuditService> auditServiceProvider;
public ReportService(ObjectProvider<AuditService> auditServiceProvider) {
this.auditServiceProvider = auditServiceProvider;
}
}
Nützlich, wenn die Abhängigkeit vielleicht nicht existiert.
34. Kann ich eine Bean manuell holen?
Ja — im normalen Business-Code aber meist nicht empfohlen.
Beispiel:
ApplicationContext context = SpringApplication.run(App.class, args);
OrderService orderService = context.getBean(OrderService.class);
Funktioniert — normalerweise bevorzugst du aber Constructor Injection.
Warum?
Weil Constructor Injection Abhängigkeiten sichtbar macht.
Schlechter Stil im Service-Code:
@Component
public class OrderService {
private final ApplicationContext context;
public OrderService(ApplicationContext context) {
this.context = context;
}
public void process() {
PaymentService paymentService = context.getBean(PaymentService.class);
}
}
Das versteckt Abhängigkeiten.
Besser:
@Component
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
35. Ist jede Bean ein Singleton?
Nein.
Der Standard-Scope ist singleton — Spring unterstützt aber verschiedene Scopes.
Gängige Scopes:
singleton
prototype
request
session
application
websocket
Heute merkst du dir:
Standard-Scope ist singleton.
Scopes schauen wir später genauer an.
36. Bedeutet Singleton das Java-Singleton-Pattern?
Nein.
Spring-Singleton heißt:
eine Bean-Instanz pro Spring-Container.
Java-Singleton-Pattern meist:
eine Instanz pro JVM, gesteuert über statischen Zugriff.
Das ist nicht dasselbe.
Prüfungsfalle:
Spring-Singleton ist nicht dasselbe wie das klassische Java-Singleton-Pattern.
37. Was passiert, wenn die Bean-Erzeugung fehlschlägt?
Kann Spring eine erforderliche Bean nicht erzeugen, startet die App meist nicht.
Beispiel:
@Service
public class OrderService {
public OrderService(OrderRepository orderRepository) {
}
}
Aber keine OrderRepository-Bean existiert.
Dann wirft Spring z. B.:
No qualifying bean of type 'OrderRepository' available
Nützlich — Fehler werden früh erkannt.
38. @Service gesetzt, Spring findet die Klasse trotzdem nicht?
Mögliche Gründe:
- Klasse liegt außerhalb des gescannten Packages.
- Klasse ist nicht public oder nicht instanziierbar.
- Konstruktor-Abhängigkeiten fehlen.
- Annotation aus falschem Package importiert.
- Profil-Bedingung passt nicht.
- Bean ist conditional und die Bedingung ist false.
Am häufigsten für Einsteiger:
Klasse liegt außerhalb des Component Scans.
39. Können Interfaces Beans sein?
Ein Interface allein ist meist keine Bean — Spring kann kein Interface instanziieren.
Beispiel:
public interface OrderRepository {
}
Das reicht nicht.
Spring braucht eine Implementierung:
@Repository
public class JpaOrderRepository implements OrderRepository {
}
Spring Data JPA ist speziell:
public interface OrderRepository extends JpaRepository<Order, Long> {
}
Spring Data erzeugt automatisch eine Proxy-Implementierung.
Das Repository-Interface kann also über Spring-Data-Infrastruktur zur Bean werden.
40. Können abstrakte Klassen Beans sein?
Meist nein — Spring kann keine abstrakte Klasse direkt instanziieren.
Beispiel:
@Component
public abstract class BaseService {
}
Das kann nicht als normale Bean erzeugt werden — die Klasse ist abstrakt.
Konkrete Subklassen können aber Beans sein.
41. Was ist ein Bean-Kandidat?
Ein Bean-Kandidat ist eine Bean, die Spring nutzen kann, um eine Abhängigkeit zu erfüllen.
Beispiel:
public OrderService(PaymentService paymentService) {
}
Spring sucht Beans vom Typ:
PaymentService
Alle passenden Beans sind Kandidaten.
Gibt es genau einen, injiziert Spring ihn.
Gibt es mehrere, braucht Spring mehr Information.
42. Was ist Autowiring?
Autowiring heißt: Spring löst Abhängigkeiten automatisch auf und injiziert sie.
Beispiel:
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
Spring sieht den Konstruktor-Parameter und injiziert automatisch eine OrderRepository-Bean.
In modernem Spring ist @Autowired bei nur einem Konstruktor optional.
43. Constructor Injection mit @Autowired
Alter oder expliziter Stil:
@Service
public class OrderService {
private final OrderRepository orderRepository;
@Autowired
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
Moderner Stil:
@Service
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
Beides funktioniert bei nur einem Konstruktor.
Prüfungsfalle:
@Autowiredauf einem einzigen Konstruktor ist in modernem Spring optional.
44. Field Injection
Field Injection:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
}
Funktioniert — ist aber nicht empfohlen.
Warum?
- Abhängigkeiten sind versteckt
- schwerer testbar
- Felder können nicht
finalsein - Objekt kann in ungültigem Zustand entstehen
- fördert schlechtes Design
Best Practice:
Constructor Injection bevorzugen.
45. Setter Injection
Setter Injection:
@Service
public class OrderService {
private OrderRepository orderRepository;
@Autowired
public void setOrderRepository(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
Setter Injection meist für optionale Abhängigkeiten.
Für erforderliche Abhängigkeiten: Constructor Injection.
46. Constructor vs. Setter vs. Field Injection
| Typ | Am besten für | Empfehlung |
|---|---|---|
| Constructor Injection | erforderliche Deps | am besten |
| Setter Injection | optionale Deps | akzeptabel |
| Field Injection | schnelle Demos/Tests | in Produktion meiden |
Merksatz:
Erforderliche Abhängigkeiten per Constructor injizieren.
47. Kleines Code-Beispiel
Erstelle dieses Mini-Beispiel:
public interface NotificationSender {
void send(String message);
}
@Component
public class EmailNotificationSender implements NotificationSender {
@Override
public void send(String message) {
System.out.println("Email: " + message);
}
}
@Service
public class OrderService {
private final NotificationSender notificationSender;
public OrderService(NotificationSender notificationSender) {
this.notificationSender = notificationSender;
}
public void createOrder() {
notificationSender.send("Order created");
}
}
Frage:
Warum kann Spring
EmailNotificationSenderinNotificationSenderinjizieren?
Antwort:
Weil EmailNotificationSender eine Spring Bean ist und NotificationSender implementiert. Spring kann per Interface-Typ injizieren, wenn es genau eine passende Implementierung gibt.
48. Code-Beispiel mit Mehrdeutigkeit
Jetzt hinzufügen:
@Component
public class SmsNotificationSender implements NotificationSender {
@Override
public void send(String message) {
System.out.println("SMS: " + message);
}
}
Jetzt hat Spring zwei Beans vom Typ NotificationSender:
emailNotificationSender
smsNotificationSender
Dieser Konstruktor ist mehrdeutig:
public OrderService(NotificationSender notificationSender) {
}
Spring weiß nicht, welche Bean er injizieren soll.
Fix:
public OrderService(
@Qualifier("emailNotificationSender") NotificationSender notificationSender
) {
this.notificationSender = notificationSender;
}
49. Prüfungsfallen
Falle 1
@Service, @Repository und @Controller sind Spezialisierungen von @Component.
Falle 2
@Repository kann Exception Translation bieten.
Falle 3
@RestController = @Controller + @ResponseBody.
Falle 4
Eine Klasse mit @Service ist keine Bean, wenn sie außerhalb des Component Scans liegt.
Falle 5
Ein mit new erzeugtes Objekt wird nicht automatisch von Spring verwaltet.
Falle 6
BeanDefinition = Metadaten. Bean = das echte Objekt.
Falle 7
@Bean ist nützlich für Drittanbieter-Klassen oder eigene Erzeugungslogik.
Falle 8
Mehrere Beans desselben Typs → Spring braucht @Primary, @Qualifier oder eine andere Auflösung.
Falle 9
@Autowired auf einem einzigen Konstruktor ist in modernem Spring optional.
Falle 10
Spring-Singleton = eine Instanz pro Container — nicht das klassische Java-Singleton-Pattern.
50. Interview-Antwort
Frage:
Was ist eine Spring Bean?
Gute Antwort:
Eine Spring Bean ist ein vom Spring IoC-Container verwaltetes Objekt. Spring erzeugt die Bean, injiziert Abhängigkeiten, konfiguriert sie und steuert den Lebenszyklus. Beans werden per Component Scanning mit Annotationen wie @Component, @Service und @Repository registriert — oder manuell über @Bean-Methoden in Konfigurationsklassen. Weil Spring das Objekt verwaltet, kann er auch AOP-Proxies, Transaktionen und Security anwenden. Ein normales Objekt mit new ist nicht automatisch eine Spring Bean.
51. Interview-Antwort
Frage:
Was ist der Unterschied zwischen
@Componentund@Bean?
Gute Antwort:
@Component steht auf einer Klasse und wird per Component Scanning gefunden — meist für eigene App-Klassen wie Services oder Helfer. @Bean steht auf einer Methode in einer Konfigurationsklasse; der Rückgabewert wird zur Spring Bean. @Bean ist nützlich für Drittanbieter-Objekte, manuelle Konfiguration oder wenn du die Klasse nicht direkt annotieren kannst.
52. Interview-Antwort
Frage:
Was ist der Unterschied zwischen
@Serviceund@Repository?
Gute Antwort:
Beide sind Stereotyp-Annotationen und Spezialisierungen von @Component — beide registrieren Spring Beans. Der Unterschied ist semantisch und technisch. @Service markiert Business-Logik im Service-Layer. @Repository markiert Persistence-Layer und kann Persistence Exception Translation in Springs DataAccessException-Hierarchie unterstützen.
53. Interview-Antwort
Frage:
Warum wird Constructor Injection empfohlen?
Gute Antwort:
Constructor Injection macht erforderliche Abhängigkeiten explizit. Felder können final sein, Immutability wird unterstützt, Tests werden einfacher. Das Objekt kann nicht ohne seine Pflicht-Abhängigkeiten entstehen. Field Injection versteckt Abhängigkeiten und erschwert Tests — deshalb bevorzugt man Constructor Injection in Produktionscode.
Übungsfragen
Frage 1
Was ist eine Spring Bean?
Antwort:
Ein vom Spring IoC-Container erzeugtes und verwaltetes Objekt. Spring kann es erzeugen, Abhängigkeiten injizieren, konfigurieren, den Lebenszyklus steuern und zusätzliches Verhalten anwenden: AOP-Proxies, Transaktionen, Security.
Frage 2
Was ist eine BeanDefinition?
Antwort:
Metadaten, die Spring sagen, wie eine Bean erzeugt und verwaltet werden soll: Bean-Klasse, Name, Scope, Abhängigkeiten, Konstruktor-Argumente, Init/Destroy-Methode, Lazy/Eager-Verhalten.
Frage 3
Unterschied BeanDefinition und Bean?
Antwort:
BeanDefinition ist das Rezept bzw. die Metadaten. Eine Bean ist das echte Objekt, das daraus entsteht und von Spring verwaltet wird.
Frage 4
Unterschied @Component und @Bean?
Antwort:
@Component steht auf einer Klasse und wird per Component Scanning gefunden. @Bean steht auf einer Methode in einer Konfigurationsklasse — der Rückgabewert wird zur Spring Bean.
Frage 5
Wann @Bean statt @Component?
Antwort:
Wenn die Klasse aus einer Drittanbieter-Lib kommt, du sie nicht ändern kannst oder die Erzeugung eigene Konfigurationslogik braucht.
Frage 6
Unterschied @Component, @Service und @Repository?
Antwort:
@Component ist generisch. @Service für Business-Logik im Service-Layer. @Repository für Persistence-Layer mit Datenzugriff.
Frage 7
Was ist besonders an @Repository?
Antwort:
@Repository kann Persistence Exception Translation unterstützen — DB-spezifische Exceptions werden in Springs DataAccessException-Hierarchie übersetzt.
Frage 8
Was enthält @RestController?
Antwort:
@Controller und @ResponseBody. Für REST-APIs, bei denen Rückgabewerte direkt in den HTTP-Response-Body geschrieben werden — meist als JSON.
Frage 9
Ist das eine Spring Bean?
OrderService service = new OrderService();
Antwort:
Nein. Mit new erzeugt — Spring verwaltet es nicht automatisch.
Frage 10
Wird diese Klasse automatisch eine Bean?
@Service
public class OrderService {
}
Antwort:
Sie kann eine Spring Bean werden, wenn sie in einem von Spring gescannten Package liegt.
Frage 11
Was kann verhindern, dass diese @Service-Klasse eine Bean wird?
@Service
public class OrderService {
}
Antwort:
Mögliche Gründe: außerhalb des gescannten Packages, fehlende Abhängigkeit, aktives Profil passt nicht, Bedingung ist false, Klasse nicht instanziierbar.
Frage 12
Was passiert bei zwei Beans desselben Typs ohne eindeutige Wahl?
Antwort:
Spring startet nicht — Mehrdeutigkeitsfehler. Auflösung mit @Primary, @Qualifier, spezifischerem Typ oder Collection-Injection.
Frage 13
Unterschied @Primary und @Qualifier?
Antwort:
@Primary markiert die Standard-Bean bei mehreren Kandidaten. @Qualifier wählt explizit eine bestimmte Bean — präziser.
Frage 14
Warum ist Constructor Injection besser als Field Injection?
Antwort:
Abhängigkeiten sind explizit, Felder können final sein, Immutability und Testbarkeit verbessern sich — das Objekt entsteht nicht ohne Pflicht-Abhängigkeiten.
Frage 15
Ist @Autowired auf einem einzigen Konstruktor nötig?
Antwort:
Nein. In modernem Spring ist es bei nur einem Konstruktor optional.
Frage 16
Kann ein Interface eine Spring Bean sein?
Antwort:
Ein Interface allein meist nicht — Spring kann es nicht instanziieren. Frameworks wie Spring Data JPA erzeugen aber Proxy-Implementierungen für Repository-Interfaces.
Frage 17
Kann Spring per Interface-Typ injizieren?
Antwort:
Ja — wenn es genau eine passende Implementierung gibt oder Mehrdeutigkeit mit @Primary oder @Qualifier aufgelöst ist.
Frage 18
Standard-Bean-Name für diese Klasse?
@Service
public class PaymentService {
}
Antwort:
paymentService
Spring nutzt den Klassennamen mit kleinem Anfangsbuchstaben.
Frage 19
Standard-Bean-Scope?
Antwort:
singleton
Frage 20
Ist Spring-Singleton dasselbe wie das Java-Singleton-Pattern?
Antwort:
Nein. Spring-Singleton = eine Instanz pro Spring-Container. Java-Singleton-Pattern = eine Instanz pro JVM über statischen Zugriff.
Merksätze zum Mitnehmen
- Spring Bean = vom Container verwaltetes Objekt.
BeanDefinitionist das Rezept. Bean ist das Objekt.@Componentsteht auf Klassen.@Beansteht auf Methoden.@Beanfür Drittanbieter oder eigene Erzeugungslogik.@Service= Business-Logik.@Repository= Persistence + Exception Translation.@RestController=@Controller+@ResponseBody.- Klasse muss im Component Scan liegen, um Bean zu werden.
- Mit
newerzeugte Objekte sind nicht automatisch Spring-verwaltet. - Constructor Injection bevorzugen.
@Autowiredauf einem Konstruktor ist optional.@Primary= Standard-Bean.@Qualifier= exakte Bean.- Standard-Scope ist singleton.
- Spring-Singleton ≠ Java-Singleton-Pattern.