0

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?

2
  • If you know all your interfaces are in a certain package, you can exclude them with : @Around("staticinitialization() && !within(com.your.interface.package..)") You can also write multiple exclusions like: @Around("staticinitialization() && !within(com.your.interface.package.YourInterface1) && !within(com.your.interface2.package2.YourInterface2)") Commented Apr 5 at 21:59
  • there are thousands of interfaces across 100s of packages. Enumeration doesn't work in my case Commented Apr 5 at 23:15

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

2 Comments

thanks that did work. Does a later jdk allow you to put class initializers on interfaces? Otherwise why not just not consider interfaces?
No, at least until JDK 24 no static {} blocks are permitted in interfaces. I think, an error message is instructive here, telling the user explicitly what is wrong. Then, she needs to fix it by excluding interfaced from matching as shown here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.