Gemini Blueprint參考文件 第8章 打包和部署基於Spring的OSGi應用
8.1.Bundle格式和Manifest頭
每一個應用模組都應打包成一個OSGi的bundle。bundle本質上是包含META-INF/MANIFEST.MF檔案的jar檔案,MANIFEST.MF檔案包含了OSGi服務平臺能夠識別的一系列頭資訊。參見OSGi服務平臺核心規範第3.2節瞭解細節。一些OSGi實現可能支援零散的jar檔案,但是格式是相同的。
Spring extender能識別基於Spring的bundle,當這個bundle啟動的時候,Spring extender將會建立與這個bundle相關的應用上下文。下面的一個條件為真:
- bundle的路徑包含一個資料夾META-INF/spring
- META-INF/MANIFEST.MF包含一個清單頭Spring-Context。
另外,如果在bundle的manifest中聲明瞭可選的SpringExtender-Version頭,那麼extender只會識別滿足版本約束(Bundle-Version)的bundle。SpringExtender-Version頭的只必須遵循OSGi服務平臺核心規範第3.2.5節指定的版本範圍。
如果缺少Spring-Context頭,那麼extender期望META-INF/spring資料夾下的每一個".xml"檔案都是合法的Spring配置檔案,所有的指令都取預設值,如下所示:
小貼士 |
應用上下文就是從這些檔案構造的。推薦將應用上下文配置分為至少兩個檔案,按慣例命名為modulename-context.xml和modulename-osgi-context.xml。modulename-context.xml檔案包含普通的bean定義,獨立於OSGi。modulename-osgi-context.xml檔案包含匯入和匯出OSGi服務的bean定義。它可能用(但是必需的)Gemini Blueprint OSGi schema作為頂級的名稱空間,而不是Spring 'beans'名稱空間。 |
Spring-Contextmanifest頭資訊用於指定可選的配置檔案。資源路徑是相對的資源路徑,解析bundle
Spring-Context頭資訊的語法是:
Spring-Context-Value ::= context ( ',' context ) *
context ::= path ( ';' path ) * (';' directive) *
這個語法與OSGi服務平臺公共頭語義定義是一致的(OSGi服務平臺核心規範第3.2.3節)。
例如,manifest條目:
Spring-Context: config/account-data-context.xml, config/account-security-context.xml
表明要用bundle jar檔案中的account-data-context.xml和account-security-context.xml兩個檔案中的配置例項化應用上下文。
許多指令都用於Spring-Context頭。這些指令包括:
- create-asynchronously(false|true):控制是否非同步(預設值)或者同步建立應用上下文。例如
Spring-Context: *;create-asynchronously:=false
同步建立應用上下文,用META-INF/spring檔案下的所有xml檔案。
Spring-Context: config/account-data-context.xml;create-asynchrously:=false
用config/account-data-context.xml配置檔案同步建立應用上下文。 注意,當同保護建立應用上下文時,建立應用上下文時在OSGi事件執行緒中,它會阻塞後面的事件傳遞,直到這個上下文完全初始化完成。如果在同步建立應用上下文時發生錯誤,那麼就產生FrameworkEvent.ERROR事件。這個bundle仍然會變為Active狀態。
- wait-for-dependencies(true|false):控制應用上下文的建立是否應該等待強制服務依賴滿足,或者不等待服務依賴啟動。例如:
Spring-Context: config/osgi-*.xml;wait-for-dependencies:=false
用配置目錄下所有匹配"osgi-*.xml"的檔案建立應用上下文。上下文建立立即開始,即使依賴不滿足。這從本質上意味著強制的服務引用被作為可選項對待-客戶端注入的服務物件可能不是登錄檔中實際的服務。參見瞭解更多細節。
- timeout(300):在放棄和應用上下文建立失敗之前,等待服務依賴滿足的時間。這個設定會被忽略,如果指定了wait-for-dependencies:=false。預設超時時間為5分鐘(300秒)。
例如:
Spring-Context: *;timeout:=60
建立應用上下文時,等待強制依賴的時間為1分鐘(60秒)。
- publish-context(true|false):控制應用上下文物件自己是否應該釋出到OSGi服務登錄檔中。預設是會發布這個上下文的。
例如:
Spring-Context: *;publish-context:=false
如果沒有Spring-Contextmanifest條目,或者條目中沒有指定值,那麼這個指令就取預設值。
8.2.Blueprint Manifest配置比較
下面的表格總結了Eclipse Gemini Blueprint/Spring DM和Blueprint Container之間的manifest配置選項差異:
表8.1. 配置設定區別
選項 |
Gemini Blueprint/Spring DM |
Blueprint |
預設配置位置 |
META-INF/spring |
OSGI-INF/blueprint |
自定義位置頭 |
Spring-Context |
Bundle-Blueprint |
屬性頭 |
Spring-Context |
Bundle-SymbolicName |
非同步建立屬性 |
create-asynchronously |
- |
啟動強制依賴屬性 |
wait-for-dependencies |
blueprint.graceperiod |
啟動強制超時屬性 |
timeout (in s) |
blueprint.timeout (in ms) |
容器服務API釋出屬性 |
publish-context |
- |
下面的manifest中的配置是等價的:
Bundle-SymbolicName: org.example.account.bundle Spring-Context: config/account-data-context.xml, config/osgi-*.xml; wait-for-dependencies:=true; timeout:=10 |
1、所有Gemini Blueprint和Spring DM特定的屬性都位於Spring-Context頭 2、超時的單位為秒(s) |
Bundle-SymbolicName: org.example.account.bundle; blueprint.graceperiod:=true; blueprint.timeout:=10000 Blueprint-Bundle: config/account-data-context.xml, config/osgi-*.xml |
1、Blueprint設定在Bundle-SymbolicName和Blueprint-Bundle之間擴充套件 2、超時的單位為毫秒(ms) |
8.3.Extender配置選項
除了特定bundle的配置,Gemini Blueprint和Spring DM允許配置核心extender通用行為 。當把Spring DM嵌入到管理環境或者當期望bundle範圍的功能,這就有用了。為了允許擴充套件配置,extender依賴來覆蓋預設值。extender查詢位於bundle空間的META-INF/spring/extender資料夾下的所有xml檔案,並聚合到應用上下文中(型別為OsgiBundleXmlApplicationContext),這是內部用於配置。為了覆蓋extender的預設設定,從下表中查詢合適的bean名字,以合適的方式定義它,然而將它作為spring-osgi-extender.jar的附屬fragments,使用:
Fragment-Host: org.eclipse.gemini.blueprint.extender
下面的bean當前可以被extender識別:
表8.2. Extender配置選項
Bean名 |
型別 |
角色 |
預設的行為/值 |
taskExecutor |
TaskExecutor[a] |
建立並執行與每一個bundle有關的Spring應用上下文。task executor負責管理自己的,應用上下文使用的執行緒池 |
預設使用SimpleAsyncTaskExecutor這意味著每一個應用上下文都建立一個新的執行緒。這適用於測試和開發,我們強烈建議在生產環境中使用執行緒池 |
shutdownTaskExecutor |
TaskExecutor[b] |
銷燬與每一個bundle有關的Spring應用上下文。task executor負責管理自己的,應用上下文使用的執行緒池 |
預設使用TimerTaskExecutor,這意味著每一個應用上下文以序列方式銷燬。由於關閉順序通常很重要,對於管理環境推薦用預設實現,用一個執行緒池只執行一個任務(這樣上下文按給定的順序關閉) |
extenderProperties |
java.util.Properties |
定義簡單屬性,例如上下文優雅關閉的最大時間 |
參加下面的預設值 |
osgiApplicationEventMulticaster |
ApplicationEventMulticaster[c] |
||
applicationContextCreator |
OsgiApplicationContextCreator[d] |
允許自定義extender建立的應用上下文。包括修改應用上下文的型別或者額外的處理 |
Extender預設行為 |
(irrelevant) |
OsgiBeanFactoryPostProcessor[d] |
類似於Spring的BeanFactoryPostProcessor介面,OsgiBeanFactoryPostProcessor的bean自動檢測是應用所有的上下文,不管是不是使用者定義的。這種後處理器的型別是很有的,因為它允許自定義bean工程,例如增加/刪除/修改已有的bean定義或則增加一個新的bean例項 |
Extender預設行為 |
osgiApplicationContextListener |
OsgiBundleApplicationContextListener[e] |
應用上下文事件監聽器是由extender自動註冊的 |
預設實現提供了應用上下文生命週期的日誌記錄功能 |
[a]org.springframework.core.task [b]org.springframework.core.task [c]org.springframework.context.event [d]org.eclipse.gemini.blueprint.extender package [e]org.eclipse.gemini.blueprint.context.event package |
從extenderPropertiesbean,下面的屬性被識別:
另外,在Eclipse Gemini Blueprint中,引入了新的系統屬性來控制提供名稱空間的bundle是否被認為應該處於RESOLVED (預設)或STARTED狀態。前一種狀態允許一旦安裝到OSGi框架的bundle的依賴解析了,就可以獲得該名稱空間-它的優勢是名稱空間儘可能快的變為可用,但是缺點是,要移除名稱空間,就需要移除源bundle。後面的狀態只有當源bundle實際啟動時,才會強制考慮名稱空間,要移除名稱空間,只需要簡單的停止它自己的bundle即可。然而,bundle的啟動順序會影響名稱空間的可用性-提供名稱空間的bundle需要先啟動,使用這些名稱空間的bundle後啟動-依賴於應用,這樣的依賴圖可能導致難以捉摸的問題(在執行時)。因此,如果定義了系統屬性org.eclipse.gemini.blueprint.ns.bundles.started,並設定為true,那麼只有started狀態的bundle的名稱空間才被考慮,如果設定false,那麼resolved狀態的bundle會被使用。
表8.3. 可用的extenderProperties
名字 |
型別 |
描述 |
預設值 |
shutdown.wait.time |
java.lang.Long |
每一個應用優雅關閉等待的時間,單位毫秒(ms) |
10000 ms (10 s) |
dependencies.wait.time |
java.lang.Long |
新建立的應用上下文等待強制服務依賴的時間。單位毫秒(ms)。這個設定只用於上下文自己的bundle manifest不定義該值 |
300000 ms (300 s或5 min) |
注意 |
由於使用應用上下文,Spring IoC容器的全功能用於建立extender的配置 |