Zum Hauptinhalt springen

Woche 2, Tag 1 — Java-Konfiguration, @Configuration und @Bean im Detail

Ziel

Heute verstehst du, wie Spring-Konfiguration mit Java-Code funktioniert.

Die Kernfragen:

  1. Was ist Java-Konfiguration in Spring?
  2. Was macht @Configuration?
  3. Was macht @Bean?
  4. Was ist der Unterschied zwischen @Component und @Bean?
  5. Warum sind @Configuration-Klassen besonders?
  6. Was ist Proxying von @Configuration-Klassen?
  7. Was ist der Unterschied zwischen Full- und Lite-Configuration-Mode?
  8. Wann solltest du @Bean verwenden?
  9. Welche typischen Prüfungsfallen gibt es?

1. Kurz-Wiederholung aus Woche 1

In Woche 1 hast du gelernt:

  • Spring verwaltet Objekte — Beans.
  • ApplicationContext ist der zentrale Spring-Container.
  • BeanDefinition sind Metadaten zur Bean-Erzeugung.
  • Beans können per Component Scanning registriert werden.
  • Beans können auch mit @Bean registriert werden.
  • @Component steht auf Klassen.
  • @Bean steht auf Methoden.

Merksatz:


@Component is for class-based bean registration.
@Bean is for method-based bean registration.

Heute gehst du tiefer in @Configuration und @Bean.


2. Was ist Spring-Konfiguration?

Spring-Konfiguration sagt Spring:

Welche Objekte Beans sein sollen, wie sie erzeugt werden und wie sie verbunden werden.

Es gibt mehrere Wege, Spring zu konfigurieren:


1. XML configuration
2. Java configuration
3. Annotation-based configuration
4. Auto-configuration in Spring Boot

Modernes Spring nutzt meist:


Java configuration + annotations + Spring Boot auto-configuration

3. Was ist Java-Konfiguration?

Java-Konfiguration heißt: Spring Beans mit Java-Klassen definieren.

Beispiel:


@Configuration
public class AppConfig {

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}

Diese Klasse sagt Spring:


Create a Clock bean using this method.

Der Rückgabewert der Methode wird zur Spring Bean.


4. Warum es Java-Konfiguration gibt

Vor Annotation-basierter und Java-basierter Konfiguration nutzte Spring oft XML.

Beispiel-Idee:


<bean id="clock" class="java.time.Clock" />

Moderne Java-Konfiguration ist einfacher, weil sie:

  • typsicher ist
  • Refactoring unterstützt
  • normalen Java-Code nutzt
  • Bedingungen und Logik enthalten kann
  • gut mit IDE-Support funktioniert
  • große XML-Dateien vermeidet

5. Was ist @Configuration?

@Configuration markiert eine Klasse als Quelle von Bean-Definitionen.

Beispiel:


@Configuration
public class TimeConfig {

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}

Einfache Definition:

@Configuration sagt Spring, dass diese Klasse Bean-Definitionen enthält.

Prüfungsdefinition:

@Configuration markiert eine Klasse als Konfigurationsklasse. Spring verarbeitet sie und registriert Bean-Definitionen aus ihren @Bean-Methoden.


6. Was ist @Bean?

@Bean markiert eine Methode, deren Rückgabewert eine Spring Bean werden soll.

Beispiel:


@Bean
public Clock clock() {
return Clock.systemUTC();
}

Spring macht Folgendes:


1. Calls the clock() method.
2. Takes the returned Clock object.
3. Registers it as a Spring bean.
4. Manages that object inside the ApplicationContext.

Standard-Bean-Name:


clock

Bean-Typ:


Clock

7. @Bean-Methodenname und Bean-Name

Standardmäßig wird der Methodenname zum Bean-Namen.

Beispiel:


@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}

Bean-Name:


objectMapper

Bean-Typ:


ObjectMapper

8. Benutzerdefinierter Bean-Name

Du kannst einen eigenen Bean-Namen vergeben.


@Bean("customObjectMapper")
public ObjectMapper objectMapper() {
return new ObjectMapper();
}

Bean-Name:


customObjectMapper

Du kannst auch nutzen:


@Bean(name = "customObjectMapper")

oder mehrere Namen:


@Bean(name = {"customObjectMapper", "jsonMapper"})

9. Wann solltest du @Bean verwenden?

Nutze @Bean, wenn:

  • die Klasse aus einer Drittanbieter-Library kommt
  • du die Klasse nicht ändern kannst
  • die Objekterzeugung eigene Logik braucht
  • du Konstruktor-Argumente manuell konfigurieren musst
  • du eine Factory-Methode aufrufen musst
  • du Werte aus Properties wählen musst
  • du mehrere Beans desselben Typs erzeugen musst

Beispiel:


@Configuration
public class TimeConfig {

@Bean
public Clock utcClock() {
return Clock.systemUTC();
}

@Bean
public Clock berlinClock() {
return Clock.system(ZoneId.of("Europe/Berlin"));
}
}

Das erzeugt zwei Clock-Beans.


10. @Component vs. @Bean

Das ist sehr wichtig für die Prüfung.

Thema@Component@Bean
Verwendet aufKlasseMethode
ObjekterzeugungSpring erzeugt die Klasse direktMethode erzeugt und gibt Objekt zurück
Am besten füreigene KlassenDrittanbieter-/Custom-Objekte
AuffindbarkeitComponent ScanningVerarbeitung der Konfigurationsklasse
BeispielTaskServiceClock, ObjectMapper, RestTemplate
Eigene Erzeugungslogikbegrenztsehr flexibel

11. Beispiel: @Component für eigene Klasse


@Service
public class TaskService {

public void createTask() {
System.out.println("Task created");
}
}

Das ist deine Klasse.

Du kannst sie direkt annotieren.

Also ist @Service / @Component passend.


12. Beispiel: @Bean für Drittanbieter-Klasse


@Configuration
public class JsonConfig {

@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
return mapper;
}
}

ObjectMapper kommt von Jackson.

Du besitzt die Klasse nicht.

Du kannst also kein @Component darauf setzen.

@Bean ist die richtige Wahl.


13. Beispiel: @Bean mit Abhängigkeiten

Eine @Bean-Methode kann andere Beans als Parameter erhalten.

Beispiel:


@Configuration
public class ServiceConfig {

@Bean
public TaskService taskService(TaskRepository taskRepository) {
return new TaskService(taskRepository);
}
}

Spring sieht, dass taskService() ein TaskRepository braucht.

Also injiziert Spring die TaskRepository-Bean in die Methode.

Das ist auch Dependency Injection.


14. Abhängigkeitsfluss bei @Bean-Methoden

Beispiel:


@Configuration
public class AppConfig {

@Bean
public OrderRepository orderRepository() {
return new OrderRepository();
}

@Bean
public OrderService orderService(OrderRepository orderRepository) {
return new OrderService(orderRepository);
}
}

Spring-Ablauf:


1. Register BeanDefinition for orderRepository.
2. Register BeanDefinition for orderService.
3. Create OrderRepository bean.
4. Call orderService(orderRepository).
5. Inject OrderRepository into OrderService.
6. Register OrderService as a bean.

15. Direkte Methodenaufrufe innerhalb von @Configuration

Das ist ein sehr wichtiges Prüfungsthema.

Beispiel:


@Configuration
public class AppConfig {

@Bean
public OrderRepository orderRepository() {
return new OrderRepository();
}

@Bean
public OrderService orderService() {
return new OrderService(orderRepository());
}
}

Auf den ersten Blick sieht es so aus, als würde das ein neues OrderRepository manuell erzeugen.

Weil die Klasse aber mit @Configuration annotiert ist, erweitert Spring sie mit einem Proxy.

Wenn orderService() also orderRepository() aufruft, gibt Spring die verwaltete Singleton-Bean zurück.

Kein neues Objekt.


16. Warum @Configuration-Klassen besonders sind

@Configuration-Klassen werden von Spring mit CGLIB-Proxying erweitert.

Das heißt: Spring kann Aufrufe von @Bean-Methoden abfangen.

Beispiel:


orderRepository()

innerhalb derselben Konfigurationsklasse verhält sich nicht wie ein normaler Java-Methodenaufruf.

Spring fängt ihn ab und gibt die verwaltete Bean aus dem Container zurück.

So bleibt das Singleton-Verhalten erhalten.


17. Normales Java-Verhalten

In normalem Java:


public OrderRepository orderRepository() {
return new OrderRepository();
}

public OrderService orderService() {
return new OrderService(orderRepository());
}

Jedes Mal, wenn du aufrufst:


orderRepository()

wird ein neues Objekt erzeugt.


18. Spring-@Configuration-Verhalten

Mit:


@Configuration

erweitert Spring die Klasse.

Also erzeugt:


return new OrderService(orderRepository());

nicht unbedingt jedes Mal ein neues Repository.

Stattdessen gibt Spring die verwaltete Singleton-OrderRepository-Bean zurück.

Merksatz:

Full @Configuration classes proxy @Bean methods to preserve singleton behavior.


19. Full Configuration Mode

Eine Klasse mit @Configuration läuft im Full Configuration Mode.

Beispiel:


@Configuration
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Spring proxied die Konfigurationsklasse.

Der Aufruf von a() innerhalb von b() gibt die verwaltete Bean zurück.

Das schützt das Singleton-Verhalten.


20. Lite Configuration Mode

Eine Klasse kann auch @Bean-Methoden ohne @Configuration haben.

Beispiel:


@Component
public class AppConfigLite {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Das kann trotzdem Beans registrieren.

Aber es ist kein Full Configuration Mode.

Spring proxied die Klasse nicht auf dieselbe Weise.

Der Aufruf von a() innerhalb von b() ist ein normaler Java-Methodenaufruf.

Das kann ein neues Objekt erzeugen.


21. Full vs. Lite Configuration

ThemaFull modeLite mode
Annotation@Configuration@Component mit @Bean, oder andere Fälle
Proxy erweitert?jakein vollständiges Enhancement
Aufrufe zwischen Bean-Methoden abgefangen?janein
Singleton bei direktem Methodenaufruf erhalten?janicht garantiert
Am besten für Konfigurationsklassenjanur für einfache Fälle

Merksatz für die Prüfung:

Use @Configuration for classes with @Bean methods, especially when one @Bean method calls another.


22. Wichtig: Methodenparameter bevorzugen

Statt:


@Bean
public OrderService orderService() {
return new OrderService(orderRepository());
}

lieber:


@Bean
public OrderService orderService(OrderRepository orderRepository) {
return new OrderService(orderRepository);
}

Warum?

Weil Abhängigkeiten explizit sind.

Es ist auch leichter zu verstehen und weniger abhängig vom internen Methodenaufruf-Verhalten.


23. @Configuration(proxyBeanMethods = false)

Modernes Spring Boot nutzt oft:


@Configuration(proxyBeanMethods = false)

Das deaktiviert das Proxying von @Bean-Methoden.

Warum?

Performance-Optimierung.

Aber dann werden direkte Aufrufe zwischen @Bean-Methoden nicht abgefangen.

Beispiel:


@Configuration(proxyBeanMethods = false)
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Hier ist a() innerhalb von b() ein normaler Methodenaufruf.

Er kann ein neues A erzeugen — getrennt von der Spring-verwalteten A-Bean.

Wenn also proxyBeanMethods = false, bevorzuge Methodenparameter-Injection:


@Bean
public B b(A a) {
return new B(a);
}

24. @Configuration(proxyBeanMethods = true)

Standardverhalten:


@Configuration

ist im Grunde:


@Configuration(proxyBeanMethods = true)

Das heißt: Spring proxied @Bean-Methoden.

Nützlich, wenn @Bean-Methoden sich gegenseitig direkt aufrufen.


25. Typische Prüfungsfalle: proxyBeanMethods

Frage:


@Configuration(proxyBeanMethods = false)
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Erhält b() garantiert die Spring-verwaltete Singleton-A-Bean?

Antwort:

Nein. Mit proxyBeanMethods = false fängt Spring den direkten Methodenaufruf nicht ab. a() verhält sich wie ein normaler Java-Methodenaufruf innerhalb von b() — es kann ein separates A-Objekt erzeugen.

Besser:


@Bean
public B b(A a) {
return new B(a);
}

26. @Bean und Scope

Standardmäßig sind Beans Singleton.

Beispiel:


@Bean
public Clock clock() {
return Clock.systemUTC();
}

Das erzeugt eine Clock-Bean pro Spring-Container.

Scope ändern:


@Bean
@Scope("prototype")
public MyObject myObject() {
return new MyObject();
}

Fürs Erste merken:


Default bean scope is singleton.

27. @Bean und Lifecycle-Methoden

Du kannst Init- und Destroy-Methoden definieren.

Beispiel:


@Bean(initMethod = "init", destroyMethod = "cleanup")
public ExternalClient externalClient() {
return new ExternalClient();
}

Beispielklasse:


public class ExternalClient {

public void init() {
System.out.println("Connecting...");
}

public void cleanup() {
System.out.println("Disconnecting...");
}
}

Spring ruft auf:


init after bean creation
cleanup when context closes

28. @Bean und @Primary

Wenn mehrere Beans desselben Typs existieren, kann eine primär sein.


@Configuration
public class ClockConfig {

@Bean
@Primary
public Clock utcClock() {
return Clock.systemUTC();
}

@Bean
public Clock berlinClock() {
return Clock.system(ZoneId.of("Europe/Berlin"));
}
}

Wenn eine Klasse braucht:


public TimeService(Clock clock) {
}

injiziert Spring utcClock.


29. @Bean und @Qualifier

Nutze @Qualifier, um eine bestimmte Bean auszuwählen.


@Service
public class TimeService {

private final Clock clock;

public TimeService(@Qualifier("berlinClock") Clock clock) {
this.clock = clock;
}
}

Das injiziert:


berlinClock

30. Mehrere Beans desselben Typs

Beispiel:


@Configuration
public class PaymentConfig {

@Bean
public PaymentProvider stripePaymentProvider() {
return new StripePaymentProvider();
}

@Bean
public PaymentProvider paypalPaymentProvider() {
return new PaypalPaymentProvider();
}
}

Wenn du injizierst:


public CheckoutService(PaymentProvider paymentProvider) {
}

weiß Spring nicht, welche es injizieren soll.

Lösungen:


1. @Primary
2. @Qualifier
3. Inject List<PaymentProvider>
4. Inject Map<String, PaymentProvider>
5. Use a more specific type

31. @Import

Manchmal willst du eine Konfigurationsklasse explizit importieren.

Beispiel:


@Configuration
@Import(TimeConfig.class)
public class AppConfig {
}

Das registriert TimeConfig, auch wenn sie nicht per Component Scanning gefunden wird.

Nützliche Idee:

@Import brings another configuration class into the application context.


32. @Configuration und Component Scanning

@Configuration ist selbst ein Spring-Stereotyp.

Diese Klasse kann also per Component Scanning gefunden werden:


@Configuration
public class TimeConfig {
}

Liegt sie im Scan-Pfad, findet Spring sie.

Dann verarbeitet Spring ihre @Bean-Methoden.

Liegt sie außerhalb des Scan-Pfads und wird nicht importiert, verarbeitet Spring sie nicht.


33. Echte Frage: Wird diese Bean erzeugt?


package com.example.config;

@Configuration
public class TimeConfig {

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}

Main-Klasse:


package com.example.app;

@SpringBootApplication
public class MyApplication {
}

Wird clock erzeugt?

Antwort:

Standardmäßig nicht.

Spring Boot scannt ab:


com.example.app

Aber TimeConfig liegt in:


com.example.config

Das ist kein Subpackage von com.example.app.

Also wird TimeConfig nicht gescannt, und ihre @Bean-Methode wird nicht verarbeitet.


34. Wie du es behebst

Beste Lösung:

Main-Klasse ins Root-Package verschieben:


package com.example;

@SpringBootApplication
public class MyApplication {
}

Dann scannt Spring:


com.example.app
com.example.config

Alternative:


@SpringBootApplication(scanBasePackages = "com.example")
public class MyApplication {
}

Oder:


@Import(TimeConfig.class)

35. @Bean vs. Auto-Konfiguration

Spring Boot Auto-Konfiguration erzeugt oft Beans für dich.

Du kannst aber deine eigene Bean definieren, um das Verhalten anzupassen.

Beispiel:

Spring Boot konfiguriert vielleicht automatisch einen ObjectMapper.

Wenn du aber deinen eigenen definierst:


@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper().findAndRegisterModules();
}

tritt Spring Boot je nach Auto-Konfigurationsbedingung zurück.

Das basiert oft auf:


@ConditionalOnMissingBean

Merksatz:

My custom bean can override or replace Boot’s auto-configured bean when auto-configuration backs off.


36. Echte Prüfungsfrage: @ConditionalOnMissingBean

Spring Boot Auto-Konfiguration sagt oft:


Create this bean only if the user has not already defined one.

Das wird häufig implementiert mit:


@ConditionalOnMissingBean

Beispiel-Idee:


@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new DefaultSomeService();
}

Wenn du bereits deinen eigenen SomeService definierst, erzeugt Spring Boot nicht den Default.


37. @Bean für umgebungsspezifische Konfiguration

Du kannst @Bean mit @Profile kombinieren.

Beispiel:


@Configuration
public class EmailConfig {

@Bean
@Profile("dev")
public EmailSender fakeEmailSender() {
return new FakeEmailSender();
}

@Bean
@Profile("prod")
public EmailSender realEmailSender() {
return new RealEmailSender();
}
}

Ist das Profil dev, erzeugt Spring fakeEmailSender.

Ist das Profil prod, erzeugt Spring realEmailSender.


38. @Bean für bedingte Konfiguration

Du kannst Beans bedingt erzeugen.

Beispiel:


@Bean
@ConditionalOnProperty(
name = "feature.audit.enabled",
havingValue = "true"
)
public AuditService auditService() {
return new AuditService();
}

Diese Bean wird nur erzeugt, wenn:


feature.audit.enabled=true

Das ist eher Spring-Boot-spezifisch, aber nützlich zum Verständnis der Auto-Konfiguration.


39. Häufige @Bean-Nutzung in der Praxis

Häufig mit @Bean erzeugte Dinge:


Clock
ObjectMapper
RestTemplate
WebClient
PasswordEncoder
SecurityFilterChain
CorsConfigurationSource
CommandLineRunner
ApplicationRunner
DataSource customization
External API clients

Beispiel:


@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Das ist sehr häufig in Spring Security.


40. Praxisbeispiel: PasswordEncoder


@Configuration
public class SecurityConfig {

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

Dann kann eine andere Bean ihn injizieren:


@Service
public class UserService {

private final PasswordEncoder passwordEncoder;

public UserService(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
}

Spring erzeugt die PasswordEncoder-Bean und injiziert sie in UserService.


41. Praxisbeispiel: Clock für Testbarkeit

Schlecht:


public class TaskService {

public boolean isOverdue(Task task) {
return task.deadline().isBefore(LocalDate.now());
}
}

Das ist schwer testbar, weil LocalDate.now() von der echten Zeit abhängt.

Besser:


@Service
public class TaskService {

private final Clock clock;

public TaskService(Clock clock) {
this.clock = clock;
}

public boolean isOverdue(Task task) {
return task.deadline().isBefore(LocalDate.now(clock));
}
}

Konfiguration:


@Configuration
public class TimeConfig {

@Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
}

In Tests kannst du Clock durch eine feste Uhr ersetzen.

Das ist ein sehr professioneller Einsatz von @Bean.


42. Praxisbeispiel: External-API-Client


@Configuration
public class ExternalApiConfig {

@Bean
public TaxApiClient taxApiClient(
@Value("${tax-api.base-url}") String baseUrl
) {
return new TaxApiClient(baseUrl);
}
}

Das ist nützlich, weil das Objekt Konfiguration aus Properties braucht.


43. Typische Prüfungsfalle: Rückgabetyp der @Bean-Methode

Der deklarierte Rückgabetyp ist wichtig für die Injection.

Beispiel:


@Bean
public PaymentProvider paymentProvider() {
return new StripePaymentProvider();
}

Spring kennt diese Bean als Typ:


PaymentProvider

und intern auch als tatsächlichen Implementierungstyp.

Für Klarheit: gib den nützlichsten Typ zurück.

Brauchst du implementierungsspezifische Methoden, kannst du den Implementierungstyp zurückgeben:


@Bean
public StripePaymentProvider stripePaymentProvider() {
return new StripePaymentProvider();
}

Best Practice:

Return an interface when consumers should depend on abstraction. Return concrete type when specific configuration needs it.


44. Typische Prüfungsfalle: private @Bean-Methoden

@Bean-Methoden sollten nicht privat sein.

Spring muss sie verarbeiten können.

Nutze normalerweise public oder package-private Methoden.

Üblicher Stil:


@Bean
public Clock clock() {
return Clock.systemUTC();
}

45. Typische Prüfungsfalle: finale @Configuration-Klasse

Weil Spring @Configuration-Klassen mit CGLIB proxien kann, sind finale Konfigurationsklassen problematisch, wenn Proxying aktiv ist.

Vermeide:


@Configuration
public final class AppConfig {
}

Vermeide auch finale @Bean-Methoden, wenn Proxying nötig ist.

Merksatz:

Full @Configuration relies on proxying, so final classes or methods can break proxy behavior.


46. Typische Prüfungsfalle: @Bean-Methoden manuell aufrufen

Außerhalb von Spring ist ein direkter Aufruf einer @Bean-Methode nur ein normaler Java-Methodenaufruf.

Beispiel:


AppConfig config = new AppConfig();
Clock clock = config.clock();

Dieses Objekt wird nicht unbedingt von Spring verwaltet.

Für eine Spring-verwaltete Bean nutze den Context:


Clock clock = applicationContext.getBean(Clock.class);

47. Prüfungsfrage: @Bean

Frage:


@Configuration
public class AppConfig {

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}

Wie lautet der Bean-Name?

Antwort:

Der Standard-Bean-Name ist:


clock

Der Methodenname wird zum Bean-Namen.


48. Prüfungsfrage: @Configuration

Frage:

Was macht @Configuration?

Antwort:

@Configuration markiert eine Klasse als Quelle von Spring Bean-Definitionen. Spring verarbeitet die Klasse und registriert Beans aus ihren @Bean-Methoden. Full-@Configuration-Klassen werden außerdem mit Proxies erweitert, damit Aufrufe zwischen Bean-Methoden verwaltete Singleton-Beans zurückgeben können.


49. Prüfungsfrage: @Bean-Parameter

Frage:


@Bean
public OrderService orderService(OrderRepository orderRepository) {
return new OrderService(orderRepository);
}

Woher kommt orderRepository?

Antwort:

Spring löst es aus dem Application Context auf. Es sucht eine Bean vom Typ OrderRepository und übergibt sie der @Bean-Methode.


50. Prüfungsfrage: Full Configuration

Frage:


@Configuration
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Erhält b() die verwaltete Singleton-A-Bean?

Antwort:

Ja. Im Full-@Configuration-Mode proxied Spring die Konfigurationsklasse und fängt Aufrufe von @Bean-Methoden ab. Der Aufruf von a() gibt die verwaltete Singleton-Bean zurück.


51. Prüfungsfrage: Lite Configuration

Frage:


@Component
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Wird der Aufruf von a() innerhalb von b() wie bei Full-@Configuration abgefangen?

Antwort:

Nein. Das ist Lite Configuration Mode. Der direkte Aufruf von a() ist ein normaler Java-Methodenaufruf — er kann ein separates Objekt erzeugen.


52. Prüfungsfrage: proxyBeanMethods = false

Frage:


@Configuration(proxyBeanMethods = false)
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Was ist das Risiko?

Antwort:

Weil proxyBeanMethods = false, fängt Spring direkte Aufrufe zwischen @Bean-Methoden nicht ab. Der Aufruf von a() innerhalb von b() kann ein neues A-Objekt erzeugen, statt die verwaltete Singleton-A-Bean zu nutzen.


53. Prüfungsfrage: Besserer Stil

Frage:

Welcher Stil ist besser?

Option A:


@Bean
public B b() {
return new B(a());
}

Option B:


@Bean
public B b(A a) {
return new B(a);
}

Antwort:

Option B ist meist besser, weil die Abhängigkeit explizit ist und Spring die verwaltete A-Bean als Methodenparameter injiziert. So musst du nicht auf direkte @Bean-Methodenaufrufe vertrauen.


54. Prüfungsfrage: Config außerhalb des Scans

Frage:

Wenn eine Klasse mit @Configuration außerhalb des Component Scans liegt — werden ihre @Bean-Methoden verarbeitet?

Antwort:

Nein, nicht automatisch. Die Konfigurationsklasse muss bei Spring registriert sein — per Component Scanning, @Import oder einem anderen expliziten Registrierungsmechanismus.


55. Interview-Antwort

Frage:

What is Java configuration in Spring?

Gute Antwort:

Java-Konfiguration heißt: Spring Beans mit Java-Klassen und Annotationen statt XML definieren. Eine Klasse mit @Configuration kann Methoden mit @Bean enthalten. Spring verarbeitet diese Methoden und registriert ihre Rückgabewerte als Beans im Application Context. Der Ansatz ist typsicher, refactoring-freundlich und in modernen Spring-Anwendungen üblich.


56. Interview-Antwort

Frage:

What is the difference between @Component and @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-Klassen, eigene Objekterzeugung oder wenn du mehr Kontrolle über den Aufbau brauchst.


57. Interview-Antwort

Frage:

Why are @Configuration classes proxied?

Gute Antwort:

Full-@Configuration-Klassen werden proxied, damit Spring Aufrufe von @Bean-Methoden abfangen kann. So bleibt das Singleton-Verhalten erhalten, wenn eine @Bean-Methode eine andere aufruft. Ohne Proxying wäre ein direkter @Bean-Methodenaufruf ein normaler Java-Methodenaufruf — er könnte ein neues Objekt erzeugen statt die verwaltete Spring Bean zurückzugeben.


58. Interview-Antwort

Frage:

What does @Configuration(proxyBeanMethods = false) mean?

Gute Antwort:

@Configuration(proxyBeanMethods = false) deaktiviert das Proxying von @Bean-Methoden. Das kann die Start-Performance verbessern, bedeutet aber: direkte Aufrufe zwischen @Bean-Methoden werden von Spring nicht abgefangen. Hängt eine Bean von einer anderen ab, nutze daher lieber Methodenparameter statt einen direkten @Bean-Methodenaufruf.


59. Tiny Code Practice

Erstelle das:


@Configuration
public class TimeConfig {

@Bean
public Clock clock() {
return Clock.systemUTC();
}
}

Dann injiziere es:


@Service
public class DeadlineService {

private final Clock clock;

public DeadlineService(Clock clock) {
this.clock = clock;
}

public LocalDate today() {
return LocalDate.now(clock);
}
}

Frage:

Why is this better than calling LocalDate.now() directly?

Antwort:

Weil die Injection von Clock den Code leichter testbar macht. In Tests kannst du die echte Uhr durch eine feste Uhr ersetzen.


60. Tiny Bug Practice

Problem:


@Configuration(proxyBeanMethods = false)
public class AppConfig {

@Bean
public A a() {
return new A();
}

@Bean
public B b() {
return new B(a());
}
}

Frage:

What is the problem?

Antwort:

Weil proxyBeanMethods = false, wird der Aufruf von a() innerhalb von b() nicht abgefangen. Er kann ein neues A erzeugen statt die Spring-verwaltete A-Bean zu nutzen.

Besser:


@Bean
public B b(A a) {
return new B(a);
}

Übungsfragen

Frage 1

Was ist Java-Konfiguration in Spring?

Antwort:

Java-Konfiguration heißt: Spring Beans mit Java-Klassen und Annotationen statt XML definieren. Eine Konfigurationsklasse kann @Configuration und @Bean-Methoden nutzen, um Beans zu registrieren.


Frage 2

Was macht @Configuration?

Antwort:

@Configuration markiert eine Klasse als Quelle von Spring Bean-Definitionen. Spring verarbeitet die Klasse und registriert Beans aus ihren @Bean-Methoden.


Frage 3

Was macht @Bean?

Antwort:

@Bean markiert eine Methode, deren Rückgabewert als Spring Bean registriert werden soll.


Frage 4

Wie lautet der Standard-Bean-Name für diese Methode?


@Bean
public Clock clock() {
return Clock.systemUTC();
}

Antwort:

Der Standard-Bean-Name ist:


clock

Der Methodenname wird zum Bean-Namen.


Frage 5

Wie kann ich einen benutzerdefinierten Bean-Namen vergeben?

Antwort:

So kannst du einen eigenen Bean-Namen vergeben:


@Bean("utcClock")
public Clock clock() {
return Clock.systemUTC();
}

Frage 6

Wann solltest du @Bean statt @Component verwenden?

Antwort:

Nutze @Bean für Drittanbieter-Klassen, Klassen die du nicht ändern kannst, eigene Erzeugungslogik, Objekte die Properties brauchen, Factory-Methoden oder mehrere Beans desselben Typs.


Frage 7

Was ist der Unterschied zwischen @Component und @Bean?

Antwort:

@Component steht auf einer Klasse und wird per Component Scanning gefunden. @Bean steht auf einer Methode — der Rückgabewert wird zur Spring Bean.


Frage 8

Kann eine @Bean-Methode Abhängigkeiten als Parameter erhalten?

Antwort:

Ja. Eine @Bean-Methode kann Abhängigkeiten als Methodenparameter erhalten.


Frage 9

Woher holt Spring den Parameter für eine @Bean-Methode?

Antwort:

Spring löst den Parameter aus dem Application Context auf, indem es eine passende Bean findet.


Frage 10

Warum werden Full-@Configuration-Klassen proxied?

Antwort:

Full-@Configuration-Klassen werden proxied, damit Spring Aufrufe von @Bean-Methoden abfangen und verwaltete Singleton-Beans zurückgeben kann — statt neue Objekte zu erzeugen.


Frage 11

Was passiert, wenn eine @Bean-Methode innerhalb einer Full-@Configuration-Klasse eine andere aufruft?

Antwort:

Im Full Configuration Mode wird der Aufruf von Spring abgefangen und gibt die verwaltete Bean aus dem Container zurück.


Frage 12

Warum werden Full-@Configuration-Klassen proxied?

Antwort:

Full-@Configuration-Klassen werden proxied, damit Spring Aufrufe zwischen @Bean-Methoden abfangen kann. So bleibt das Singleton-Verhalten erhalten: ein direkter Methodenaufruf gibt die verwaltete Bean zurück — kein neues Objekt.


Frage 13

Was ist das Risiko des Lite Configuration Mode?

Antwort:

Das Risiko: direkte Aufrufe zwischen @Bean-Methoden sind normale Java-Methodenaufrufe und können neue Objekte erzeugen statt verwaltete Singleton-Beans zurückzugeben.


Frage 14

Was bedeutet @Configuration(proxyBeanMethods = false)?

Antwort:

@Configuration(proxyBeanMethods = false) deaktiviert das Proxying von @Bean-Methoden.


Frage 15

Was ist das Risiko von proxyBeanMethods = false?

Antwort:

Das Risiko: direkte Aufrufe zwischen @Bean-Methoden werden nicht abgefangen — sie können separate Objekte erzeugen statt verwaltete Spring Beans zu nutzen.


Frage 16

Welcher Stil ist besser und warum?


@Bean
public B b() {
return new B(a());
}

oder


@Bean
public B b(A a) {
return new B(a);
}

Antwort:

Dieser Stil ist meist besser:


@Bean
public B b(A a) {
return new B(a);
}

weil die Abhängigkeit explizit ist und Spring die verwaltete A-Bean als Methodenparameter injiziert.


Frage 17

Was muss passieren, damit eine @Configuration-Klasse verarbeitet wird?

Antwort:

Die Konfigurationsklasse muss bei Spring registriert sein — meist per Component Scanning, @Import oder direkter Registrierung.


Frage 18

Was macht @Import?

Antwort:

@Import importiert explizit eine andere Konfigurationsklasse in den Application Context.


Frage 19

Wie kann @Bean mit @Profile zusammenarbeiten?

Antwort:

@Bean kann mit @Profile kombiniert werden, sodass eine Bean nur erzeugt wird, wenn ein bestimmtes Profil aktiv ist.


Frage 20

Warum ist Clock oft ein guter Kandidat für @Bean?

Antwort:

Clock ist ein guter Kandidat für @Bean, weil zeitbasierte Logik damit testbar wird. In Produktion nutzt du eine echte Systemuhr — in Tests ersetzt du sie durch eine feste Uhr.


Merksätze zum Mitnehmen

  • Java-Konfiguration definiert Spring Beans mit Java-Code.
  • @Configuration markiert eine Klasse als Quelle von Bean-Definitionen.
  • @Bean markiert eine Methode, deren Rückgabewert zur Spring Bean wird.
  • Der Standard-Bean-Name ist der @Bean-Methodenname.
  • Nutze @Bean für Drittanbieter-Objekte oder eigene Erzeugungslogik.
  • @Component steht auf Klassen.
  • @Bean steht auf Methoden.
  • Eine @Bean-Methode kann Abhängigkeiten als Parameter erhalten.
  • Full-@Configuration-Klassen werden proxied.
  • Proxying erhält das Singleton-Verhalten bei Aufrufen zwischen Bean-Methoden.
  • Lite Configuration Mode fängt direkte @Bean-Methodenaufrufe nicht ab.
  • @Configuration(proxyBeanMethods = false) deaktiviert Proxying.
  • Bevorzuge Methodenparameter statt direkter Aufrufe zwischen @Bean-Methoden.
  • Eine Konfigurationsklasse muss registriert sein, damit ihre @Bean-Methoden verarbeitet werden.
  • @Import kann eine andere Konfigurationsklasse explizit registrieren.
  • @Bean kann mit @Profile oder Bedingungen kombiniert werden.