Spring aspect call on custom annotation on interface method
Asked Answered
A

3

6

I have this interface:

public interface FakeTemplate {

    @CustomAnnotation
    void foo() {

    }

}

And this implementation of the interface:

@Component
public FakeImpl implements FakeTemplate {

    @Override
    public void foo() {
        //Do Stuff
    }

}

And this aspect:

@Aspect
@Component
public class CustomAspect {

    @Before(value = "@annotation(com.fake.CustomAnnotation)")
    public void doStuffBefore(JoinPoint joinPoint} {

    }

}

I'm using spring with AspectJ enabled using: @EnableAspectJAutoProxy(proxyTargetClass = true)

My issue is that the aspect doStuffBefore method is not being called before the execution of FakeImpl's foo() method. It Does work when I put the @CustomAnnotation on FakeImpl instead of FakeTemplate, but I'd much prefer to put the annotation on FakeTemplate as it's in a separate API package and I've kind of delegated it as the place where I put all my annotations.

I'd also like to ensure that the CustomAnnotation is called on every class that implements FakeTemplate without remembering to put the annotation on all the implementation classes themselves.

Is there any way to get the advice to be called if the annotation is only on the interface class?

Aqueous answered 17/3, 2016 at 15:54 Comment(2)
Duplicate of this: #2848140Amphetamine
Not really, @RahulSharma , it's definitely similar, but I don't want to have to specify the interface in the aspect. I want to be able to throw the annotation on any interface and have all implementing classes of any interface the annotation is on have that advice run. I don't want to continuously have to add interface specifications to the aspect.Aqueous
G
5

Annotation inheritance doesn't work for methods in java. But you can use other pointcut expression, something like execution(public * FakeTemplate+.foo(..))

Graceless answered 17/3, 2016 at 16:32 Comment(1)
Yea, thats what I was trying to avoid. I'd like to use the annotation on multiple interfaces, so then I'd have to continuously add new interfaces to the aspect. I'm just going to add the annotation to the implementing classes, that keeps my aspect simple and, while its repeated work, makes the most sense to me. Marking your answer as correct.Aqueous
A
0

There is sort of a workaround. In your example, you can add an extra 'default' method e.g. named fooFacade to your FakeTemplate interface, annotate that with your @CustomAnnotation, and then delegate to the 'real' foo method:

public interface FakeTemplate {

    @CustomAnnotation
    default void fooFacade() {
        foo();
    }

    void foo();
}

Now whenever you call fooFacade(), execution of the pointcut on @CustomAnnotation will be triggered.

Almanza answered 11/5, 2020 at 14:47 Comment(1)
Ha, that's pretty clever. Not very pretty, but clever.Tribade
F
0

This is NOT implemented so far.

See https://github.com/spring-projects/spring-framework/issues/22311

Fogle answered 18/7 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.