Spring AOP с прототипами beans - PullRequest
2 голосов
/ 29 мая 2020

Я использую Spring AOP для запуска метрик в нашем приложении. Я создал аннотацию @CaptureMetrics, с которой связан совет @around. Совет прекрасно вызывается из всех методов, помеченных @CaptureMetrics, за исключением случая , когда метод вызывается в компоненте-прототипе.

В аннотации указано @Target({ElementType.TYPE, ElementType.METHOD})

Выражение PointCut:

@Around(value = "execution(* *.*(..)) && @annotation(captureMetrics)",
      argNames = "joinPoint,captureMetrics")

Создание прототипа bean-компонента

@Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public DummyService getDummyServicePrototypeBean(int a, String b) {
    return new DummyService(a, b);
  }

DummyService имеет метод с именем dummyMethod (String dummyString)

    @CaptureMetrics(type = MetricType.SOME_TYPE, name = "XYZ")
          public Response dummyMethod(id) throws Exception {
           // Do some work here
        }

Когда dummyService.dummyMethod("123") - вызывается из другой службы, совет @Around не вызывается.

Класс конфигурации

@Configuration
public class DummyServiceConfig {

  @Bean
  public DummyServiceRegistry dummyServiceRegistry(
      @Value("${timeout}") Integer timeout,
      @Value("${dummy.secrets.path}") Resource dummySecretsPath) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    Map<String, String> transactionSourceToTokens = mapper.readValue(
        dummySecretsPath.getFile(), new TypeReference<Map<String, String>>() {
        });
    DummyServiceRegistry registry = new DummyServiceRegistry();
    transactionSourceToTokens.forEach((transactionSource, token) ->
        registry.register(transactionSource,
            getDummyServicePrototypeBean(timeout, token)));

    return registry;
  }

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public DummyService getDummyServicePrototypeBean(int a, String b) {
    return new DummyService(a, b);
  }

}

Класс Singleton Registry

public class DummyServiceRegistry {
  private final Map<String, DummyService> transactionSourceToService = new HashMap<>();

  public void register(String transactionSource, DummyService dummyService) {
    this.transactionSourceToService.put(transactionSource, dummyService);
  }

  public Optional<DummyService> lookup(String transactionSource) {
    return Optional.ofNullable(transactionSourceToService.get(transactionSource));
  }
}

Какие-нибудь советы по этому поводу?

Примечание:

  • Прототип Dummy-сервиса используется для вызова стороннего клиента . Это компонент-прототип, так как его состояние меняется в зависимости от того, от чьего имени он будет вызывать третью сторону.

  • Одноэлементный компонент реестра во время инициализации строит карту {source_of_request, dummyService_prototype}. Чтобы получить прототип dummyService, он вызывает getDummyServicePrototypeBean ()

1 Ответ

0 голосов
/ 29 мая 2020

Конфигурация, реестр и фиктивный компонент прототипа были правильными.

Я тестировал поток с использованием существующего интеграционного теста, и там вместо предоставления прототипа Bean новые объекты DummyService были созданы с использованием new ключевое слово. Это не был компонент, управляемый Spring.

Spring AOP работает только с компонентами, управляемыми Spring.

...