AspectJ: custom *.aj file is ignored

前端 未结 2 1544
礼貌的吻别
礼貌的吻别 2021-01-23 07:10

Why aspectj-maven-plugin ignore my AnnotationInheritor.aj file? Am I configured something wrong?

I want to advice ItemRepository

相关标签:
2条回答
  • 2021-01-23 07:19

    I guess it should work, even without AnnotationInheritor

    made a small demo, have a look...

    demo

    0 讨论(0)
  • 2021-01-23 07:35

    I copied your code into an AspectJ project (no Spring or Spring AOP there) in order to test it. I found a few problems:

    • @Around("@annotation(MyAnnotation)") will not find the annotation because there is no fully qualified class name.

    • declare @method : void ItemRepository+.getById() : @MyAnnotation; does not match your interface method's signature Item getById(Long id).

    • MyAspects.execute(..) needs to throw Throwable and of course also return something, such as the result of joinPoint.proceed(). But maybe that was just sloppy copy & paste.

    After fixing this, the following MCVE works beautifully:

    Helper classes making the project compile:

    package de.scrum_master.app;
    
    public class Item {}
    
    package de.scrum_master.app;
    
    public interface JpaRepository<P, Q> {}
    
    package de.scrum_master.app;
    
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ItemRepository extends JpaRepository<Item, Long> {
      Item getById(Long id);
    }
    
    package de.scrum_master.app;
    
    public class ItemRepositoryImpl implements ItemRepository {
      @Override
      public Item getById(Long id) {
        return new Item();
      }
    }
    

    Marker annotation:

    package de.scrum_master.app;
    
    import java.lang.annotation.*;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface MyAnnotation {}
    

    Driver Application:

    package de.scrum_master.app;
    
    public class Application {
      public static void main(String[] args) {
        ItemRepository repository = new ItemRepositoryImpl();
        repository.getById(11L);
      }
    }
    

    Aspects:

    Just in case you wonder why I added execution(* *(..)) to the pointcut, this is because I wanted to exclude matching call() joinpoints which are available in AspectJ as opposed to Spring AOP.

    package de.scrum_master.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class MyAspect {
      @Around("@annotation(de.scrum_master.app.MyAnnotation) && execution(* *(..))")
      public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(joinPoint);
        return joinPoint.proceed();
      }
    }
    
    package de.scrum_master.aspect;
    
    import de.scrum_master.app.Item;
    import de.scrum_master.app.ItemRepository;
    import de.scrum_master.app.MyAnnotation;
    
    public aspect AnnotationInheritor {
      declare @method : Item ItemRepository+.getById(Long) : @MyAnnotation;
    }
    

    Console log:

    execution(Item de.scrum_master.app.ItemRepositoryImpl.getById(Long))
    

    Voilà! It works nicely.

    If it does not work for you like this you have other issues such as (but not exclusively)

    • the "auto-generated ItemRepositoryImpl#getById" you mentioned in passing. Whenever and wherever this is generated during the build process, it needs to exist before the aspect is applied to it. In order to analyze this I would need an MCVE on GitHub, though.

    • whether the target code to weave the aspect into is in the same Maven module as the aspect code. If it is not, you need to change your Maven setup.

    0 讨论(0)
提交回复
热议问题