SpringAOP представляет AspectJ с использованием аннотаций - PullRequest
0 голосов
/ 04 июля 2018

Я учусь Представления (известные как объявления типов в AspectJ). Я получил пример из представлений SpringAOP с AspectJ с использованием xml. Я пытаюсь повторить то же самое, используя аннотации , но я не знаю, как поступить. Я провел много исследований в интернете, но не смог найти никаких образцов. Не могли бы вы помочь мне с этим.

PerformanceTest.class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConcertConfig.class)
public class PerformanceTest {

    @Autowired
    public Audience audience;

    @Autowired
    public Performance liveOpera;

    @Autowired
    public EncoreableIntroducer encoreable;

    @Test
    public void testPerformance(){
        liveOpera.perform();
    }
}

LiveOpera.class

public class LiveOpera implements Performance{
    @Override
    public void perform() {
        System.out.println("Live Opera Performance Started");   
    }}

Encoreable.interface

public interface Encoreable {
    public void performEncore();
}

DefaultEncoreable.class

public class DefaultEncoreable implements Encoreable {
    @Override
    public void performEncore() {
        System.out.println("WoW!! What an encore performance!!");
    }
}

ConcertConfig.class

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {

    @Bean
    public Audience audience(){
        return new Audience();
    }

    @Bean
    public LiveOpera opera(){
        return new LiveOpera();
    }

    @Bean
    public EncoreableIntroducer encoreable(){
        return new EncoreableIntroducer();
    }

}

Интерфейс производительности

public interface Performance {
    public void perform();
}

EncoreableIntroducer.class

@Aspect
public class EncoreableIntroducer {
    @DeclareParents(value="com.example.introduction.Performance+",
            defaultImpl=DefaultEncoreable.class)
    public static Encoreable encoreable;
}

Audience.class

@Aspect
public class Audience {

    @Pointcut("execution(** com.example.introduction.Performance.perform(..))")
    public void performance() {
    }

    public void silenceMobilePhones() {
        System.out.println("Silencing Mobile Phones");
    }

    public void takeSeats() {
        System.out.println("Taking seats");
    }

    public void applause() {
        System.out.println("CLAP CLAP CLAP!!");
    }

    public void demandRefund() {
        System.out.println("Need a Refund!!");
    }

    @Around("performance()")
    public void wrapPerformance(ProceedingJoinPoint jp) {
        try {
            silenceMobilePhones();
            takeSeats();
            jp.proceed();
            applause();
        } catch (Throwable e) {
            System.out.println(e);
            e.printStackTrace();
            demandRefund();
        }
    }
}

Вывод: при выполнении метода @Test в PerformanceTest.class

Silencing Mobile Phones
Taking seats
Live Opera Performance Started
CLAP CLAP CLAP!!

Пожалуйста, дайте мне знать, как я могу использовать аспект в EncoreableIntroducer.class, используя AspectJ-Introductions, чтобы можно было использовать метод execute () в DefaultEncoreable.class?

Ожидается вывод, как показано ниже при использовании AspectJ Introduction:

Silencing Mobile Phones
Taking seats
WoW!! What an encore performance!!
Live Opera Performance Started
CLAP CLAP CLAP!!

1 Ответ

0 голосов
/ 05 июля 2018

У вас тут несколько проблем:

  • Вы работаете с двумя интерфейсами (Performance против Encoreable), реализующими одни и те же методы. Почему?
  • Вы пытаетесь ввести метод к LiveOpera, который у него уже есть, а именно void perform(). Вероятно, ваше намерение состоит в том, чтобы переопределить исходный. Это не будет работать ни в Spring AOP, ни в AspectJ. Вы можете вводить только те методы, которые еще не существуют в целевом классе.
  • Вы пытаетесь перехватить метод, представленный аспектом A в другом аспекте B. Насколько я знаю, это работает только в AspectJ, а не в Spring AOP. Я не являюсь пользователем Spring, но быстро попробовал, и он не работает. При воспроизведении вашей ситуации в AspectJ это сработало. Поэтому вы можете активировать AspectJ через LTW в своем приложении Spring и изменить свой код, чтобы он работал, избегая первых двух проблем, которые я описал.

Обновление и ответ на вопрос, заданный в комментарии:

Прежде всего, я избавился от ваших ручных @Bean методов в классе конфигурации, потому что вы все равно включили сканирование компонентов. Вместо этого я просто добавил аннотации @Component к классу LiveOpera и двум аспектам. Ваш метод также работает, но мне это нравится больше:

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {}

выглядит чище, не так ли? Только не забудьте @Component аннотации, где они принадлежат.

Теперь реальное решение. В аспекте измените свой совет на:

@Around("performance() && this(encoreable)")
public void wrapPerformance(ProceedingJoinPoint jp, Encoreable encoreable) {
  try {
    silenceMobilePhones();
    takeSeats();
    encoreable.performEncore();
    jp.proceed();
    applause();
  } catch (Throwable e) {
    System.out.println(e);
    e.printStackTrace();
    demandRefund();
  }
}
...