【问题标题】:OSGi bundle access Spring context file from another bundleOSGi 包从另一个包访问 Spring 上下文文件
【发布时间】:2011-10-08 15:00:11
【问题描述】:

我有一个作为多个 Spring 项目存在的现有应用程序。项目 A 的 Spring 上下文 XML 文件使用

导入 B 的 Spring 上下文 XML 文件
<import resource="classpath*:/META-INF/spring/BContext.xml" />

但是,我得到了FileNotFoundException。我认为这是由于项目 B 的捆绑包没有公开资源这一事实造成的。我可以访问类,但不能访问文件。

在研究这个问题时,常见的评论是使用 OSGi 服务并注入服务,而不是尝试直接注入 bean。但是,由于这是一个现有的应用程序,我想避免重新布线。

有没有办法告诉 OSGi 导出资源?我正在 Karaf 上运行 ServiceMix。

【问题讨论】:

    标签: java spring osgi apache-karaf apache-servicemix


    【解决方案1】:

    它只是一个类路径资源,所以我假设添加一个适当的Export-Package 指令就可以了。不过,这绝对不是正确的做法。该上下文文件的路径表明,可能包含 BContext.xml 的项目已经设置为使用 Spring 动态模块。如果是这样,那么当您启动该捆绑包时,Spring ApplicationContext 将作为服务导出。在您的 OSGi 控制台中查找它。

    编辑:回应 cmets 中的讨论:

    我自己从未尝试过,但理论上应该可以使用 Spring DM 的 osgi namespace 来制作 bean reference to the OSGi service,这是项目 B 的 ApplicationContext。然后,拥有一个作为 ApplicationContext 的 bean,您可以使用 normal Spring configuration 使用 one of the getBean() 方法从中提取 bean。请注意,您可以使用 &lt;constructor-arg ... /&gt; 在 Spring 配置中指定工厂方法的参数,如 toward the bottom of this examples section 所示。

    【讨论】:

    • 我知道 ApplicationContext 已公开,但除非它是 OSGi 服务,否则我如何将其连接到 XML 文件中?
    • 对于Export-Package,它会是“META-INF.spring”作为包吗?
    • @Justin:它导出为 Spring DM 容器中的 OSGi 服务。您可以像使用任何其他 OSGi 服务一样使用它。对于 Export-Package,我会尝试“META-INF.spring”,是的;但是,我突然想到包名称中的连字符无效,因此您可能必须将文件移动到其他位置。
    • 是上下文中的所有 bean 都导出为 OSGi 服务,还是只是上下文本身?
    • @Justin: context itself
    【解决方案2】:

    从另一个模块加载 Spring 上下文和所有实现类是对模块封装的严重违反。如果您愿意这样做,那么将 A 和 B 作为单独的捆绑包确实没有任何意义,您不妨将它们单独打包。

    【讨论】:

      【解决方案3】:

      您应该这样做的方式是利用 OSGi 服务。您可以使用以下内容在 Spring DM 中注册服务(通常在单独的 osgi-context.xml 文件中完成,以确保代码库不依赖于 OSGi 以进行测试。在此示例中,您将拥有一个带有BContext.xml 中定义的 id 诊所,作为 OSGi 服务引用

      <?xml version="1.0" encoding="UTF-8"?>
      <beans:beans xmlns="http://www.springframework.org/schema/osgi"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:beans="http://www.springframework.org/schema/beans"
          xsi:schemaLocation="http://www.springframework.org/schema/osgi  
              http://www.springframework.org/schema/osgi/spring-osgi.xsd
              http://www.springframework.org/schema/beans   
              http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <service id="osgiClinic" ref="clinic" interface="org.springframework.petclinic.repository.Clinic" />
      
      </beans:beans>
      

      然后在消费包的 osgi-context.xml 中,您将引用该服务。在下面的示例中,您现在有一个名为 Clinic 的 bean,它使用了第一个 bean 中的代码。

      <?xml version="1.0" encoding="UTF-8"?>
      <beans:beans xmlns="http://www.springframework.org/schema/osgi"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:beans="http://www.springframework.org/schema/beans"
          xsi:schemaLocation="http://www.springframework.org/schema/osgi  
              http://www.springframework.org/schema/osgi/spring-osgi.xsd
              http://www.springframework.org/schema/beans   
              http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <reference id="clinic" interface="org.springframework.petclinic.repository.Clinic"/>
      
      </beans:beans>
      

      这种做事方式将确保您考虑捆绑包之间的依赖关系,并仅导出其他捆绑包所必需的服务。

      【讨论】:

        猜你喜欢
        • 2011-04-16
        • 1970-01-01
        • 2014-07-24
        • 2011-04-01
        • 2016-07-22
        • 1970-01-01
        • 2011-09-22
        • 2012-07-22
        • 1970-01-01
        相关资源
        最近更新 更多