原文轉(zhuǎn)自:http://www.uusam.com/uu/blog/article.asp?id=80
?
最近研究Spring的JDBC DataSource配置問題,看到proxool這個(gè)東西,根據(jù)網(wǎng)上大部分網(wǎng)友的評論,對proxool情有獨(dú)鐘。我于是去下載了一個(gè)最新版本:0.9.0RC2,你可以到http://proxool.sf.net/去下載。
我根據(jù)官方文檔進(jìn)行了Datasource的配置,但是發(fā)現(xiàn)了問題。像大多數(shù)網(wǎng)友反應(yīng)的一樣,出現(xiàn)了“參數(shù)無效的問題”。我根據(jù)源碼進(jìn)行了分析,終于發(fā)現(xiàn)了問題所在。
?
Proxool 指南里配置的例子如下:
?

5. Configuration example for Tomcat
Configuration method: ObjectFactory
Configure a resource with ProxoolDataSource as the factory in server.xml (or the other places a context element can exist):
												<context>
										
												??? <Resource
										
												??????? name="jdbc/mydatasource"
										
												??????? auth="Container"
										
												??????? type="javax.sql.DataSource"
										
												??????? factory="org.logicalcobwebs.proxool.ProxoolDataSource"
										
												??????? proxool.alias="hrs"
										
												??????? user="joe"
										
												??????? password="******"
										
												??????? delegateProperties="foo=bar"
										
												??????? proxool.driver-url="jdbc:oracle:thin:@127.0.0.1:1521:DB"
										
												??????? proxool.driver-class="oracle.jdbc.driver.OracleDriver"/>
										
</context>
?
看完后照著例子做,寫出簡單的配置文件:
?

<? xml version = "1.0" encoding = "GBK" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<!--
??? 描述: ProxoolSample 默認(rèn)連接的數(shù)據(jù)源
??? 作者:悠游
??? 時(shí)間:2006-08-07
??? 備注:
??? ???? 該類的諸多屬性請參考Proxool文檔.
???
-->
?
< beans >
??? <!-- Proxool 默認(rèn)連接的數(shù)據(jù)源 -->
??? < bean id = "ProxoolSample"
??????? class = "org.logicalcobwebs.proxool.ProxoolDataSource" >
??????? < property name = "driver" >
??????????? < value > ${oracle.121.driverClassName} </ value >
??????? </ property >
??????? < property name = "driverUrl" >
??????????? < value > ${oracle.121.url} </ value >
??????? </ property >
??????? < property name = "user" >
??????????? < value > ${oracle.121.userName} </ value >
??????? </ property >
??????? < property name = "password" >
??????????? < value > ${oracle.121.passWord} </ value >
??????? </ property >
??? </ bean >
???
??? <!-- 配置屬性文件 -->
??? < import resource = "../resource/Properties.xml" />
</ beans >
?
?
測試,結(jié)果和預(yù)期一樣,參數(shù)無效報(bào)錯(cuò)了。斷點(diǎn)跟蹤到最后發(fā)現(xiàn)這么一個(gè)問題:配置的用戶名和密碼丟失!
?
大家都知道以前自己在寫連接池的時(shí)候最后一步是這個(gè)DriverManager.getConnection(url, info)方法。 url就是連接的url,info是屬性類。里面最基本要存放兩個(gè)屬性,不用說就知道是user和password。但是斷點(diǎn)跟蹤到proxool最后一步的時(shí)候發(fā)現(xiàn)info是空的,所以就出現(xiàn)了上述參數(shù)無效的問題。
?
?????? 回頭看問題到底出現(xiàn)在哪里?info不就是一開始的時(shí)候注入到工廠里面的delegateProperties屬性么?看他的源碼如下:

??? /**
???? * Set any property that should be handed to the delegate driver.
???? * E.g. <code>foo=1,bar=true</code>
???? * @param properties a comma delimited list of name=value pairs
???? * @see ConnectionPoolDefinitionIF#getDelegateProperties()
???? */
??? public void setDelegateProperties(String properties) {
??????? StringTokenizer stOuter = new StringTokenizer(properties, "," );
??????? while (stOuter.hasMoreTokens()) {
??????????? StringTokenizer stInner = new StringTokenizer(stOuter.nextToken(), "=" );
??????????? if (stInner.countTokens() != 2) {
??????????????? throw new IllegalArgumentException( "Unexpected delegateProperties value: '" + properties + "'. Expected 'name=value'" );
??????????? }
??????????? delegateProperties.put(stInner.nextToken().trim(), stInner.nextToken().trim());
??????? }
??? }
?????? 不用細(xì)看,大概就知道他希望如果有的話把foo=1,bar=true兩個(gè)附加屬性放進(jìn)去了。那個(gè)用戶名和密碼怎么沒放進(jìn)去呢?自己放算了,于是我這樣增加了點(diǎn)東西:
?

??? < property name = "delegateProperties" >
????? < value > user=${oracle.121.userName},password=${oracle.121.passWord} </ value >
??? </ property >
?
?????? 測試,結(jié)果通過,不過有點(diǎn)投機(jī)取巧。因?yàn)?span style="FONT-SIZE: 10pt">foo=1,bar=trueuser=××,password=××都正好是兩個(gè)屬性。
?
??? 知道怎么回事了就行了,看來這是個(gè)BUG。經(jīng)過解析,發(fā)現(xiàn)了最終原因:
?
類: ProxoolDataSource
方法:registerPool
問題:
???

??????????? cpd.setAlias(getAlias());
????? ?????? cpd.setDriver(getDriver());
??????????? cpd.setFatalSqlExceptionsAsString(getFatalSqlExceptionsAsString());
??????????? cpd.setFatalSqlExceptionWrapper(getFatalSqlExceptionWrapperClass());
??????????? cpd.setHouseKeepingSleepTime(getHouseKeepingSleepTime());
??????????? cpd.setHouseKeepingTestSql(getHouseKeepingTestSql());
??????????? cpd.setMaximumActiveTime(getMaximumActiveTime());
??????????? cpd.setMaximumConnectionCount(getMaximumConnectionCount());
??????????? cpd.setMaximumConnectionLifetime(getMaximumConnectionLifetime());
??????????? cpd.setMinimumConnectionCount(getMinimumConnectionCount());
??????????? cpd.setPrototypeCount(getPrototypeCount());
??????????? cpd.setPassword(getPassword());
??????????? cpd.setRecentlyStartedThreshold(getRecentlyStartedThreshold());
??????????? cpd.setSimultaneousBuildThrottle(getSimultaneousBuildThrottle());
??????????? cpd.setUser(getUser());
??????????? cpd.setStatistics(getStatistics());
??????????? cpd.setStatisticsLogLevel( getStatisticsLogLevel ());
?????? ????? cpd.setTrace(isTrace());
??????????? cpd.setUrl(getDriverUrl());
??????????? cpd.setVerbose(isVerbose());
??????????? cpd.setJmx(isJmx());
??????????? cpd.setJmxAgentId(getJmxAgentId());
??????????? cpd.setTestAfterUse(isTestAfterUse());
??????????? cpd.setTestBeforeUse(isTestBeforeUse());
??????????? cpd.setDelegateProperties(delegateProperties);
???
cpd 對象里面有個(gè)properties屬性。在cpd設(shè)置完成用戶名和密碼后,最后一步設(shè)置delegateProperties屬性的時(shí)候把原來的屬性給覆蓋掉了,這個(gè)就是最終原因。改改:
?

??????????? cpd.setDelegateProperties(delegateProperties);
??????????? cpd.setUser(getUser());
?????? ????? cpd.setPassword(getPassword());
???
重新bunid、測試、ok!
?
Evil Gard 2003 年推出了 0.8 ×版本,這次的 0.9 RC2 改動較大。所以出現(xiàn)上述問題在所難免,偶英文不好。誰有時(shí)間去提交個(gè) BUG 說明,希望早日看到 0.9 正式版推出。