Выражение spring aop pointcut в других проектах не применяется

Структура проекта

  1. spring-contract
  2. spring-aop как зависимость от (1)
  3. spring-service как зависимость от (2).

У меня есть аннотация параметра @MyAnnotation в проекте spring-contract, класс аспекта в spring-aop,

package com.learning.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotatedFieldAspect {

    @Before("execution(* *(.., @MyAnnotation (*), ..)) && args(newValue)")
    public void advice(JoinPoint jp, Object newValue) {
        System.out.println(">>> inspecting "+newValue+" on "+jp.getTarget()+", "+jp.getSignature());
    }
}

Класс, который будет указан в аннотации, находится в проекте spring-service,

package com.learning.fieldtest.service;

public class TestField {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(@MyAnnotation String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        TestField testField = new TestField();
        testField.setName("Alex");
        testField.m1(testField.getName());
        System.out.println(testField.getName());
    }

    public void m1(@MyAnnotation String string) {
        System.out.println("Inside m1() @MyAnnotation" + string);
    }
}

Методы класса TestField не помечены как рекомендованные, если я перемещаю все классы в одном пакете, я получаю результат. Есть и другие аспекты, написанные на уровне классов и методов, которые применяются.

>>> inspecting Alex on com.learning.fieldtest.service.TestField@3fa77460, void com.learning.fieldtest.service.TestField.setName(String)
>>> inspecting Alex on com.learning.fieldtest.service.TestField@3fa77460, void com.learning.fieldtest.service.TestField.m1(String)
Inside m1() @MyAnnotationAlex
Alex

Пользовательская аннотация

package com.learning.spring.contract;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MyAnnotation {
}

person tinker_fairy    schedule 09.02.2020    source источник
comment
Не ответ, просто наблюдение - это чистый код Aspectj, так как там нет никаких связанных с Spring аннотаций.   -  person R.G    schedule 09.02.2020
comment
Вы не показали свой класс аннотации и, в частности, его имя пакета - пожалуйста, узнайте, что такое MCVE и почему он так ценен - но если аннотация не находится в том же пакете, что и аспект, вам нужно использовать его полное имя класса в pointcut, например execution(* *(.., @com.learning.whatever.MyAnnotation (*), ..)).   -  person kriegaex    schedule 09.02.2020
comment
@kriegaex добавил код, я пробовал   -  person tinker_fairy    schedule 09.02.2020
comment
Как я уже догадался, ваша аннотация находится в другом пакете, нежели аспект. Итак, ваш pointcut должен начинаться с execution(* *(.., @com.learning.spring.contract.MyAnnotation (*), ..)). Вы сказали, что пробовали, но не сообщили о результате. Не очень полезно. Так работает ли это так, как я предлагал? Затем я могу преобразовать свои комментарии в ответ, который вы затем можете принять + проголосовать, чтобы закрыть вопрос.   -  person kriegaex    schedule 09.02.2020
comment
Аспект не применяется, есть предупреждение в совете аспекта, определенном в com.learning.spring.contract.AnnotatedFieldAspect не был применен [Xlint: adviceDidNotMatch]. Я пробовал эту опцию только для проверки @Before("execution(* com.com.learning.fieldtest.service..*(..))") and @Before("within(com.com.learning.fieldtest.service.*)") того же предупреждающего сообщения   -  person tinker_fairy    schedule 09.02.2020
comment
Я проверил файлы .class с помощью декомпилятора, класс рекомендуется, но eclipse не отображается. Плагин аспекта есть, иерархия под кроссовером не отображается.   -  person tinker_fairy    schedule 10.02.2020


Ответы (1)


В один из ваших классов конфигурации Spring добавьте @EnableAspectJAutoProxy. Это позволит обрабатывать аспекты в приложении Spring.

    @Configuration
    @EnableAspectJAutoProxy
     public class AppConfig {

         @Bean
         public FooService fooService() {
             return new FooService();
         }

         @Bean
         public MyAspect myAspect() {
             return new MyAspect();
         }
     }

Для получения дополнительных сведений см .: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/EnableAspectJAutoProxy.html

person Satish    schedule 09.02.2020
comment
OP уже сообщил, что аспект работает, если все классы находятся в одном пакете. Очевидно, он уже правильно настроил Spring AOP, и его проблема в другом. - person kriegaex; 09.02.2020
comment
на самом деле конфигурация аспекта находится в проекте spring-contract, и он пытается применить это для класса в проекте spring-service, поэтому он не будет работать, если в spring-service также аспект не включен через. @EnableAspectJAutoProxy. (хотя применяется в пружинном контракте). Он упомянул, что когда он копирует файл в тот же пакет, который, я думаю, он копирует из проекта весеннего контракта в проект весеннего обслуживания, это сработало. Итак, я считаю, что ему просто нужно снова включить аспект во всех проектах, где бы он ни хотел его использовать. - person Satish; 09.02.2020
comment
Возможно, вы правы, но я был бы очень удивлен. Я никогда раньше не использовал Spring, поэтому не могу быть уверен, но насколько я понимаю, конфигурация Spring применяется глобально, а не для каждого модуля Maven. Как приложение узнает, какой класс принадлежит к какому модулю, а затем намеренно обработает его по-другому? Для меня это не имеет логического смысла. - person kriegaex; 09.02.2020
comment
Вы тоже правы. Spring учитывает класс конфигурации из зависимых модулей, но он не применим к некоторым конкретным аннотациям, например, «@Aspect», если он не включен в каждом дочернем проекте. Я цитирую объяснение из официального документа «Примечание:« @EnableAspectJAutoProxy »применяется только к его локальному контексту приложения, что позволяет избирательно проксировать bean-компоненты на разных уровнях. Пожалуйста, повторно объявите «@EnableAspectJAutoProxy» в каждом отдельном контексте ». См .: docs. spring.io/spring-framework/docs/current/javadoc-api/org/ - person Satish; 09.02.2020