Meteo ir3
Meteo ir3

Reputation: 449

AspectJ within(is(FinalType)) missed

I'm using aspectJ 1.8.10. In my code I have a bean with ScheduledExecutorService:

@Bean
public ScheduledExecutorService backgroundTaskExecutor() {
    return Executors.newSingleThreadScheduledExecutor();
}

When bean instantiated, proxy class throws:

.AopConfigException: Could not generate CGLIB subclass of class [class java.util.concurrent.Executors$DelegatedScheduledExecutorService]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class java.util.concurrent.Executors$DelegatedScheduledExecutorService

I know, that ScheduledExecutorService haven't constructor, is the root cause. But I need to configure my aspect's pointcut to exclude FinalType classes. Like this:

@Before("!within(is(FinalType)) && execution(* your_method_name(..)) ")

But, as I mentioned, aspectJ version 1.8.10 is not recognize is(..) syntax. (Intellij IDEA warning Cannot resolve symbol 'is'). Application starts without AOP issues, but fails with

java.lang.IllegalArgumentException: No visible constructors in class java.util.concurrent.Executors$DelegatedScheduledExecutorService

What I'm doing wrong? Is there any changes is aspectj > 1.8.4? (is(..) syntax)

Upvotes: 0

Views: 859

Answers (1)

kriegaex
kriegaex

Reputation: 67457

You have Spring AOP configured to force creation of CGLIB proxies even for interface types like ScheduledExecutorService, probably via

@EnableAspectJAutoProxy(proxyTargetClass = true)

Just remove the proxyTargetClass = true part or set to false, then your aspect will work. You do not need any is(FinalType) pointcut designator, just write something like

@Before("execution(* schedule*(..))")

in order to intercept scheduler methods.


Update: Let me explain why is(FinalType) does not help you and why thinking it does not work is wrong:

Read the error messages again:

Could not generate CGLIB subclass of class
  [class java.util.concurrent.Executors$DelegatedScheduledExecutorService]:
  Common causes of this problem include using a final class or a non-visible class;
  nested exception is
    java.lang.IllegalArgumentException: No visible constructors in class
    java.util.concurrent.Executors$DelegatedScheduledExecutorService

"No visible constructors" does not mean the class is final, it means what it says: There just are no visible constructors. Actually the inner static class Executors.DelegatedScheduledExecutorService is package-protected in java.util.concurrent where Executors resides. If you look at the source code you see:

static class DelegatedScheduledExecutorService
        extends DelegatedExecutorService
        implements ScheduledExecutorService {

    private final ScheduledExecutorService e;

    DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
        super(executor);
        e = executor;
    }

    // (...)
}

See? No final class here. The actual problem is that CGLIB just cannot create a subclass due to JVM limitations: You cannot subclass something that is in another package if it is not public.

This is why I told you to let Spring use a JDK dynamic proxy and take advantage of the fact that in this case subclassing is not necessary but implementing an interface is enough.

Upvotes: 3

Related Questions