【问题标题】:Spring AOP with prototype beans带有原型 bean 的 Spring AOP
【发布时间】:2020-09-17 05:35:14
【问题描述】:

我正在使用 Spring AOP 在我们的应用程序中触发指标。我创建了一个注释@CaptureMetrics,它有一个与之关联的@around 建议。除了 在原型 bean 上调用方法的情况外,所有带有 @CaptureMetrics 标记的方法都可以正常调用通知。

注解有@Target({ElementType.TYPE, ElementType.METHOD})

切入点表达式:

@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);
  }

}

单例注册表类

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 服务用于调用第三方客户端。它是一个原型 bean,因为它的状态会根据它将调用第三方的代表而有所不同。

  • 在初始化期间,单例注册表 bean 会构建 {source_of_request, dummyService_prototype} 的映射。要获取 dummyService 原型,它调用 getDummyServicePrototypeBean()

【问题讨论】:

  • 谁在调用 getDummyServicePrototypeBean
  • 原型 Dummy 服务用于调用第三方客户端。它是一个原型 bean,因为它的状态会根据它将调用第三方的代表而有所不同。 @simon 初始化期间的单例注册表 bean 构建 {source_of_request, dummyService_prototype} 的映射。要获取 dummyService 原型,它调用 getDummyServicePrototypeBean()
  • @ArchitRaiGupta 你能否用可以重现问题的代码更新问题?在我的本地测试中,总是建议使用原型范围的 bean。我会对@Configuration 类以及bean 工厂方法getDummyServicePrototypeBean() 的使用方式更感兴趣
  • @R.G 添加了配置类和单例注册类。

标签: spring-boot prototype javabeans aop spring-aop


【解决方案1】:

配置、注册表和原型 dummy bean 都是正确的。

我正在使用现有的集成测试来测试流程,并且没有提供原型 Bean,而是使用 new 关键字实例化了 DummyService 的新对象。它不是 Spring 管理的 bean。

Spring AOP 仅适用于 Spring 托管 bean。

【讨论】:

    猜你喜欢
    • 2016-08-09
    • 2021-05-10
    • 2010-12-29
    • 2021-01-13
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多