Migration Deep Dive für 02 · AOP öffnen →
⌂ ÜbersichtAlle Vergleiche
Modul 02 · 100 % Codeabdeckung

AOP

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.

6Legacy-Dateien
8Modern-Dateien
100 → 131Codezeilen
15/15vollständig erfasst

Fachliche Einordnung

Legacy

JDK Dynamic Proxy

Ein InvocationHandler erzeugt den Proxy manuell und funktioniert nur über ein Interface.

Modern

Spring AOP mit @Aspect

Ein Spring-Aspect fängt die mit @Tracked markierte Methode am Container-Proxy ab.

Vergleichsfokus: Alle Dateien werden nach technischer Rolle und fachlicher Verantwortung gruppiert.
Wichtige Abgrenzung: One-to-many-Änderungen werden als Gruppe dargestellt; eine künstliche 1:1-Zuordnung wird vermieden.

Vollständige Abdeckungsmatrix

Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.

VergleichsgruppeLegacy-DateienModern-DateienLegacy-ZeilenModern-ZeilenÄhnlichkeit
Build-Konfiguration11313851%
Bootstrap und Demo12112828%
Fachlicher Vertrag1155100%
Cross-cutting Concern12333612%
Implementierung und Test22202474%

Gemeinsame Modulstruktur

Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.

Gemeinsam · 19 Zeilenpom.xml
<?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>java-modernization-deep-dive</artifactId>
        <version>1.0.0</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <artifactId>02aop-pair</artifactId>
    <packaging>pom</packaging>
    <name>AOP: Legacy und Modern</name>
    <modules>
        <module>legacy</module>
        <module>modern</module>
    </modules>
</project>

Alle semantischen Codevergleiche

01Build-KonfigurationDirektvergleich · Legacy 31 / Modern 38 Zeilen · Ähnlichkeit 51%

AOP- und Testabhängigkeiten werden gegenübergestellt.

Legacy-DateienModern-DateienEinordnung
pom.xmlpom.xmlDirektvergleich
Semantische Ähnlichkeit: 51%

Legacy

Legacy · 31 Zeilenlegacy/pom.xml
<?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>02aop-pair</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>aop-legacy</artifactId>
    <packaging>jar</packaging>
    <name>AOP 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>

Modern

Modern · 38 Zeilenmodern/pom.xml
<?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>02aop-pair</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>aop-modern</artifactId>
    <packaging>jar</packaging>
    <name>AOP Modern</name>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</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>
02Bootstrap und DemoDirektvergleich · Legacy 11 / Modern 28 Zeilen · Ähnlichkeit 28%

Manueller Programmstart wird durch Spring Boot und Runner ersetzt.

Legacy-DateienModern-DateienEinordnung
AopLegacyApplication.javaAopModernApplication.java
CalculatorRunner.java
Direktvergleich
Semantische Ähnlichkeit: 28%

Legacy

package at.aydin.lab.aop.legacy;

public final class AopLegacyApplication {
    private AopLegacyApplication() {
    }

    public static void main(String[] args) {
        Calculator calculator = LoggingProxy.wrap(Calculator.class, new SimpleCalculator());
        System.out.println("Ergebnis: " + calculator.add(4, 7));
    }
}

Modern

package at.aydin.lab.aop.modern;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AopModernApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopModernApplication.class, args);
    }
}
package at.aydin.lab.aop.modern;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CalculatorRunner implements CommandLineRunner {
    private final Calculator calculator;
    public CalculatorRunner(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public void run(String ... args) {
        System.out.println("Ergebnis: " + calculator.add(4, 7));
    }
}
03Fachlicher VertragDirektvergleich · Legacy 5 / Modern 5 Zeilen · Ähnlichkeit 100%

Das fachliche Interface bleibt vergleichbar.

Legacy-DateienModern-DateienEinordnung
Calculator.javaCalculator.javaDirektvergleich
Semantische Ähnlichkeit: 100%

Legacy

Modern

04Cross-cutting ConcernDirektvergleich · Legacy 33 / Modern 36 Zeilen · Ähnlichkeit 12%

Dynamischer Proxy wird durch Annotation und Aspect getrennt.

Legacy-DateienModern-DateienEinordnung
LoggingProxy.javaTracked.java
TrackingAspect.java
Direktvergleich
Semantische Ähnlichkeit: 12%

Legacy

package at.aydin.lab.aop.legacy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

// Design Pattern: Proxy
// Zweck: Querschnittslogik wird vor und nach einem Methodenaufruf ausgeführt.
public final class LoggingProxy implements InvocationHandler {
    private final Object target;
    private LoggingProxy(Object target) {
        this.target = target;
    }

    public static <T> T wrap(Class<T> contract, T target) {
        Object proxy = Proxy.newProxyInstance(contract.getClassLoader(), new Class<?>[] {
            contract
        }, new LoggingProxy(target));
        return contract.cast(proxy);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long started = System.nanoTime();
        System.out.printf("START %s %s%n", method.getName(), Arrays.toString(args));
        try {
            return method.invoke(target, args);
        } finally {
            System.out.printf("ENDE %s %d µs%n", method.getName(), (System.nanoTime() - started) / 1_000);
        }
    }
}

Modern

package at.aydin.lab.aop.modern;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public
@interface
Tracked {
}
package at.aydin.lab.aop.modern;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
// Design Pattern: Interceptor / Aspect
// Zweck: Monitoring bleibt getrennt von der Geschäftslogik.
public class TrackingAspect {
    @Around("@annotation(Tracked)")
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
        long started = System.nanoTime();
        try {
            return joinPoint.proceed();
        } finally {
            long micros = (System.nanoTime() - started) / 1_000;
            System.out.printf("%s dauerte %d µs%n", joinPoint.getSignature().toShortString(), micros);
        }
    }
}
05Implementierung und TestDirektvergleich · Legacy 20 / Modern 24 Zeilen · Ähnlichkeit 74%

Zielobjekt und Verifikation werden vollständig verglichen.

Legacy-DateienModern-DateienEinordnung
SimpleCalculator.java
CalculatorTest.java
TrackedCalculator.java
TrackedCalculatorTest.java
Direktvergleich
Semantische Ähnlichkeit: 74%

Legacy

package at.aydin.lab.aop.legacy;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatorTest {
    @Test
    void proxyDelegates() {
        Calculator calculator = LoggingProxy.wrap(Calculator.class, new SimpleCalculator());
        assertEquals(11, calculator.add(4, 7));
    }
}

Modern

package at.aydin.lab.aop.modern;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class TrackedCalculatorTest {
    @Test
    void addsNumbersWithoutSpringContext() {
        Calculator calculator = new TrackedCalculator();
        assertEquals(11, calculator.add(4, 7));
    }
}
⌂ Cockpit