如何在自定义Quarkus公司扩展中引用第三方扩展的合成Bean?
解决方案:通过合成Bean依赖注入或运行时容器获取ConnectionFactory
你不能在BuildStep阶段直接获取ConnectionFactory实例——Quarkus的Build阶段属于编译期,此时quarkus-artemis-jms生成的ConnectionFactory合成Bean还未完成实例化,只有运行时才能拿到真实实例。
下面是两种可行的解决方式:
方法一:让EventProducer通过依赖注入接收ConnectionFactory
如果你的EventProducer类可以调整,直接在构造方法中声明对ConnectionFactory的依赖,注册合成Bean时让Quarkus自动处理注入逻辑:
@SuppressWarnings("unused") @Record(ExecutionTime.RUNTIME_INIT) @BuildStep EventProducerBuildItem loadEventProducer( BuildProducer<SyntheticBeanBuildItem> syntheticBeanProducer ) { // 注册合成Bean,声明依赖ConnectionFactory syntheticBeanProducer.produce(SyntheticBeanBuildItem.configure(EventProducer.class) .scope(Singleton.class) // 通过实例化器自动注入ConnectionFactory .createWith(inst -> new EventProducer(inst.get(ConnectionFactory.class))) .done()); return new EventProducerBuildItem(); }
对应的EventProducer类需要有接收ConnectionFactory的构造方法:
public class EventProducer { private final ConnectionFactory connectionFactory; public EventProducer(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; // 这里可以添加初始化逻辑 } // 业务方法实现 }
方法二:通过Recorder在运行时获取ConnectionFactory
如果必须使用Recorder处理初始化逻辑,可以在Recorder方法中传入BeanContainer,在运行时阶段获取实例:
首先调整Recorder类:
public class EventProducerRecorder { public Supplier<EventProducer> eventProducerSupplier(BeanContainer beanContainer) { ConnectionFactory connectionFactory = beanContainer.beanInstance(ConnectionFactory.class); return () -> new EventProducer(connectionFactory); } }
然后修改BuildStep代码:
@SuppressWarnings("unused") @Record(ExecutionTime.RUNTIME_INIT) @BuildStep EventProducerBuildItem loadEventProducer( EventProducerRecorder eventProducerRecorder, BeanContainerBuildItem beanContainerBuildItem, BuildProducer<SyntheticBeanBuildItem> syntheticBeanProducer ) { // 将BeanContainer传递给Recorder,延迟到运行时获取ConnectionFactory syntheticBeanProducer.produce(SyntheticBeanBuildItem.configure(EventProducer.class) .scope(Singleton.class) .runtimeValue(eventProducerRecorder.eventProducerSupplier(beanContainerBuildItem.getValue())) .done()); return new EventProducerBuildItem(); }
原代码失效原因
你原代码中调用beanContainerBuildItem.getValue().beanInstance(ConnectionFactory.class)获取到的是编译期代理容器,并非运行时的真实Bean容器,此时ConnectionFactory合成Bean还未实例化,自然拿不到有效实例。
参考逻辑
Quarkus官方扩展(如各类JMS相关扩展)普遍采用声明依赖+框架自动注入的方式实现跨扩展Bean引用,你可以参考这类扩展的内部实现逻辑。
内容的提问来源于stack exchange,提问作者jelmew
相关产品推荐
相关产品推荐

