【问题标题】:Accessing InjectionPoint inside Spring functional bean definition DSL在 Spring 功能 bean 定义 DSL 中访问 InjectionPoint
【发布时间】:2021-12-28 16:25:42
【问题描述】:

我们使用 Bean 工厂函数来允许将 Logger 对象注入到我们的 Bean 中。 这看起来类似于 Simar Paul Singh 在他的文章“Inject loggers in Spring”中描述的内容

import org.slf4j.*
import org.springframework.beans.factory.InjectionPoint
import org.springframework.context.annotation.*

@Bean
@Scope("prototype")
fun logger(injectionPoint: InjectionPoint): Logger {
  return LoggerFactory.getLogger(
      injectionPoint.methodParameter?.containingClass // constructor
          ?: injectionPoint.field?.declaringClass // or field injection
  )
}

今天我尝试使用Springs functional bean definition DSL 将此声明转换为 Bean 声明。但是,我没有成功获取用于检索 Logger 注入的类的InjectionPoint

import org.slf4j.*
import org.springframework.beans.factory.InjectionPoint
import org.springframework.context.support.beans
import org.springframework.context.support.BeanDefinitionDsl.Scope.PROTOTYPE

fun beans() = beans {
    bean(scope = PROTOTYPE) {
        val injectionPoint = ref<InjectionPoint>()
    
        LoggerFactory.getLogger(
            injectionPoint.methodParameter?.containingClass // constructor
                ?: injectionPoint.field?.declaringClass // or field injection
        )
    }
}

上述结果导致异常:

NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.InjectionPoint' available

有没有办法检索InjectionPoint 或至少是类以提供类似于没有DSL 的Bean 声明的行为?

可以在GitHub 上找到最小的复制存储库。 在 Windows 上运行 ./gradlew bootRun.\gradlew.bat bootRun 以重现错误。


我在 Spring 的 GitHub 存储库上打开了issue #27738

【问题讨论】:

  • 你能分享你的整个代码或 GitHub 链接吗?
  • @Raj 我向 GitHub 添加了一个复制最少的存储库。请参阅问题的最后一段。
  • 可以重现(..带有注释配置,它就像魅力一样)!请提出问题(我认为最好here)。等待修复/坚持/混合注释配置/starSpring Fu
  • @xerx593 感谢您的回复。我可能很快会在 Spring 的 GitHub 存储库中提交一个问题。我知道并期待着“春福”的进展,现在悲哀地停止了。
  • ..我认为,这些家伙(实现 DSL 支持)只是忘记了这一点(also in the TestThe documentation 也需要一些努力。 (死链接,不正确/复制和粘贴)

标签: java spring spring-boot kotlin dsl


【解决方案1】:

我认为您不会获得InjectionPoint 的实例,因为它是根据组件对托管 bean 注入的需求而创建的。

InjectionPoint 类未使用@Component 或其任何派生类如@Service 进行注释。因此,它不是托管 bean,您不会使用 ref&lt;InjectionPoint&gt; 获得引用。

InjectionPoint 仅包含有关请求托管 bean 实例的类或方法的元信息。 也就是说,它不是一个功能对象,因此,不是托管的。 但是,bean 工厂方法可以选择接受它来对要返回的实例做出一些决定。因此,您的 bean 工厂方法(无论在 Kotlin 中调用什么)必须接受 InjectionPoint 的实例,这就是您在帖子的第一个版本中所做的。

此外,从我从 Kotlin Bean DSL here 的文档中可以理解的最低限度来看,我看不到 一种将其作为参数接受的方法(但这可能仅仅是由于我对 Kotlin 缺乏了解。因此,总而言之,这对于需要注入点的 bean 定义可能没有用,除非您可以浏览文档并找到我可能错过的方法。

【讨论】:

  • 感谢@SreeKumar,您的回答对我的用例没有直接帮助,但可以很好地概述手头的问题。因此,如果在接下来的一个小时内没有人给出更合适的答案,我将奖励这个答案。但是,由于它没有完全回答问题,因此我不会将其标记为已接受的答案。
【解决方案2】:

我不是 Kotlin 专家,但请你试试这个

fun beans() = beans {
    bean<InjectionPoint>()
    bean(scope = PROTOTYPE) {
        val injectionPoint = ref<InjectionPoint>()
    
        LoggerFactory.getLogger(
            injectionPoint.methodParameter?.containingClass // constructor
                ?: injectionPoint.field?.declaringClass // or field injection
        )
    }
}

【讨论】:

  • 不幸的是,这不起作用。此后,对ref&lt;InjectionPoint&gt;() 的调用不再产生上述错误,而只是null,这也无助于创建记录器。
猜你喜欢
  • 2018-02-06
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 2020-05-22
  • 2011-07-27
  • 1970-01-01
  • 2020-12-06
  • 2018-07-02
相关资源
最近更新 更多