javaannotationsaspectjinitializerpointcut

AspectJ @around a static initializer


I'm attempting to use a point cut of

@Around("staticinitialization(*)")

but when applying i get this error:

[iajc] [error 4]: error at /home/dave/dev/coyote/projects/aspects/debug_src/com/acme/aspects/exceptions/StaticInitializerExceptions.java:15::443 around on staticinitialization of interface 'com.acme.intgservices.discussions.DiscussionListener' not supported (compiler limitation)

Which of course makes sense. But is there a way to tell aspectj not to select interfaces? That seems like something it should do on its own?


Solution

  • You need to use so-called type category type patterns. Unfortunately, they are undocumented in the regular AspectJ docs such as Programming Guide, AspectJ 5 Developer's Notebook or the Quick Reference PDFs. But they are described in the 1.6.9 release notes and an extension by one more category is mentioned in the 1.8.4 release notes.

    package de.scrum_master.stackoverflow.q79557444.app;
    
    public interface Shape {
      double getArea();
      double getCircumference();
    }
    
    package de.scrum_master.stackoverflow.q79557444.app;
    
    public class Circle implements Shape {
      private double radius;
    
      public Circle(double radius) {
        this.radius = radius;
      }
    
      @Override
      public double getArea() {
        return Math.PI * radius * radius;
      }
    
      @Override
      public double getCircumference() {
        return 2 * Math.PI * radius;
      }
    }
    
    package de.scrum_master.stackoverflow.q79557444.app;
    
    public class Application {
      public static void main(String[] args) {
        Circle circle = new Circle(5);
        System.out.println(circle.getArea());
        System.out.println(circle.getCircumference());
      }
    }
    

    In your aspect, you need to exclude both interface types by !is(InterfaceType)) and the aspect itself by !within(MyAspect) to avoid the aspect trying to weave into its own static initialiser, which would lead to a runtime error during aspect bootstrapping.

    package de.scrum_master.stackoverflow.q79557444.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class MyAspect {
      @Around("staticinitialization(!is(InterfaceType)) && !within(MyAspect)")
      public Object myAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(joinPoint);
        return joinPoint.proceed();
      }
    }
    

    Console log:

    staticinitialization(de.scrum_master.stackoverflow.q79557444.app.Application.<clinit>)
    staticinitialization(de.scrum_master.stackoverflow.q79557444.app.Circle.<clinit>)
    78.53981633974483
    31.41592653589793