JDBC開發之數據庫連接池
使用數據庫連接池優化程序性能
應用程序直接獲取鏈接的缺點:用戶每次請求都需要向數據庫獲得鏈接,而數據庫創建連接通常需要消耗相對較大的資源,創建時間也較長。假設網站一天10萬訪問量,數據庫服務器就需要創建10萬次連接,極大的浪費數據庫的資源,並且極易造成數據庫服務器內存溢出、宕機。
編寫數據庫連接池
編寫連接池需實現javax.sql.DataSource接口。DataSource接口中定義了兩個重載的getConnection方法:
Connection getConnection()
Connection getConnection(String username, String password)
實現DataSource接口,並實現連接池功能的步驟:
在DataSource構造函數中批量創建與數據庫的連接,並把創建的連接加入LinkedList對象中。
實現getConnection方法,讓getConnection方法每次調用時,從LinkedList中取一個Connection返回給用戶。
當用戶使用完Connection,調用Connection.close()方法時,Collection對象應保證將自己返回到LinkedList中,而不要把conn還給數據庫。
Collection保證將自己返回到LinkedList中是此處編程的難點。
數據庫連接池核心代碼
使用動態代理技術構建連接池中的connection
proxyConn = (Connection) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), conn.getClass().getInterfaces(),
new InvocationHandler() {
//此處爲內部類,當close方法被調用時將conn還回池中,其它方法直接執行
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.getName().equals("close")) {
pool.addLast(conn);
return null;
}
return method.invoke(conn, args);
}
});
動態代理
明確兩個概念:
代理對象存在的價值:主要用於攔截對真實業務對象的訪問。
代理對象有什麼方法?
如何生成代理對象?
Java提供了一個Proxy類,調用它的newInstance方法可以生成某個對象的代理對象,使用該方法生成代理對象時,需要三個參數:
1.生成代理對象使用哪個類裝載器
2.生成哪個對象的代理對象,通過接口指定
3.生成的代理對象的方法裏幹什麼事,由開發人員編寫handler接口的實現來指定。
初學者必須理解,或不理解必須記住的2件事情:
Proxy類負責創建代理對象時,如果指定了handler(處理器),那麼不管用戶調用代理對象的什麼方法,該方法都是調用處理器的invoke方法。
由於invoke方法被調用需要三個參數:代理對象、方法、方法的參數,因此不管代理對象哪個方法調用處理器的invoke方法,都必須把自己所在的對象、自己(調用invoke方法的方法)、方法的參數傳遞進來。
開源數據庫連接池
現在很多WEB服務器(Weblogic, WebSphere, Tomcat)都提供了DataSource的實現,即連接池的實現。通常我們把DataSource的實現,按其英文含義稱之爲數據源,數據源中都包含了數據庫連接池的實現。
也有一些開源組織提供了數據源的獨立實現:
DBCP 數據庫連接池
C3P0 數據庫連接池
實際應用時不需要編寫連接數據庫代碼,直接從數據源獲得數據庫的連接。程序員編程時也應儘量使用這些數據源的實現,以提升程序的數據庫訪問性能。
DBCP數據源
DBCP 是 Apache 軟件基金組織下的開源連接池實現,使用DBCP數據源,應用程序應在系統中增加如下兩個 jar 文件:
Commons-dbcp.jar:連接池的實現
Commons-pool.jar:連接池實現的依賴庫
Tomcat 的連接池正是採用該連接池來實現的。該數據庫連接池既可以與應用服務器整合使用,也可由應用程序獨立使用。
使用DBCP示例代碼:
static{
InputStream in = JdbcUtil.class.getClassLoader().
getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
dataSource = factory.createDataSource(prop);
}
配置Tomcat數據源
查看Tomcat文檔,示例代碼:
<Context>
<Resource name="jdbc/datasource" auth="Container"
type="javax.sql.DataSource" username="root" password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbc"
maxActive="8" maxIdle="4"/>
</Context>
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/datasource");
特別提醒:此種配置下,驅動jar文件需放置在tomcat的lib下