如何以编程方式添加便携式 CDI 扩展?
How to add a portable CDI Extension programmatically?
创建可移植 CDI 扩展(如 this)的示例均使用 javax.enterprise.inject.spi.Extension 扩展点以允许 ServiceLoader 加载扩展。
是否有 Weld/CDI API/SPI 以编程方式动态注册扩展?
我意识到生命周期可能是一个问题,因为您在没有此扩展的情况下启动了应用程序,并且在某些方面可能是 "too late",但无论如何还是想问一下。具体来说,我想知道 EE 环境。
据我所知,没有官方API支持这一点。
我知道有两个 hacks/options 您可能想根据自己的用例尝试一下。
添加动态创建 spi 服务文件的自定义类加载器
可以看看cdi unit的出处。上次我查看时,它使用反射和特定于实现的 类 来访问 Weld 的内部结构以影响初始化。我会 NOT 推荐该方法用于测试以外的其他事情。
为什么要动态加载扩展?
一个简单的解决方案可能是始终加载扩展程序并让它决定实际执行某些操作。
简短回答 - CDI 有意不提供 API 来动态添加扩展 。事实上,您不应该试图实现这一目标。
一点原因:
CDI 本质上是静态的 - 它在 bootstrap 期间需要某些信息,扩展就是其中之一。一旦 bootstrap 完成,扩展大部分变得无用(当然,您仍然可以将它们用作 beans 并在那里有一些逻辑,但它是'just a bean' then) .原因是扩展挂钩到 bootstrap 周期并且会影响每个阶段(ProcessAnnotatedType
、ProcessBeanAttributes
、...)。
现在,如果您以后以某种方式加载了这样的扩展(例如使用启动的 CDI 容器),将有两个选择;要么重新加载整个 CDI 容器以考虑此扩展,要么完全忽略它的内容,使其完全无用,因为它将充当普通 bean(永远不会调用容器生命周期观察器)。前者在某些部署中会非常 costly/disturbing 并且可能导致不可预测的结果 - 想象这样的动态扩展与替代品和专业化混在一起。后一种情况几乎没有意义,因为它会添加一个从未使用过的 bean。这就是 CDI 通常不允许这样做的原因。
我想知道,您的用例是什么?如果我们知道这一点,也许我们可以帮助您以不同的方式解决这个问题。
创建可移植 CDI 扩展(如 this)的示例均使用 javax.enterprise.inject.spi.Extension 扩展点以允许 ServiceLoader 加载扩展。
是否有 Weld/CDI API/SPI 以编程方式动态注册扩展?
我意识到生命周期可能是一个问题,因为您在没有此扩展的情况下启动了应用程序,并且在某些方面可能是 "too late",但无论如何还是想问一下。具体来说,我想知道 EE 环境。
据我所知,没有官方API支持这一点。
我知道有两个 hacks/options 您可能想根据自己的用例尝试一下。
添加动态创建 spi 服务文件的自定义类加载器
可以看看cdi unit的出处。上次我查看时,它使用反射和特定于实现的 类 来访问 Weld 的内部结构以影响初始化。我会 NOT 推荐该方法用于测试以外的其他事情。
为什么要动态加载扩展?
一个简单的解决方案可能是始终加载扩展程序并让它决定实际执行某些操作。
简短回答 - CDI 有意不提供 API 来动态添加扩展 。事实上,您不应该试图实现这一目标。
一点原因:
CDI 本质上是静态的 - 它在 bootstrap 期间需要某些信息,扩展就是其中之一。一旦 bootstrap 完成,扩展大部分变得无用(当然,您仍然可以将它们用作 beans 并在那里有一些逻辑,但它是'just a bean' then) .原因是扩展挂钩到 bootstrap 周期并且会影响每个阶段(ProcessAnnotatedType
、ProcessBeanAttributes
、...)。
现在,如果您以后以某种方式加载了这样的扩展(例如使用启动的 CDI 容器),将有两个选择;要么重新加载整个 CDI 容器以考虑此扩展,要么完全忽略它的内容,使其完全无用,因为它将充当普通 bean(永远不会调用容器生命周期观察器)。前者在某些部署中会非常 costly/disturbing 并且可能导致不可预测的结果 - 想象这样的动态扩展与替代品和专业化混在一起。后一种情况几乎没有意义,因为它会添加一个从未使用过的 bean。这就是 CDI 通常不允许这样做的原因。
我想知道,您的用例是什么?如果我们知道这一点,也许我们可以帮助您以不同的方式解决这个问题。