捆绑中的蓝图依赖注入

时间:2013-01-08 13:45:20

标签: dependency-injection osgi blueprint-osgi aries

我遇到过一种情况,我希望在运行时使用Blueprint(Aries)来解析依赖关系,并且实现是在需要它的同一个bundle中定义的,不会在任何其他bundle中使用。我在这个包中抽象实现,以便在单元测试时更容易模拟依赖。如果我把这项服务放在自己的捆绑中,就会导致内聚力不佳。

在运行时,Blueprint表示正在等待依赖项。如何使用Blueprint实现捆绑中的依赖注入?

<!-- Interface -->
<reference id="modelEntityMapper" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />
<!-- Implementation defined within same bundle -->
<bean id="modelEntityMapperImpl" class="org.example.blog.rest.cxf.server.model.impl.ModelEntityMapperImpl" />
<service ref="modelEntityMapperImpl" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />

<!-- Object which has dependency -->
<bean id="posts" class="org.example.blog.rest.cxf.server.BlogResourceImpl">
        <property name="modelEntityMapper" ref="modelEntityMapper" />
</bean>

修改

我刚刚尝试了来自@ christian-scheider的建议,而Blueprint仍在等待一些服务来满足ModelEntityMapper

XML

<!-- Interface -->
<reference id="modelEntityMapper" interface="org.example.blog.rest.cxf.server.model.ModelEntityMapper" />
<!-- Implementation defined within same bundle -->
<bean id="modelEntityMapperImpl" class="org.example.blog.rest.cxf.server.model.impl.ModelEntityMapperImpl" />

<!-- Object which has dependency -->
<bean id="posts" class="org.example.blog.rest.cxf.server.BlogResourceImpl">
        <property name="modelEntityMapper" ref="modelEntityMapperImpl" />
</bean>

日志

Bundle rest-cxf-server is waiting for dependencies [(objectClass=org.example.blog.rest.cxf.server.model.ModelEntityMapper)]

2 个答案:

答案 0 :(得分:3)

你能直接引用服务的bean吗?如果您在同一蓝图文件中定义服务和服务引用,那么使用OSGi服务就没有多大意义。

答案 1 :(得分:2)

我无法在Aries网站上找到与捆绑引用相关的详细文档,因此我将引用Eclipse Gemini Blueprint实现文档(以前称为Spring Dynamic Modules)。请参阅section 9.2.1.1 of their documentation中的警告。是的,从技术上讲这与他们的实施有关,但我相信这可能是白羊座的类似故事。

  

声明对同一个bundle也导出的服务的强制引用是一个错误,这种行为可能导致应用程序上下文创建失败,无论是死锁还是超时。

简而言之,您通常要么导入(引用)OSGi服务,要么在同一个包中导出OSGi服务,通常您不会尝试在单个捆绑中同时执行这两项操作。

如果您希望此捆绑包导出ModelEntityMapper类型的服务,则需要使用service元素导出该捆绑包。当其他bean需要同一个包中的引用时,您将使用ref属性,就像您正在使用它一样。在这种情况下,您根本不需要reference元素,而是使用service元素。

如果您不打算在此捆绑包之外使用ModelEntityMapper bean,则根本不需要在配置中使用referenceservice元素。您应该能够在ref属性中使用它而不将其作为OSGi服务导出 - 它基本上是该bundle内部的bean。在这种情况下,您应该能够完全删除reference元素:<bean id="modelEntityMapperImpl" ...将在包内部创建一个bean,<property name="modelEntityMapper" ref="modelEntityMapperImpl" />元素应该能够在内部使用该bean到捆绑。

如果要从OSGi导入类型为ModelEntityMapper的引用(如果可用),则使用内部定义的回退,这会变得更复杂。您必须声明一个非强制性reference并将该引用与内部定义的bean一起注入您的类,然后使用默认逻辑来检查它们的可用性。或者,您可以在接口的单独包中定义实现。