Custom Annotation bei Spring AOP Pointcut-Definition

AOP (Aspektorientierte Programmierung) ist ein Programmierparadigma, das die objektorientierte Programmierung erweitert. Es werden Querschnittsbelange wie z. B. Caching, Security, Transaktionen und Auditierung gekapselt, die das System an mehreren Stellen benötigt. Diese Funktionalitäten werden nicht an mehreren Stellen (Klassen, Methoden) wiederholt implementiert, sondern an eine zentrale Stelle ausgelagert. Die ausgelagerte Funktionalität wird zur Compile- oder Laufzeit an den Stellen hinzugefügt, an denen sie gebraucht wird. Die Menge dieser Stellen nennt man Pointcut.

Bei der Entwicklung von Spring AOP wird folgendes Pattern für die Pointcut-Definition benutzt: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?). Es ist manchmal schwierig, ein gemeinsames Pattern für alle Methoden, die gematcht werden sollen, zu finden. In so einem Fall empfiehlt sich eine elegantere Variante und zwar die Erstellung einer eigenen Annotation, wie zum Beispiel @Transactional für die Pointcut-Definition.

Der Artikel zeigt anhand von Codebeispielen wie mit Spring AOP eine eigene Annotation für die Pointcut-Definition geschrieben wird. Für das Beispiel wurde mit Spring Initializr eine Spring Boot Applikation generiert.

Die Realisierung erfolgt in den folgenden Schritten:

Als erstes wird Spring AOP eingeschaltet:

@EnableAspectJAutoProxy
@SpringBootApplication
public class CustomAnnotationApplication {
    public static void main(String[] args) {
        SpringApplication.run(CustomAnnotationApplication.class, args);
    }
}

Der nächste Schritt ist die Erzeugung der eigenen Annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
    String value();
}

Der nächste Schritt ist die Definition der AOP-Logik. In unserem Fall ist das die Messung der Performanz:

@Aspect
@Component
public class MonitorPerformance {

    @Around("execution(@de.oio.custom.annotation.MyCustomAnnotation * *(..)) && @annotation(myCustomAnnotation)")
    public Object monitor(ProceedingJoinPoint joinPoint, MyCustomAnnotation myCustomAnnotation) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println(myCustomAnnotation.value()+": "+duration+"ms");   
        return result; 
    }
}

Die Annotation kann jetzt benutzt werden:

@Controller
public class MyController {

      @RequestMapping("/customAnnotation/hello")
         @MyCustomAnnotation("Hello Custom Annotation") 
         public @ResponseBody String getHelloWorld(){
              try {
                Thread.sleep(3000);
              } catch (InterruptedException e) {
                throw new RuntimeException("Sleep Interrupted", e);
              } 
              return "Hello World";
         } 
}

Short URL for this post: http://wp.me/p4nxik-2zJ
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply