閱讀425 返回首頁    go 技術社區[雲棲]


適應各種開發,測試,線上,線下環境的Spring配置方式

背景

假設開發了一個中間件,比如是一個緩存係統,這個中間件要配置一個IP地址,還要配置一個Factory,從這個Factory裏得到一個client,如:

<bean name="cacheFactory" >
    <property name="address" value="192.168.1.100"/>
</bean>
<bean name="cacheClient" factory-bean="cacheFactory" factory-method="getClient" />

然後這個中間件有三個集群(clusterA, clusterB, clusterC),分別給不同的業務使用,那就這時會有很多的配置的麻煩。

  • 從使用者的角度出發,應用不喜歡引入一堆的配置,它們隻希望import一個配置文件,然後在代碼裏用@AutoWried注入一個Bean,就可以使用了。
  • Spring Bean被覆蓋的風險。

如果兩個不同的業務都使用了這個cache,然後它們的jar包又再被第三個業務引用,那麼它們都import了一個cache service的配置,那麼就有可能出現後麵的Bean定義被前麵的覆蓋了。而Spring默認不處理這種Bean重複定義的問題。

  • @AutoWried 注入的問題。和上一個問題類似,@AutoWried注入時如果沒有配置@Qualifier,那麼如果某個類有多個Bean實例,那麼就有可能出現Bean注入混亂的情況。
  • 線上環境臨時切換。必須要支持線上臨時修改配置。
  • 開發者無需配置。要提供默認值的配置,開發者不用做配置就可以直接在本地和測試環境運行代碼。
  • 靜默發布新版配置。比如當集群遷移了,IP地址變換了,應用不用修改代碼和配置,隻需要用Maven重新打包即可。

可以利用的技術

spring profile,,@AutoWried,@Qualifier, PropertyPlaceholderConfigurer,PropertyOverrideConfigurer。

profile,PropertyPlaceholderConfigurer等的相關,不一一介紹了。如果有不明白的,可以到spring的文檔裏參考下。


簡要列舉下是如何解決上麵的問題的。

1.在緩存中間件的jar包裏放上三個集群的默認配置:


2.看下spring-cacheClusterA.xm裏的內容:

	<beans pro>
		<bean  >
			<property name="address" value="${cache.address.clusterA:127.0.0.1}"/>
		</bean>
		<bean name="cacheClusterAClient" factory-bean="cacheClusterAFactory" factory-method="getClient" />
	</beans>
	
	<beans pro>
		<bean  >
			<property name="address" value="${cache.address.clusterA:192.168.1.101}"/>
		</bean>
		<bean name="cacheClusterAClient" factory-bean="cacheClusterAFactory" factory-method="getClient" />
	</beans>

	<beans pro>
		<bean  >
			<property name="address" value="${cache.address.clusterA:10.10.1.10}"/>
		</bean>
		<bean name="cacheClusterAClient" factory-bean="cacheClusterAFactory" factory-method="getClient" />
	</beans>	

裏麵定義了三個profile:dev,test,product。這三個profile分別對應開發,測試,線上三種環境。

而在具體bean的配置上,用了一些"${}"這樣的占位符,另外還為它們配置了默認值。

PropertyPlaceholderConfigurer,PropertyOverrideConfigurer可以配置默認值,估計這功能比較少人知道 。

這樣就解決了不同環境,還要有默認配置的問題。

3.使用者的使用方法

假定使用者要用到clusterA和clusterB這兩個集群,那麼可以這樣配置:

	<context:property-placeholder location="classpath:env.properties" />

	<import resource="cacheConfigDefault/spring-cacheClusterA.xml" />
	<import resource="cacheConfigDefault/spring-cacheClusterB.xml" />

import了緩存中間件的默認配置,然後還用placeholder加載了一個env.properties的環境變量文件。

那麼對於spring-cacheClusterA.xml和spring-cacheClusterB.xml裏的address這個屬性,如果沒有在env.properties裏有配置,則會使用默認配置。

如果想要修改,如修改cacheClusterA的配置,則可以在env.properties裏加下:

#if comment this, will use the default value
cache.address.clusterA=testClusterAAddress

那麼clusterA使用的就是用戶的配置,而不是所依賴的jar包的默認配置了。


詳細代碼

再多詳細的代碼和配置,可以到這裏找到演示的代碼:

https://github.com/hengyunabc/spring-config

其它的一些東東

調試spring placeholder時,或者線上查看placeholder到底有沒有工作時,可以把spring的log級別調為TRACE,這樣就可以看到很多有用的信息了。


最後更新:2017-04-03 12:54:50

  上一篇:go xmpp即時通訊三
  下一篇:go git 使用初步