AspectJ: custom *.aj file is ignored

前端 未结 2 1545
礼貌的吻别
礼貌的吻别 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: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 {}
    
    package de.scrum_master.app;
    
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ItemRepository extends JpaRepository {
      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.

提交回复
热议问题