1. IoC (Inversion of Control — Umkehrung der Kontrolle)
Idee:
Du erstellst Objekte nicht manuell (new), sondern ein Container (Spring) verwaltet ihre Erstellung und Verknüpfung.
👉 In der typischen Java:
class Car {
private Engine engine = new Engine(); // starre Kopplung
}👉 In Spring (durch DI):
@Component
class Engine {}
@Component
class Car {
private final Engine engine;
@Autowired
Car(Engine engine) { this.engine = engine; }
}⚡ Jetzt erstellt der Spring-Container Engine und Car.
2. DI (Dependency Injection — Abhängigkeitsinjektion)
Arten der DI:
- Über den Konstruktor (bessere Methode)
@Component
class UserService {
private final UserRepository repo;
@Autowired
UserService(UserRepository repo) { this.repo = repo; }
}- Über ein Feld (Anti-Pattern, wird aber gefunden)
@Component
class UserService {
@Autowired
private UserRepository repo;
}- Über einen Setter
@Component
class UserService {
private UserRepository repo;
@Autowired
public void setRepo(UserRepository repo) {
this.repo = repo;
}
}3. Beans (Behälter)
Bean = Objekt, das von Spring verwaltet wird.
👉 Erstellung eines Beans:
@Component
class MyService {}👉 Alternative (Java Config):
@Configuration
class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}4. ApplicationContext
Spring speichert alle Beans im ApplicationContext (Container). Beispiel für einen Start ohne Spring Boot:
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
MyService service = ctx.getBean(MyService.class);
service.doWork();In Spring Boot geschieht dies automatisch.
5. Lebenszyklus eines Beans
- Objekt erstellen
- Abhängigkeiten injizieren
- @PostConstruct aufrufen
- Nutzung
- Zerstörung (PreDestroy aufrufen)
@Component
class MyBean {
@PostConstruct
public void init() {
System.out.println("Bean initialisiert");
}
@PreDestroy
public void cleanup() {
System.out.println("Bean zerstört");
}
}6. Scope (Lebenszyklus von Beans)
- singleton (Standard) → ein Objekt pro Anwendung
- prototype → ein neues Objekt bei jeder Anfrage
- request (Web) → ein Objekt pro HTTP-Anfrage
- session (Web) → ein Objekt pro Sitzung
@Component
@Scope("prototype")
class PrototypeBean {}7. Spring Core Annotationen
| Annotation | Funktion |
|---|---|
| @Component | Bean-Komponente |
| @Service | Business-Logik |
| @Repository | DAO-Schicht (automatisch @Transactional) |
| @Controller | MVC-Controller |
| @RestController | Controller mit @ResponseBody |
| @Configuration | Konfigurationsklasse |
| @Bean | Bean innerhalb von @Configuration |
| @Autowired | Abhängigkeitsinjektion |
| @Qualifier | Bean-Spezifizierung, wenn mehrere vorhanden sind |
| @Value | Wert aus application.properties injizieren |
8. Konfigurationen (Java, XML, Annotationen)
Heute wird fast immer Java Config und Annotationen verwendet.
@Configuration
class MyConfig {
@Bean
public Engine engine() {
return new Engine();
}
}9. Profile (verschiedene Umgebungen)
application.properties:
spring.profiles.active=devDefinition eines Beans für ein bestimmtes Profil:
@Component
@Profile("dev")
class DevDatabaseConfig {}10. Best Practices
- ✅ Verwende Dependency Injection über den Konstruktor → einfacher zu testen, weniger Probleme mit null.
- ✅ Erstelle Klassen mit @Service → für Business-Logik, @Repository → für die Arbeit mit der Datenbank.
- ✅ Verwende @Autowired nur in Konstruktoren (nicht in Feldern).
- ✅ Überwache den Scope → Standardmäßig ist singleton besser.
- ✅ Verwende @Configuration und @Bean für komplexe Abhängigkeiten.