如何为@query设置spel contextprovider

tcomlyy6  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(334)

如何设置上下文提供程序以使我的spel扩展在 @Query("...") ?
我们在postgres中使用r2dbc。
据我所知,我需要注册一个 ReactiveExtensionAwareQueryMethodEvaluationContextProvider 但我找不到任何关于如何做到这一点的文件。有没有一个特定的豆子或者 @Configuration 用它吗?
我找到了这个单元测试。它是monogo而不是r2dbc,但我认为这是相同的原则-但是因为它是一个单元测试,所以它没有显示如何在我的普通代码中设置上下文。
试图这样实现它并不能提供 my() spel中的方法

@Configuration
class MySpELExtensionConf {

  @Bean
  fun mySpELExtension() : ReactiveEvaluationContextExtension {
    return ReactiveSpelExtension()
  }

  class ReactiveSpelExtension : ReactiveEvaluationContextExtension {

    override fun getExtension(): Mono<out EvaluationContextExtension> {
      return Mono.just(SpelExtension.INSTANCE)
    }

    override fun getExtensionId(): String {
      ReactiveQueryMethodEvaluationContextProvider.DEFAULT
      return "mySpELExtension"
    }
  }

  enum class SpelExtension : EvaluationContextExtension {
    INSTANCE;

    override fun getRootObject(): Any? {
      return this
    }

    override fun getExtensionId(): String {
      return "mySpELExtension"
    }

    fun my(): String {
      return "x"
    }
  }
}

我现在看到 mySpELExtension 在应用程序上下文中,但是使用 my() a中的方法 @Query 不可能:

interface MyRepository : ReactiveCrudRepository<MyEntity, Long> {
  @Query("""
    ...
    :#{my()}
    ...
  """)
  fun findByMyQuery() : Flux<MyEntity>
}

结果

EL1004E: Method call: Method my() cannot be found on type java.lang.Object[]
332nm8kg

332nm8kg1#

我利用 PostBeanProcessor .

@Configuration
class MySpELExtensionConf {

  companion object {
    // list of provided extensions
    val contextProviderWithExtensions =
      ReactiveExtensionAwareQueryMethodEvaluationContextProvider(listOf(ReactiveSpelExtension()))
  }

  /**
   * Registers the customizer to the context to make spring aware of the bean post processor.
   */
  @Bean
  fun spELContextInRepositoriesCustomizer(): AddExtensionsToRepositoryBeanPostProcessor {
    return AddExtensionsToRepositoryBeanPostProcessor()
  }

  /**
   * Sets the [contextProviderWithExtensions] for SpEL in the [R2dbcRepositoryFactoryBean]s which makes the extensions
   * usable in `@Query(...)` methods.
   */
  class AddExtensionsToRepositoryBeanPostProcessor : BeanPostProcessor {
    override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any {
      if (bean is R2dbcRepositoryFactoryBean<*, *, *>) {
        bean.addRepositoryFactoryCustomizer { it.setEvaluationContextProvider(contextProviderWithExtensions) }
      }
      return bean
    }
  }

 // ... extension implementation as in question ...
}

请注意,自定义 R2dbcRepositoryFactoryBean 为…工作 CoroutineCrudRepository 而且您可能需要根据所使用的存储库定制不同的工厂bean。

相关问题