OSGI企业应用开发(六)细说Blueprint & Gemini Blueprint(一)
上篇文章介绍了如何使用Blueprint將Spring框架整合到OSGI应用的Bundle中,从上篇文章中我们大概了解了Blueprint与Gemini Blueprint的关系,简单的说,Blueprint是OSGI Alliance借鉴了Spring Dynamic Modules 的思想,为OSGI制定的依赖注入(DI)规范,而Gemini Blueprint的前生是Spring DM,它即兼容之前的Spring DM,又实现了Blueprint规范。本篇文章开始,我们就来了解一下Gemini Blueprint的一些重要使用细节,以及它与Blueprint的差异。
一、自定义Bean配置文件路径
上篇文章中,我们知道,使用Blueprint整合Spring后,默认情况下,Gemini Blueprint会从Bundle的META-INF/spring目录下读取Bean的配置文件,而实际上标准的Blueprint规范会从OSGI-INF/blueprint目录下加载Bean的配置文件,为了说明这个观点,我们不妨在篇文章的代码基础上新建一个Bundle来演示。
首先新建一个Plug-in Project,名称为com.csdn.osgi.helloworld,步骤和前面文章中相同,如果读者不知道如何操作,可以阅读本系列博文的前面几篇,完成后工程如下图所示:
前面提到过,Gemini Blueprint支持标准的Blueprint规范,所以我们把Bean的配置文件放到OSGI-INF/blueprint目录下也是可以的,为了方便观察Bean是否被实例化,我们可以新建一个Java类,com.csdn.osgi.HelloWorld,内容如下:
package com.csdn.osgi;
public class HelloWorld {
public HelloWorld() {
System.out.println("================Hello World================");
}
}
如上面代码所示,我们可以在HelloWorld类的构造方法中,输出一些日志信息,这样实例化HelloWorld对象时,控制台中就会打印相应的信息。
接下来在com.csdn.osgi.helloworld工程中,新建OSGI-INF/blueprint目录,在该目录下新建Bean的配置文件beans.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="helloWorld" class="com.csdn.osgi.HelloWorld"/>
</blueprint>
最后,启动Equinox容器,注意要勾选我们新建的Bundle,名称为com.csdn.osgi.helloworld,如下图所示:
启动后,控制台输出日志内容如下:
hello world!
十二月 22, 2016 9:44:16 下午 org.eclipse.gemini.blueprint.extender.internal.boot.ChainActivator <init>
信息: Blueprint API detected; enabling Blueprint Container functionality
十二月 22, 2016 9:44:16 下午 org.eclipse.gemini.blueprint.extender.internal.activator.LoggingActivator start
信息: Starting [org.eclipse.gemini.blueprint.extender] bundle v.[2.0.0.M02]
osgi> 十二月 22, 2016 9:44:16 下午 org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration start
信息: No custom extender configuration detected; using defaults...
十二月 22, 2016 9:44:16 下午 org.springframework.scheduling.timer.TimerTaskExecutor afterPropertiesSet
信息: Initializing Timer
十二月 22, 2016 9:44:16 下午 org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator createApplicationContext
信息: Discovered configurations {osgibundle:/META-INF/spring/*.xml} in bundle [Common (com.csdn.osgi.common)]
十二月 22, 2016 9:44:17 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.common, config=osgibundle:/META-INF/spring/*.xml): startup date [Thu Dec 22 21:44:17 CST 2016]; root of context hierarchy
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.context.support.AbstractOsgiBundleApplicationContext unpublishContextAsOsgiService
信息: Application Context service already unpublished
十二月 22, 2016 9:44:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from URL [bundleentry://9.fwk1970436060/META-INF/spring/beans.xml]
Hello World!!
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.support.BlueprintContainerCreator createApplicationContext
信息: Discovered configurations {bundleentry://35.fwk1970436060/OSGI-INF/blueprint/beans.xml} in bundle [Helloworld (com.csdn.osgi.helloworld)]
十二月 22, 2016 9:44:17 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.helloworld, config=bundleentry://35.fwk1970436060/OSGI-INF/blueprint/beans.xml): startup date [Thu Dec 22 21:44:17 CST 2016]; root of context hierarchy
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.context.support.AbstractOsgiBundleApplicationContext unpublishContextAsOsgiService
信息: Application Context service already unpublished
十二月 22, 2016 9:44:17 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from OSGi resource[bundleentry://35.fwk1970436060/OSGI-INF/blueprint/beans.xml|bnd.id=35|bnd.sym=com.csdn.osgi.helloworld]
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor stageOne
信息: No outstanding OSGi service dependencies, completing initialization for OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.common, config=osgibundle:/META-INF/spring/*.xml)
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor stageOne
信息: No outstanding OSGi service dependencies, completing initialization for OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.helloworld, config=bundleentry://35.fwk1970436060/OSGI-INF/blueprint/beans.xml)
十二月 22, 2016 9:44:17 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@24259add: defining beans [helloWorld,blueprintBundle,blueprintBundleContext,blueprintContainer,blueprintConverter]; root of factory hierarchy
十二月 22, 2016 9:44:17 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2b8730e8: defining beans [object,length,buffer,current-time,list]; root of factory hierarchy
================Hello World================
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.blueprint.container.support.BlueprintContainerServicePublisher registerService
信息: Publishing BlueprintContainer as OSGi service with properties {Bundle-SymbolicName=com.csdn.osgi.helloworld, Bundle-Version=1.0.0.qualifier, osgi.blueprint.container.version=1.0.0.qualifier, osgi.blueprint.container.symbolicname=com.csdn.osgi.helloworld}
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.context.support.AbstractOsgiBundleApplicationContext publishContextAsOsgiServiceIfNecessary
信息: Publishing application context as OSGi service with properties {org.eclipse.gemini.blueprint.context.service.name=com.csdn.osgi.helloworld, org.springframework.context.service.name=com.csdn.osgi.helloworld, Bundle-SymbolicName=com.csdn.osgi.helloworld, Bundle-Version=1.0.0.qualifier}
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.context.support.AbstractOsgiBundleApplicationContext publishContextAsOsgiServiceIfNecessary
信息: Publishing application context as OSGi service with properties {org.eclipse.gemini.blueprint.context.service.name=com.csdn.osgi.common, org.springframework.context.service.name=com.csdn.osgi.common, Bundle-SymbolicName=com.csdn.osgi.common, Bundle-Version=1.0.0.qualifier}
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.extender.internal.support.DefaultOsgiBundleApplicationContextListener onOsgiApplicationEvent
信息: Application context successfully refreshed (OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.common, config=osgibundle:/META-INF/spring/*.xml))
十二月 22, 2016 9:44:17 下午 org.eclipse.gemini.blueprint.extender.internal.support.DefaultOsgiBundleApplicationContextListener onOsgiApplicationEvent
信息: Application context successfully refreshed (OsgiBundleXmlApplicationContext(bundle=com.csdn.osgi.helloworld, config=bundleentry://35.fwk1970436060/OSGI-INF/blueprint/beans.xml))
日志中输出了================Hello World================,说明我们在OSGI-INF/blueprint目录下配置的bean也能够成功被实例化。
接下来是本节的重点内容,Gemini Blueprint除了支持从默认的目录加载Bean的配置文件,还支持自定义配置文件的路径,同样支持Spring DM风格和Blueprint风格,首先介绍Spring DM风格。
有些OSGI基础的朋友应该都知道,OSGI的Bundle与普通Jar包的区别,从文件结构上来说,仅在于META-INF/MANIFEST.MF文件中的描述信息,例如我们新建的com.csdn.osgi.helloworld工程,MANIFEST.MF文件内容如下:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworld
Bundle-SymbolicName: com.csdn.osgi.helloworld
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.csdn.osgi.helloworld.Activator
Bundle-Vendor: CSDN
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.osgi.framework;version="1.3.0"
MANIFEST.MF文件由多个信息头构成,具体每一项的含义这里不做过多介绍,读者可以参考OSGI规范和相关的书籍,我们可以使用Gemini Blueprint自定义的Spring-Context信息头来指定配置文件位置,使用方式如下:
Spring-Context-Value ::= context ( ',' context ) *
context ::= path ( ';' path ) * (';' directive) *
上面的表达式描述了Spring-Context的值的形式,是啥意思呢,读者可能看不懂,不要紧,看几个具体的例子就知道了,例如下面的配置方式是允许的:
Spring-Context: config/account-data-context.xml, config/account-security-context.xml
同时指定多个配置文件路径,使用逗号分割开,除此之外,还支持通配符的方式,例如:
Spring-Context: config/*.xml
上面的配置,表示加载config目录下的所有XML文件,另外,我们还可以指定一些属性,例如:
Spring-Context: config/*.xml;create-asynchronously:=false
参数与配置文件路径使用分号分割开,create-asynchronously参数的含义是application context采用同步还是异步的方式创建,默认为异步方式,其他参数的含义读者可参考Gemini Blueprint官方文档。
接下来我们可以修改com.csdn.osgi.helloworld工程中的MANIFEST.MF文件,增加Spring-Context信息头来指定Bean的配置文件,例如:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Helloworld
Bundle-SymbolicName: com.csdn.osgi.helloworld
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.csdn.osgi.helloworld.Activator
Bundle-Vendor: CSDN
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.osgi.framework;version="1.3.0"
Spring-Context: config/*.xml
然后com.csdn.osgi.helloworld工程中新建config/beans.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="helloWorld1" class="com.csdn.osgi.HelloWorld"/>
<bean id="helloWorld2" class="com.csdn.osgi.HelloWorld"/>
</blueprint>
然后重启Equinox容器,日志中输出了连续的两行信息,如下:
================Hello World================
================Hello World================
从输出日志中,可以分析出config/beans.xml中配置的Bean也能够被实例化,说明Spring-Context头指定的Bean配置文件路径生效。
需要注意的是,Spring-Context指定Bean配置文件路径是Spring DM的方式,而标准的Blueprint规范使用Bundle-Blueprint头来指定Bean配置文件路径,使用方式相同,不做过多介绍,下面是Gemini Blueprint与Blueprint自定义Bean配置文件的区别,如下图所示:
关于Blueprint与Gemini Blueprint的使用本文暂时介绍这么多,下篇文章继续。
OSGI企业应用开发(六)细说Blueprint & Gemini Blueprint(一)的更多相关文章
- OSGI企业应用开发(四)使用Blueprint整合Spring框架(一)
上篇文章中介绍了如何使用独立的Equinox发行包搭建OSGI运行环境,而不是依赖与具体的Eclipse基础开发工具,本文开始介绍如何使用Blueprint將Spring框架整合到OSGI中. 一.开 ...
- OSGI企业应用开发(五)使用Blueprint整合Spring框架(二)
上篇文章中,我们开发了一个自定义的Bundle,接着从网络中下载到Spring和Blueprint的Bundle,然后复制到DynamicRuntime项目下. 需要注意的是,这些Bundle并不能在 ...
- OSGI企业应用开发(八)整合Spring和Mybatis框架(一)
到目前为止,我们已经学习了如何使用Blueprint將Spring框架整合到OSGI应用中,并学习了Blueprint&Gemini Blueprint的一些使用细节.本篇文章开始,我们將My ...
- OSGI企业应用开发(七)细说Blueprint & Gemini Blueprint(二)
上篇文章介绍了标准的Blueprint 规范与 Gemini Blueprint如何自定义Bean配置文件路径,本文接着上篇文章继续介绍Blueprint的使用. 一.Bean的配置 前面提到过,Ge ...
- OSGI企业应用开发(十四)整合Spring、Mybatis、Spring MVC
作为一个企业级的Web应用,MVC框架是必不可少的.Spring MVC目前使用也比较广泛,本文就来介绍一下如何在OSGI应用中实现Spring.Mybatis.Spring MVC框架的整合,其中S ...
- OSGI企业应用开发(十)整合Spring和Mybatis框架(三)
上篇文章中,我们已经完成了OSGI应用中Spring和Mybatis框架的整合,本文就来介绍一下,如何在其他Bundle中,使用Mybatis框架来操作数据库. 为了方便演示,我们新建一个新的Plug ...
- OSGI企业应用开发(九)整合Spring和Mybatis框架(二)
上篇文章中,我们完成了在OSGI应用中整合Spring和Mybatis框架的准备工作,本节我们继续Spring和Mybatis框架的整合. 一.解决OSGI整合Spring中的Placeholder问 ...
- OSGI企业应用开发(十三)OSGI Web应用开发(二)
上篇文章介绍了OSGI Web应用的两种开发模式,并把Jetty应用服务器以Bundle的形式整合到Equinox容器中,已这种模式开发Web应用,所有的应用程序资源,例如Servlet.JSP.HT ...
- OSGI企业应用开发(十二)OSGI Web应用开发(一)
前面文章中介绍了如何在OSGI应用中整合Spring和Mybatis框架,本篇文章开始介绍如何使用OSGI技术开发Web应用.对于传统的Java EE应用,应用中涉及到的Web元素无非就是Servle ...
随机推荐
- js基础知识--变量类型和变量计算
提问: JS中使用typeof能得到的哪些类型 何时使用===何时使用== JS中有哪些内置函数 JS变量按照存储方式区分为哪些类型,并描述其特点 如何理解JSON 涉及知识点:(1)变量类型 值类型 ...
- Django两天搭建个人博客
传送门:https://github.com/1417766861/django-blog(可直接运行,上面有步骤) 效果: 首页: 侧栏: 详情页面: 修改头像,资料,文章发布: 支持添加标签拖拽 ...
- (转)CentOS7安装Nginx1.14.2
原文:https://blog.csdn.net/zhyfyz/article/details/84957381 https://blog.csdn.net/q85795362/article/det ...
- Apater适配器模式(结构型模式)
1.概要 适配:即在不改变原有实现的基础上,将原先不适合的接口转换成适合的接口. what is Apater?适配,这个概念在生活中无处不在,比如你的iphone 4手机充电器坏了,这是时候只有一个 ...
- SQL Server性能优化(6)查询语句建议
1. 如果对数据不是工业级的访问(允许脏读),在select里添加 with(nolock) ID FROM Measure_heat WITH (nolock) 2. 限制结果集的数据量,如使用TO ...
- Windows下的Jdk 1.7*安装并配置(图文详解)
不多说,直接上干货! 很多人很少去想,为什么在windows下,安装完Jdk的安装包之后,还需要去配置环境变量,只是知道要这么去做,没有想过为什么要去这么做? 答:由于java是平台无关的 ,安装jd ...
- wordpress给文章添加缩略图
百度是个好东西,翻了半个小时的文章,终于把这个问题解决了. 一个问题的解决方法很多,但要找到一个自己理解的方法,缺比较难找,不管怎样,多动手,可能弄着弄着就会了. 教程开始: 1.先去后台管理安装Ea ...
- el-upload源码修改跳坑
之前给element-ui提了一个问题,结果没有鸟我,没办法,只能修改源码来满足需求了 (备注:element-ui2依然没有修改,为了迎合产品还是要改源码) 本文讨论的组件属性仅限于list-typ ...
- bootstrap-datepicker 开始时间-结束时间 thinkphp
<!DOCTYPE html> <head> <title>开始-结束时间测试</title> </head> <body> & ...
- JavaSE Collection集合
集合:是java中提供的一种容器,可以用来存储多个对象.可是我们前面学习的数组也是可以保存多个对象的,为什么还要提供集合容器呢?集合和数组它们有啥区别呢? 数组的长度是固定的.一旦创建完成不能改变长度 ...