Service Locator und manuelle Registrierung
Der Aufrufer holt die Abhängigkeit zur Laufzeit aus einer globalen Registry.
Vollständiger Legacy-Modern-Vergleich aller Java-Klassen, Tests, Maven-POMs und relevanten Ressourcen dieses Moduls. Jede Datei ist genau einmal einer fachlich passenden Vergleichsgruppe zugeordnet.
Der Aufrufer holt die Abhängigkeit zur Laufzeit aus einer globalen Registry.
Der Container übergibt den fachlichen Port sichtbar über den Konstruktor.
Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.
| Vergleichsgruppe | Legacy-Dateien | Modern-Dateien | Legacy-Zeilen | Modern-Zeilen | Ähnlichkeit |
|---|---|---|---|---|---|
| Build-Konfiguration | 1 | 1 | 31 | 38 | 52% |
| Bootstrap und Ausführung | 1 | 2 | 12 | 30 | 25% |
| Service-Vertrag und Implementierung | 2 | 2 | 13 | 18 | 63% |
| Auflösung und Test | 2 | 1 | 36 | 11 | 35% |
Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.
Abhängigkeiten und Compiler-/Testkonfiguration werden direkt verglichen.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| pom.xml | pom.xml | Direktvergleich Semantische Ähnlichkeit: 52% |
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>01dependencyinjection-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>di-legacy</artifactId>
<packaging>jar</packaging>
<name>DI Legacy</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>01dependencyinjection-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>di-modern</artifactId>
<packaging>jar</packaging>
<name>DI Modern</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>Manueller Start wird durch Spring Boot und einen injizierten Runner ersetzt.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| DiLegacyApplication.java | DiModernApplication.java GreetingRunner.java | Direktvergleich Semantische Ähnlichkeit: 25% |
package at.aydin.lab.di.legacy;
public final class DiLegacyApplication {
private DiLegacyApplication() {
}
public static void main(String[] args) {
ServiceRegistry.register(GreetingService.class, new DefaultGreetingService());
GreetingService service = ServiceRegistry.resolve(GreetingService.class);
System.out.println(service.greet("Aydin"));
}
}package at.aydin.lab.di.modern;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DiModernApplication {
public static void main(String[] args) {
SpringApplication.run(DiModernApplication.class, args);
}
}package at.aydin.lab.di.modern;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class GreetingRunner implements CommandLineRunner {
private final GreetingPort greetingPort;
// Design Pattern: Constructor Injection
// Zweck: Abhängigkeiten sind sichtbar, unveränderlich und leicht testbar.
public GreetingRunner(GreetingPort greetingPort) {
this.greetingPort = greetingPort;
}
@Override
public void run(String ... args) {
System.out.println(greetingPort.greet("Aydin"));
}
}Konkrete Abhängigkeit wird in Port und injizierbare Implementierung getrennt.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| GreetingService.java DefaultGreetingService.java | GreetingPort.java GermanGreetingService.java | Direktvergleich Semantische Ähnlichkeit: 63% |
package at.aydin.lab.di.legacy;
public interface GreetingService {
String greet(String name);
}package at.aydin.lab.di.legacy;
public final class DefaultGreetingService implements GreetingService {
@Override
public String greet(String name) {
return "Willkommen, " + name + "!";
}
}package at.aydin.lab.di.modern;
// Design Pattern: Port (Hexagonal Architecture)
// Zweck: Die Anwendung hängt von einem fachlichen Vertrag statt einer konkreten Implementierung ab.
public interface GreetingPort {
String greet(String name);
}package at.aydin.lab.di.modern;
import org.springframework.stereotype.Service;
@Service
public class GermanGreetingService implements GreetingPort {
@Override
public String greet(String name) {
return "Willkommen, " + name + "!";
}
}Die globale Registry entfällt; Verhalten wird direkt am Bean-Vertrag getestet.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| ServiceRegistry.java ServiceRegistryTest.java | GermanGreetingServiceTest.java | Direktvergleich Semantische Ähnlichkeit: 35% |
package at.aydin.lab.di.legacy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
// Design Pattern: Service Locator
// Zweck: Zentrale, manuelle Auflösung von Abhängigkeiten in Legacy-Anwendungen.
public final class ServiceRegistry {
private static final Map<Class<?>, Object> SERVICES = new ConcurrentHashMap<>();
private ServiceRegistry() {
}
public static <T> void register(Class<T> type, T implementation) {
SERVICES.put(type, implementation);
}
public static <T> T resolve(Class<T> type) {
Object service = SERVICES.get(type);
if (service == null) {
throw new IllegalStateException("Kein Service registriert: " + type.getName());
}
return type.cast(service);
}
}package at.aydin.lab.di.legacy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ServiceRegistryTest {
@Test
void resolvesRegisteredService() {
ServiceRegistry.register(GreetingService.class, new DefaultGreetingService());
assertEquals("Willkommen, Test!", ServiceRegistry.resolve(GreetingService.class).greet("Test"));
}
}package at.aydin.lab.di.modern;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class GermanGreetingServiceTest {
@Test
void greetsUser() {
assertEquals("Willkommen, Test!", new GermanGreetingService().greet("Test"));
}
}