反向控制:協(xié)調(diào)以來對象之間合作的責(zé)任從對象自身中轉(zhuǎn)移出來,這就是像Spring這樣的輕量級框架所起的作用。
創(chuàng)建系統(tǒng)組件之間關(guān)聯(lián)的動作叫做裝配。在Spring應(yīng)用系統(tǒng)中,BeanFactory負責(zé)裝載Bean的定義并把它們裝配起來。
IOC使軟件組件松散連接成為可能,AOP讓你能夠捕捉系統(tǒng)中經(jīng)常使用的功能,把它轉(zhuǎn)化為組件。
系統(tǒng)由很多組件組成,每個組件負責(zé)一部分功能,然而,這些組件也經(jīng)常帶有一些除了核心功能之外的附帶功能。系統(tǒng)服務(wù)如日志、事務(wù)管理和安全經(jīng)常融入到一些其他功能模塊中。這些系統(tǒng)服務(wù)通常叫做交叉業(yè)務(wù),這是因為它們總是分布在系統(tǒng)的很多組件中。通過將這些業(yè)務(wù)分布在多個組件中,給你的代碼引入了雙重復(fù)雜性。
ProxyFactoryBean當(dāng)需要容器提供一個對象時,它返回一個針對這個對象所有調(diào)用的攔截器對象,在調(diào)用目標(biāo)對象方法之前給AOP對象一個先執(zhí)行的機會。AOP對象執(zhí)行完畢后,控制權(quán)轉(zhuǎn)回給這個對象,由它執(zhí)行自己的任務(wù)。
盡管Spring的AOP支持可以被用于從系統(tǒng)核心羅集中分離交叉任務(wù),但是它的主要任務(wù)是作為Spring對聲明式事務(wù)支持的基礎(chǔ),Spring帶有很多為JavaBean提供聲明式事務(wù)策略的切面。Acegi安全系統(tǒng)為JavaBean提供了聲明式安全服務(wù)。
Spring的所有模塊都是建立在核心容器之上的。容器規(guī)定如何創(chuàng)建和配置Bean,以及很多Spring的具體細節(jié)。
核心容器:Spring核心容器為Spring框架提供了基礎(chǔ)功能。在這個模塊中你會找到BeanFactory,它是所有基于Spring框架系統(tǒng)的核心。BeanFactory采用工廠模式來實現(xiàn)IOC,它將系統(tǒng)的配置和依賴關(guān)系從代碼中獨立出來。
Application Context模塊
上下文模塊是使Spring成為框架的原因。這個模塊擴展了BeanFactory.這個模塊提供了很多企業(yè)級服務(wù)如電子郵件服務(wù)、JNDI訪問、EJB繼承、遠程調(diào)用以及定時服務(wù),并且支持與模板框架的集成。
Spring的AOP模塊
在AOP模塊中,Spring對面向切面提供了豐富的支持。這個模塊是為Spring應(yīng)用系統(tǒng)開發(fā)切面的基礎(chǔ)。
JDBC抽象及DAO模塊
Spring的JDBC和DAO模塊把這些樣板式的代碼抽象出來,讓你的數(shù)據(jù)庫代碼變得簡單明了。
O/R映射集成模塊
Spring不想實現(xiàn)自己的ORM解決方案,但是它為許多流行的ORM框架做了鉤子程序,包括Hibernate、JDO和iBatis映射,Spring的事務(wù)管理支持所有這些ORM框架以及JDBC.
Spring的web模塊
web上下文模塊建立在應(yīng)用上下文模塊的基礎(chǔ)之上,提供了適合web系統(tǒng)的上下文。
Spring MVC框架
Spring為web系統(tǒng)提供了全功能的MVC框架。
應(yīng)用:
使用<property>元素表示設(shè)置屬性值。使用<constructor-arg>元素表示通過構(gòu)造方法設(shè)置參數(shù)
public class HelloApp{
public static void main(String[] args)throws Exception{
BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml"));
GreetingService greetingService = (GreetingService)factory.getBean("greetingSercice");
greetingService.sayGreeting();
}
}
這里的BeanFactory就是Spring容器。將hello.xml文件載入容器后,main()方法調(diào)用BeanFactory的getBean()方法來得到問候服務(wù)的引用。
反向控制:控制的什么方面被反轉(zhuǎn)了,獲得依賴對象的方式反轉(zhuǎn)了。
依賴注入:任何重要的系統(tǒng)都需要至少2個相互合作的類來完成業(yè)務(wù)邏輯,通常,每個對象都要自己負責(zé)得到它的合作(依賴)對象。你會發(fā)現(xiàn),這樣會導(dǎo)致代碼耦合度高而且難以測試。
使用IOC,對象的依賴都是在對象創(chuàng)建時由負責(zé)協(xié)調(diào)系統(tǒng)中各個對象的外部實體提供的。
耦合是一個雙頭怪物,一方面,緊密耦合的代碼難以測試,難以重用,難以理解,帶來典型的摧毀大堤bug.另一方面,完全沒有耦合的代碼什么也做不了。為了做一些有意義的工作,類必須以某種方式知道其他類的存在。耦合是必須的,但需要小心管理。
減少耦合的一個通常的做法就是將具體實現(xiàn)隱藏在接口下面,這樣具體實現(xiàn)類的替換不會影響到引用類。
Spring以反向控制和AOP這2種先進的設(shè)計理念為基礎(chǔ)。統(tǒng)一了應(yīng)用對象的查找、配置和生命周期管理,分離了業(yè)務(wù)與基礎(chǔ)服務(wù)中的不同關(guān)注點。
在業(yè)務(wù)層,Spring為企業(yè)級應(yīng)用提供了一個相當(dāng)全面的解決方案。這個方案包括數(shù)據(jù)庫持久化支持、聲明式事務(wù)管理、遠程服務(wù)訪問,以及JMS、Mail、定時等多種企業(yè)服務(wù)。
在WEB層,Spring為企業(yè)級應(yīng)用提供了一個MVC框架,該框架與其他流行的Web框架相比毫不遜色;而且Spring可以集成各種Web框架和視圖技術(shù)。
Java可以實現(xiàn)使用分布的模塊來建立一個復(fù)雜的系統(tǒng),他們?yōu)锳pplet而來,為組件而留。
復(fù)雜的系統(tǒng)往往需要一些JavaBeans無法直接提供的服務(wù),如事務(wù)支持、安全、分布計算等,所以在1998年3月,Sun發(fā)不了EJB1.0規(guī)范。它把Java組件擴展到服務(wù)器端,提供了很多必須的企業(yè)級服務(wù),但是它不像原來的JavaBean那樣簡單了。
現(xiàn)在Java組件開發(fā)重新煥發(fā)青春,很多新技術(shù)包括AOP和Ioc為JavaBean提供了很多EJB才擁有的強大功能,為JavaBeans提供了類似于EJB那樣的聲明式編碼模型,同事沒有帶來任何像EJB那樣的復(fù)雜問題。
首先為什么要使用EJB,如果沒有使用實體Bean,所以沒有使用持久化服務(wù),同樣如果沒有使用遠程服務(wù)和安全服務(wù)。就沒有必要使用EJB.EJB之所以復(fù)雜是因為EJB是為解決復(fù)雜問題而設(shè)計的,如分布式對象和遠程事務(wù)的問題。
作為一個開發(fā)者,你始終應(yīng)該為你的系統(tǒng)找到最好的設(shè)計而不是實現(xiàn)。Spring背后的理念是讓你的系統(tǒng)按照你的需求盡量簡單。如果你需要的只是使用簡單Java對象來提供一些支持透明事務(wù)的服務(wù)的話,使用Spring就足夠了。
使用Spring,你的Bean通過接口與它的關(guān)聯(lián)類通信。因為不依賴任何特殊實現(xiàn),所以采用Spring的系統(tǒng)是松耦合的,易測試的和易維護的。
因為開發(fā)Spring應(yīng)用系統(tǒng)使用的都是JavaBeans,所以測試很簡單。你不需要啟動J2EE容器,因為你測試的是一個POJO.
Spring是為簡化企業(yè)級系統(tǒng)開發(fā)而誕生的。使用Spring,你可以用簡單的JavaBeans來實現(xiàn)那些以前只有EJB才能實現(xiàn)的功能。
Spring是一個輕量級的Ioc和AOP容器框架
輕量級:Spring是非侵入式的,基于Spring開發(fā)的系統(tǒng)中的對象一般不依賴于Spring的類。
反向控制:使用IOC,對象是被動接收依賴類而不是自己主動去找。可以將IOC理解為JNDI的反轉(zhuǎn)-對象不是從容器中查找它的依賴類,而是容器在實例化對象的時候主動將它的依賴類注入給它。
面向切面:通過將業(yè)務(wù)邏輯從系統(tǒng)服務(wù)中分離出來,實現(xiàn)了內(nèi)聚開發(fā)。系統(tǒng)對象只做它們該做的-業(yè)務(wù)邏輯,它們不負責(zé)其他系統(tǒng)問題(如日志和事務(wù)支持)。
容器:Spring是一個容器,是因為它包含并且管理系統(tǒng)對象的生命周期和配置。
框架:Spring實現(xiàn)了使用簡單的組件配置組合成一個復(fù)雜的系統(tǒng)。
Hibernate基礎(chǔ)配置選項主要圍繞SessionFactory展開:
在hibernate.cfg.xml配置文件中,我們可以通過mapping節(jié)點配置需要加載的Hibernate映射文件,如果選用了propertie
形式的配置文件(hibernate.properties),由于缺乏相應(yīng)的配置條目,這時候就需要通過編碼進行加載:
Configuration cfg = new Configuration().addFile("TUser.hbm.xml").addClass(com.redsage.db.entity.TGroup.class)
1、添加位于CLASSPATH根目錄下的TUser.hbm.xml映射文件
2、以class形式加載映射實體類com.readsage.db.entity.TGroup
在Hibernate中,可以設(shè)置2種數(shù)據(jù)庫訪問策略:一種是根據(jù)指定的JDBC參數(shù)進行數(shù)據(jù)庫連接,由Hibernate來完成連接管
理過程:另外一種則是通過JNDI完成數(shù)據(jù)庫連接獲取。
1、數(shù)據(jù)庫適配器
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
2、數(shù)據(jù)庫JDBC驅(qū)動類
hibernate.connection.driver_class com.mysql.jdbc.Driver
JNDI配置:
hibernate.connection.datasource jdbc/test
3、數(shù)據(jù)庫URL
hibernate.connection.url jdbc:mysql://localhost/sample
4、數(shù)據(jù)庫用戶名
hibernate.connection.username root
5、數(shù)據(jù)庫密碼
hiberante.connection.password
當(dāng)我們使用JDBC方式訪問數(shù)據(jù)庫時,可以為其指定數(shù)據(jù)庫連接池實現(xiàn),目前Hibernate支持4種連接池實現(xiàn)組件:
C3P0:
hibernate.c3p0.max_size 2
hibernate.c3p0.min_size 2
//獲得連接的超時時間,如果超過這個時間,會拋出異常,單位毫秒
hibernate.c3p0.timeout 5000
//最大的PreparedStatement的數(shù)量
hibernate.c3p0.max_statements 100
//每隔3000秒檢查連接池里的空閑連接 ,單位是秒
hibernate.c3p0.idle_test_period 3000
//當(dāng)連接池里面的連接用完的時候,C3P0一下獲取的新的連接數(shù)
hibernate.c3p0.acquire_increment 2
//每次都驗證連接是否可用
hibernate.c3p0.validate false
hibernate.connection.provider_class net.sf.hibernate.connection.C3p0ConnectionProvider
解釋:
hibernate.c3p0.timeout,這個表示連接池中的連接對象在多長時間沒有使用過后,就應(yīng)該被銷毀
hibernate.c3p0.idle_test_period ,這個表示連接池檢測線程多長時間檢測一次池內(nèi)的所有鏈接對象是否超時
注意:連接對象自己不會把自己從連接池中移除,而是專門有一個線程按照一定的時間間隔
(hibernate.c3p0.idle_test_period )來做這件事,這個線程通過比較連接對象最后一次被使用時間和當(dāng)前時間的時間差來
和hibernate.c3p0.timeout做對比,進而決定是否銷毀這個連接對象。
DBCP:
//連接池的最大活動個數(shù)
hibernate.dbcp.maxActive 100
//當(dāng)連接池中的連接已經(jīng)被耗盡的時候,DBCP將怎樣處理( 0 = 失敗, 1 = 等待, 2= 增長)
hibernate.dbcp.whenExhaustedAction 1
//最大等待時間
hibernate.dbcp.maxWait 120000
//沒有人用連接的時候,最大閑置的連接個數(shù)。
hibernate.dbcp.maxIdle 10
hibernate.dbcp.ps.maxActive 100
hibernate.dbcp.ps.whenExhaustendAction 1
hibernate.dbcp.ps.maxWait 120000
hibernate.dbcp.ps.maxIdle 10
//給出一條簡單的sql語句進行驗證
hibernate.dbcp.validationQuery select 1 from dual
//在取出連接時進行有效驗證
hibernate.dbcp.testOnBorrow true
//在放回連接時進行有效驗證
hibernate.dbcp.testOnreturn false
//Hibernate已經(jīng)實現(xiàn)了DBCP Provider實現(xiàn),別忘了在下面的鍵值去掉#字符
hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider 在Hibernate中,session負責(zé)完成對象的持久化操作,而Hibernate Session與之Hibernate,相當(dāng)于JDBCConnection與之JDBC
1、初始化Hibernate配置管理類Configuration
Configuration config = new Configuration().configure();
利用CLASSPATH中的默認(rèn)配置文件hibernate.cfg.xml構(gòu)建Configuration實例。
2、通過Configuration類實例創(chuàng)建Session的工廠類SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory();
3、通過SessionFactory得到Session實例
session = sessionFactory.openSession();
通過這個Session實例,就可以對對象進行持久化操作
Configuration類負責(zé)管理Hibernate的配置信息,Hibernate運行時需要獲取一些底層實現(xiàn)的基本信息,包括:
數(shù)據(jù)庫URL
數(shù)據(jù)庫用戶名
數(shù)據(jù)庫用戶密碼
數(shù)據(jù)庫JDBC驅(qū)動類
數(shù)據(jù)庫適配器,用于對特定數(shù)據(jù)庫提供支持。
Configuration類一般只有在獲取SessionFactory時需要涉及,當(dāng)SessionFactory實例創(chuàng)建之后,由于配置信息已經(jīng)由hibernate綁定在返回的SessionFactory之中,因此一般情況下無需在對其操作。
如果不希望使用默認(rèn)的hibernate.cfg.xml文件作為配置文件,還有如下方法:
File file = new File("c:\\sample\\myhiernate.xml");
Configuration config = new Configuration().configure(file);
SessionFactory負責(zé)創(chuàng)建Session實例:
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
SessionFactory一旦構(gòu)造完成,即被賦予特定的配置信息。如果需要使用基于改動后的config實例的SessionFactory,需要從config重新構(gòu)建一個SessionFactory實例。
SessionFactory中保存了對應(yīng)當(dāng)前數(shù)據(jù)庫配置的所有映射關(guān)系,同時也負責(zé)維護當(dāng)前的二級緩存和Statement Pool.由此可見,SessionFactory的創(chuàng)建過程必然非常復(fù)雜,代價高昂,而這也就意味著,我們應(yīng)該在系統(tǒng)設(shè)計中充分考慮到SessionFactory的重用策略。由于SessionFactory是線程安全的,可以多個線程并發(fā)調(diào)用,大多數(shù)情況下,一個應(yīng)用中針對一個數(shù)據(jù)庫共享一個SessionFactory實例即可。
Session作為貫穿Hibernate的持久化管理器核心,提供了眾多持久化方法,如save、update、delete,find等。通過這些方法,可透明的完成對象的增刪改查。同事,Hibernate Session的設(shè)計是非線程安全的,也就是說,一個Session實例同時只可一個線程使用,同一個Session實例的多線程并發(fā)調(diào)用將導(dǎo)致難以預(yù)知的錯誤
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Save操作:
Get操作:
delete操作:
//也可以通過HQL指定刪除條件(Hibernate2)
//通過Query接口進行基于HQL的刪除操作(Hibernate3)
Hibernate3中的Session接口取消了find方法,我們必須通過Query或Criteria接口進行數(shù)據(jù)查詢
通過Query接口進行數(shù)據(jù)查詢:
通過Criteria接口進行數(shù)據(jù)查詢:
Query面向HQL和Native SQL,而Criteria則提供了面向?qū)ο蟮牟樵兡J健?br />
Hibernate對JDBC進行了妥善封裝,會自動根據(jù)對象和表之間的映射關(guān)系,將對象操作轉(zhuǎn)換為SQL加以執(zhí)行。
Hibernate基礎(chǔ)代碼包括POJO類和Hibernate映射文件。
POJO在Hibernate語義中理解為數(shù)據(jù)庫表所對應(yīng)的Domain Object.字面上來講就是無格式普通Java對象,可以簡單的理解為一個不包含邏輯代碼的值對象(Value Object簡稱VO),從數(shù)據(jù)層面上看,POJO作為數(shù)據(jù)實體的對象化表現(xiàn)形式,也成為實體類。
Hibernate是一種對象-關(guān)系型數(shù)據(jù)映射組件,它使用映射文件將對象與關(guān)系型數(shù)據(jù)相關(guān)聯(lián)。在Hibernate中,映射文件通常以.hbm.xml作為后綴。
配置文件名默認(rèn)為hibernate.cfg.xml,Hibernate初始化期間會自動在CLASSPATH中尋找這個文件,并讀取其中的配置信息,為后期數(shù)據(jù)庫操作做好準(zhǔn)備。
一個典型的hibernate.cfg.xml配置文件如下:
Hibernate3中對包名進行了修改(net.sf.hibernate=>org.hibernate)如果采用hibernate3除了包名修改外,DTD文件也要做對應(yīng)修改http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd
在hibernate項目的SRC目錄下,創(chuàng)建內(nèi)容同上的hibernate.cfg.xml文件。
Hibernate采用Apache common logging,并結(jié)合Apache log4j作為日志輸出組件。
現(xiàn)在眾多應(yīng)用服務(wù)器以及開源社區(qū)中,都提供了完備的數(shù)據(jù)庫連接池組件,選擇采用這些成熟穩(wěn)定的組件作為我們產(chǎn)品開發(fā)的基石,在絕大多數(shù)情況下是比選擇自己實現(xiàn)更聰明的決策,還是那句老話:不要重復(fù)發(fā)明輪子。
2個數(shù)據(jù)庫連接池組件:
Apache Jakarta Commons DBCP
Proxool
JDBC程序設(shè)計中,除了數(shù)據(jù)庫連接,還有另外一個往往被忽視的重要資源---Statement,通過使用PreparedStatement,在絕大多數(shù)情況下可以有效提高重復(fù)性數(shù)據(jù)庫調(diào)用的性能。
借助Connection實例創(chuàng)建PreparedStatement對象相當(dāng)簡單,不過簡單的表面下卻隱藏著復(fù)雜的實現(xiàn),當(dāng)PreparedStatement對象創(chuàng)建時,數(shù)據(jù)庫會對這個PreparedStatement中的SQL進行語法檢查、語義分析、選擇優(yōu)化器并創(chuàng)建相應(yīng)的執(zhí)行計劃。
目前,無論是商業(yè)領(lǐng)域還是開源社區(qū),都已經(jīng)為我們提供了豐富且久經(jīng)考驗的持久層組件,使用這些成熟可靠的已有實現(xiàn)可以在很大程度上規(guī)避技術(shù)上的風(fēng)險,同時迅速提高應(yīng)用系統(tǒng)開發(fā)的勞動產(chǎn)出比。
第一章終于看完了,好累,每看一次,每次的感覺都不一樣。方興未艾。
Decorator模式:簡單來講,就是通過一個Decorator對原有對象進行封裝,同事實現(xiàn)與原有對象相同的接口,從而得到一個基于原有對象的,對既有接口的增強型實現(xiàn)。
首先引入一個ConnectionDecorator類:
動態(tài)代理:
無論是怎樣的應(yīng)用系統(tǒng),都無法脫離對資源的管理和使用。而對于持久層而言,資源的合理管理和調(diào)度則顯得尤為重要。
資源管理機制的設(shè)計對于系統(tǒng)整體表現(xiàn)往往可以產(chǎn)生關(guān)鍵性影響。同時,除去性能之外,良好的資源管理機制還能為系統(tǒng)的伸縮性、可維護性帶來相當(dāng)?shù)奶嵘?br /> Connection Pool:數(shù)據(jù)庫連接池技術(shù)帶來的優(yōu)勢
1、資源重用
由于數(shù)據(jù)庫連接得以重用,避免了頻繁創(chuàng)建、釋放連接引起的大量性能開銷。在減少系統(tǒng)消耗的基礎(chǔ)上,另一方面也增進了系統(tǒng)運行環(huán)境的平穩(wěn)性。
2、更快的系統(tǒng)響應(yīng)速度
數(shù)據(jù)庫連接池在初始化過程中,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫連接池置于池中備用。此時連接的初始化工作均已完成。對于業(yè)務(wù)請求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時間開銷,從而縮減了系統(tǒng)整體響應(yīng)時間。
3、新的資源分配手段
對于多應(yīng)用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應(yīng)用層通過數(shù)據(jù)庫連接池的配置,實現(xiàn)某一應(yīng)用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應(yīng)用獨占所有數(shù)據(jù)庫資源
4、統(tǒng)一的連接管理,避免數(shù)據(jù)庫連接泄露
在較為完備的數(shù)據(jù)庫連接池實現(xiàn)中,可根據(jù)預(yù)先的連接占用超時設(shè)定,強制收回被占用連接。從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄露。
創(chuàng)建系統(tǒng)組件之間關(guān)聯(lián)的動作叫做裝配。在Spring應(yīng)用系統(tǒng)中,BeanFactory負責(zé)裝載Bean的定義并把它們裝配起來。
IOC使軟件組件松散連接成為可能,AOP讓你能夠捕捉系統(tǒng)中經(jīng)常使用的功能,把它轉(zhuǎn)化為組件。
系統(tǒng)由很多組件組成,每個組件負責(zé)一部分功能,然而,這些組件也經(jīng)常帶有一些除了核心功能之外的附帶功能。系統(tǒng)服務(wù)如日志、事務(wù)管理和安全經(jīng)常融入到一些其他功能模塊中。這些系統(tǒng)服務(wù)通常叫做交叉業(yè)務(wù),這是因為它們總是分布在系統(tǒng)的很多組件中。通過將這些業(yè)務(wù)分布在多個組件中,給你的代碼引入了雙重復(fù)雜性。
ProxyFactoryBean當(dāng)需要容器提供一個對象時,它返回一個針對這個對象所有調(diào)用的攔截器對象,在調(diào)用目標(biāo)對象方法之前給AOP對象一個先執(zhí)行的機會。AOP對象執(zhí)行完畢后,控制權(quán)轉(zhuǎn)回給這個對象,由它執(zhí)行自己的任務(wù)。
盡管Spring的AOP支持可以被用于從系統(tǒng)核心羅集中分離交叉任務(wù),但是它的主要任務(wù)是作為Spring對聲明式事務(wù)支持的基礎(chǔ),Spring帶有很多為JavaBean提供聲明式事務(wù)策略的切面。Acegi安全系統(tǒng)為JavaBean提供了聲明式安全服務(wù)。
Spring的所有模塊都是建立在核心容器之上的。容器規(guī)定如何創(chuàng)建和配置Bean,以及很多Spring的具體細節(jié)。
核心容器:Spring核心容器為Spring框架提供了基礎(chǔ)功能。在這個模塊中你會找到BeanFactory,它是所有基于Spring框架系統(tǒng)的核心。BeanFactory采用工廠模式來實現(xiàn)IOC,它將系統(tǒng)的配置和依賴關(guān)系從代碼中獨立出來。
Application Context模塊
上下文模塊是使Spring成為框架的原因。這個模塊擴展了BeanFactory.這個模塊提供了很多企業(yè)級服務(wù)如電子郵件服務(wù)、JNDI訪問、EJB繼承、遠程調(diào)用以及定時服務(wù),并且支持與模板框架的集成。
Spring的AOP模塊
在AOP模塊中,Spring對面向切面提供了豐富的支持。這個模塊是為Spring應(yīng)用系統(tǒng)開發(fā)切面的基礎(chǔ)。
JDBC抽象及DAO模塊
Spring的JDBC和DAO模塊把這些樣板式的代碼抽象出來,讓你的數(shù)據(jù)庫代碼變得簡單明了。
O/R映射集成模塊
Spring不想實現(xiàn)自己的ORM解決方案,但是它為許多流行的ORM框架做了鉤子程序,包括Hibernate、JDO和iBatis映射,Spring的事務(wù)管理支持所有這些ORM框架以及JDBC.
Spring的web模塊
web上下文模塊建立在應(yīng)用上下文模塊的基礎(chǔ)之上,提供了適合web系統(tǒng)的上下文。
Spring MVC框架
Spring為web系統(tǒng)提供了全功能的MVC框架。
應(yīng)用:
使用<property>元素表示設(shè)置屬性值。使用<constructor-arg>元素表示通過構(gòu)造方法設(shè)置參數(shù)
public class HelloApp{
public static void main(String[] args)throws Exception{
BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml"));
GreetingService greetingService = (GreetingService)factory.getBean("greetingSercice");
greetingService.sayGreeting();
}
}
這里的BeanFactory就是Spring容器。將hello.xml文件載入容器后,main()方法調(diào)用BeanFactory的getBean()方法來得到問候服務(wù)的引用。
反向控制:控制的什么方面被反轉(zhuǎn)了,獲得依賴對象的方式反轉(zhuǎn)了。
依賴注入:任何重要的系統(tǒng)都需要至少2個相互合作的類來完成業(yè)務(wù)邏輯,通常,每個對象都要自己負責(zé)得到它的合作(依賴)對象。你會發(fā)現(xiàn),這樣會導(dǎo)致代碼耦合度高而且難以測試。
使用IOC,對象的依賴都是在對象創(chuàng)建時由負責(zé)協(xié)調(diào)系統(tǒng)中各個對象的外部實體提供的。
耦合是一個雙頭怪物,一方面,緊密耦合的代碼難以測試,難以重用,難以理解,帶來典型的摧毀大堤bug.另一方面,完全沒有耦合的代碼什么也做不了。為了做一些有意義的工作,類必須以某種方式知道其他類的存在。耦合是必須的,但需要小心管理。
減少耦合的一個通常的做法就是將具體實現(xiàn)隱藏在接口下面,這樣具體實現(xiàn)類的替換不會影響到引用類。
Spring以反向控制和AOP這2種先進的設(shè)計理念為基礎(chǔ)。統(tǒng)一了應(yīng)用對象的查找、配置和生命周期管理,分離了業(yè)務(wù)與基礎(chǔ)服務(wù)中的不同關(guān)注點。
在業(yè)務(wù)層,Spring為企業(yè)級應(yīng)用提供了一個相當(dāng)全面的解決方案。這個方案包括數(shù)據(jù)庫持久化支持、聲明式事務(wù)管理、遠程服務(wù)訪問,以及JMS、Mail、定時等多種企業(yè)服務(wù)。
在WEB層,Spring為企業(yè)級應(yīng)用提供了一個MVC框架,該框架與其他流行的Web框架相比毫不遜色;而且Spring可以集成各種Web框架和視圖技術(shù)。
Java可以實現(xiàn)使用分布的模塊來建立一個復(fù)雜的系統(tǒng),他們?yōu)锳pplet而來,為組件而留。
復(fù)雜的系統(tǒng)往往需要一些JavaBeans無法直接提供的服務(wù),如事務(wù)支持、安全、分布計算等,所以在1998年3月,Sun發(fā)不了EJB1.0規(guī)范。它把Java組件擴展到服務(wù)器端,提供了很多必須的企業(yè)級服務(wù),但是它不像原來的JavaBean那樣簡單了。
現(xiàn)在Java組件開發(fā)重新煥發(fā)青春,很多新技術(shù)包括AOP和Ioc為JavaBean提供了很多EJB才擁有的強大功能,為JavaBeans提供了類似于EJB那樣的聲明式編碼模型,同事沒有帶來任何像EJB那樣的復(fù)雜問題。
首先為什么要使用EJB,如果沒有使用實體Bean,所以沒有使用持久化服務(wù),同樣如果沒有使用遠程服務(wù)和安全服務(wù)。就沒有必要使用EJB.EJB之所以復(fù)雜是因為EJB是為解決復(fù)雜問題而設(shè)計的,如分布式對象和遠程事務(wù)的問題。
作為一個開發(fā)者,你始終應(yīng)該為你的系統(tǒng)找到最好的設(shè)計而不是實現(xiàn)。Spring背后的理念是讓你的系統(tǒng)按照你的需求盡量簡單。如果你需要的只是使用簡單Java對象來提供一些支持透明事務(wù)的服務(wù)的話,使用Spring就足夠了。
使用Spring,你的Bean通過接口與它的關(guān)聯(lián)類通信。因為不依賴任何特殊實現(xiàn),所以采用Spring的系統(tǒng)是松耦合的,易測試的和易維護的。
因為開發(fā)Spring應(yīng)用系統(tǒng)使用的都是JavaBeans,所以測試很簡單。你不需要啟動J2EE容器,因為你測試的是一個POJO.
Spring是為簡化企業(yè)級系統(tǒng)開發(fā)而誕生的。使用Spring,你可以用簡單的JavaBeans來實現(xiàn)那些以前只有EJB才能實現(xiàn)的功能。
Spring是一個輕量級的Ioc和AOP容器框架
輕量級:Spring是非侵入式的,基于Spring開發(fā)的系統(tǒng)中的對象一般不依賴于Spring的類。
反向控制:使用IOC,對象是被動接收依賴類而不是自己主動去找。可以將IOC理解為JNDI的反轉(zhuǎn)-對象不是從容器中查找它的依賴類,而是容器在實例化對象的時候主動將它的依賴類注入給它。
面向切面:通過將業(yè)務(wù)邏輯從系統(tǒng)服務(wù)中分離出來,實現(xiàn)了內(nèi)聚開發(fā)。系統(tǒng)對象只做它們該做的-業(yè)務(wù)邏輯,它們不負責(zé)其他系統(tǒng)問題(如日志和事務(wù)支持)。
容器:Spring是一個容器,是因為它包含并且管理系統(tǒng)對象的生命周期和配置。
框架:Spring實現(xiàn)了使用簡單的組件配置組合成一個復(fù)雜的系統(tǒng)。
Hibernate基礎(chǔ)配置選項主要圍繞SessionFactory展開:
在hibernate.cfg.xml配置文件中,我們可以通過mapping節(jié)點配置需要加載的Hibernate映射文件,如果選用了propertie
形式的配置文件(hibernate.properties),由于缺乏相應(yīng)的配置條目,這時候就需要通過編碼進行加載:
Configuration cfg = new Configuration().addFile("TUser.hbm.xml").addClass(com.redsage.db.entity.TGroup.class)
1、添加位于CLASSPATH根目錄下的TUser.hbm.xml映射文件
2、以class形式加載映射實體類com.readsage.db.entity.TGroup
在Hibernate中,可以設(shè)置2種數(shù)據(jù)庫訪問策略:一種是根據(jù)指定的JDBC參數(shù)進行數(shù)據(jù)庫連接,由Hibernate來完成連接管
理過程:另外一種則是通過JNDI完成數(shù)據(jù)庫連接獲取。
1、數(shù)據(jù)庫適配器
hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
2、數(shù)據(jù)庫JDBC驅(qū)動類
hibernate.connection.driver_class com.mysql.jdbc.Driver
JNDI配置:
hibernate.connection.datasource jdbc/test
3、數(shù)據(jù)庫URL
hibernate.connection.url jdbc:mysql://localhost/sample
4、數(shù)據(jù)庫用戶名
hibernate.connection.username root
5、數(shù)據(jù)庫密碼
hiberante.connection.password
當(dāng)我們使用JDBC方式訪問數(shù)據(jù)庫時,可以為其指定數(shù)據(jù)庫連接池實現(xiàn),目前Hibernate支持4種連接池實現(xiàn)組件:
C3P0:
hibernate.c3p0.max_size 2
hibernate.c3p0.min_size 2
//獲得連接的超時時間,如果超過這個時間,會拋出異常,單位毫秒
hibernate.c3p0.timeout 5000
//最大的PreparedStatement的數(shù)量
hibernate.c3p0.max_statements 100
//每隔3000秒檢查連接池里的空閑連接 ,單位是秒
hibernate.c3p0.idle_test_period 3000
//當(dāng)連接池里面的連接用完的時候,C3P0一下獲取的新的連接數(shù)
hibernate.c3p0.acquire_increment 2
//每次都驗證連接是否可用
hibernate.c3p0.validate false
hibernate.connection.provider_class net.sf.hibernate.connection.C3p0ConnectionProvider
解釋:
hibernate.c3p0.timeout,這個表示連接池中的連接對象在多長時間沒有使用過后,就應(yīng)該被銷毀
hibernate.c3p0.idle_test_period ,這個表示連接池檢測線程多長時間檢測一次池內(nèi)的所有鏈接對象是否超時
注意:連接對象自己不會把自己從連接池中移除,而是專門有一個線程按照一定的時間間隔
(hibernate.c3p0.idle_test_period )來做這件事,這個線程通過比較連接對象最后一次被使用時間和當(dāng)前時間的時間差來
和hibernate.c3p0.timeout做對比,進而決定是否銷毀這個連接對象。
DBCP:
//連接池的最大活動個數(shù)
hibernate.dbcp.maxActive 100
//當(dāng)連接池中的連接已經(jīng)被耗盡的時候,DBCP將怎樣處理( 0 = 失敗, 1 = 等待, 2= 增長)
hibernate.dbcp.whenExhaustedAction 1
//最大等待時間
hibernate.dbcp.maxWait 120000
//沒有人用連接的時候,最大閑置的連接個數(shù)。
hibernate.dbcp.maxIdle 10
hibernate.dbcp.ps.maxActive 100
hibernate.dbcp.ps.whenExhaustendAction 1
hibernate.dbcp.ps.maxWait 120000
hibernate.dbcp.ps.maxIdle 10
//給出一條簡單的sql語句進行驗證
hibernate.dbcp.validationQuery select 1 from dual
//在取出連接時進行有效驗證
hibernate.dbcp.testOnBorrow true
//在放回連接時進行有效驗證
hibernate.dbcp.testOnreturn false
//Hibernate已經(jīng)實現(xiàn)了DBCP Provider實現(xiàn),別忘了在下面的鍵值去掉#字符
hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider 在Hibernate中,session負責(zé)完成對象的持久化操作,而Hibernate Session與之Hibernate,相當(dāng)于JDBCConnection與之JDBC
1、初始化Hibernate配置管理類Configuration
Configuration config = new Configuration().configure();
利用CLASSPATH中的默認(rèn)配置文件hibernate.cfg.xml構(gòu)建Configuration實例。
2、通過Configuration類實例創(chuàng)建Session的工廠類SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory();
3、通過SessionFactory得到Session實例
session = sessionFactory.openSession();
通過這個Session實例,就可以對對象進行持久化操作
Configuration類負責(zé)管理Hibernate的配置信息,Hibernate運行時需要獲取一些底層實現(xiàn)的基本信息,包括:
數(shù)據(jù)庫URL
數(shù)據(jù)庫用戶名
數(shù)據(jù)庫用戶密碼
數(shù)據(jù)庫JDBC驅(qū)動類
數(shù)據(jù)庫適配器,用于對特定數(shù)據(jù)庫提供支持。
Configuration類一般只有在獲取SessionFactory時需要涉及,當(dāng)SessionFactory實例創(chuàng)建之后,由于配置信息已經(jīng)由hibernate綁定在返回的SessionFactory之中,因此一般情況下無需在對其操作。
如果不希望使用默認(rèn)的hibernate.cfg.xml文件作為配置文件,還有如下方法:
File file = new File("c:\\sample\\myhiernate.xml");
Configuration config = new Configuration().configure(file);
SessionFactory負責(zé)創(chuàng)建Session實例:
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
SessionFactory一旦構(gòu)造完成,即被賦予特定的配置信息。如果需要使用基于改動后的config實例的SessionFactory,需要從config重新構(gòu)建一個SessionFactory實例。
SessionFactory中保存了對應(yīng)當(dāng)前數(shù)據(jù)庫配置的所有映射關(guān)系,同時也負責(zé)維護當(dāng)前的二級緩存和Statement Pool.由此可見,SessionFactory的創(chuàng)建過程必然非常復(fù)雜,代價高昂,而這也就意味著,我們應(yīng)該在系統(tǒng)設(shè)計中充分考慮到SessionFactory的重用策略。由于SessionFactory是線程安全的,可以多個線程并發(fā)調(diào)用,大多數(shù)情況下,一個應(yīng)用中針對一個數(shù)據(jù)庫共享一個SessionFactory實例即可。
Session作為貫穿Hibernate的持久化管理器核心,提供了眾多持久化方法,如save、update、delete,find等。通過這些方法,可透明的完成對象的增刪改查。同事,Hibernate Session的設(shè)計是非線程安全的,也就是說,一個Session實例同時只可一個線程使用,同一個Session實例的多線程并發(fā)調(diào)用將導(dǎo)致難以預(yù)知的錯誤
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Save操作:
//新增名為"Emma"的用戶記錄
TUser user = new TUser();
user.setName("Emma");
session.save(user);
TUser user = new TUser();
user.setName("Emma");
session.save(user);
Get操作:
//假設(shè)T_User表中存在id=1的記錄
TUser user = (TUser)session.get(TUser.class,new Integer(1));
TUser user = (TUser)session.get(TUser.class,new Integer(1));
delete操作:
//假設(shè)T_User表中存在id=1的記錄
TUser user = (TUser)session.get(TUser.class,new Integer(1));
session.delete(user);
TUser user = (TUser)session.get(TUser.class,new Integer(1));
session.delete(user);
//也可以通過HQL指定刪除條件(Hibernate2)
session.delete("from TUser where id=1");
//通過Query接口進行基于HQL的刪除操作(Hibernate3)
String hql = "delete TUser where id=1";
Query query = session.createQuery(hql);
query.executeUpdate();
Find(Hibernate2)操作
String hql = "form TUser where name='Erica'";
List userList = session.find(hql);
Query query = session.createQuery(hql);
query.executeUpdate();
Find(Hibernate2)操作
String hql = "form TUser where name='Erica'";
List userList = session.find(hql);
Hibernate3中的Session接口取消了find方法,我們必須通過Query或Criteria接口進行數(shù)據(jù)查詢
通過Query接口進行數(shù)據(jù)查詢:
String hql = "from TUser user where user.name like ?";
Query query = session.createQuery(hql);
query.setParameter(0,"Cartier");
List list = query.list();
Iterator it = list.iterator();
while(it.hasNext()){
TUser user = (TUser)it.next();
System.out.println(user.getName);
}
Query query = session.createQuery(hql);
query.setParameter(0,"Cartier");
List list = query.list();
Iterator it = list.iterator();
while(it.hasNext()){
TUser user = (TUser)it.next();
System.out.println(user.getName);
}
通過Criteria接口進行數(shù)據(jù)查詢:
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Cartier"));
List list = criteria.list();
Iterator it = list.iterator();
while(it.hasNext()){
TUser user = (TUser)it.next();
System.out.println(user.getName());
}
criteria.add(Expression.eq("name","Cartier"));
List list = criteria.list();
Iterator it = list.iterator();
while(it.hasNext()){
TUser user = (TUser)it.next();
System.out.println(user.getName());
}
Query面向HQL和Native SQL,而Criteria則提供了面向?qū)ο蟮牟樵兡J健?br />
Hibernate對JDBC進行了妥善封裝,會自動根據(jù)對象和表之間的映射關(guān)系,將對象操作轉(zhuǎn)換為SQL加以執(zhí)行。
public class HibernateTest extends TestCase{
Session session = null;
/**
* JUnit中setUp方法在TestCase初始化的時候會自動調(diào)用一般用于初始化公用資源
*/
protected void setUp(){
try{
/**
*采用hibernate.properties或者hibernate.cfg.xml
*配置文件的初始化代碼:
*Configuration config = new Configuration();
*config.addClass(Tuser.class);
*/
//采用hiberante.cfg.xml配置文件
//1、configuration的初始化方式
//2、xml文件中已經(jīng)定義了Mapping文件,因此無需在編碼導(dǎo)入
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
}catch(HibernateException e){
e.printStackTrace();
}
}
/**
*與setUp方法相對應(yīng),JUnitTestCase執(zhí)行完畢時,會自動調(diào)用tearDown方法
*一般用于資源釋放
*/
protected void tearDown(){
try{
session.close();
}catch(HibernateException e){
e.printStackTrace();
}
}
/**
*對象持久化
*/
public void testInsert(){
Transaction tran = null;
try{
tran = session.beginTransaction();
Tuser user = new Tuser();
user.setName("Emma");
session.save(user);
tran.commit();
}catch(HiberanteException e){
e.printStackTrance();
}
}
}
Session session = null;
/**
* JUnit中setUp方法在TestCase初始化的時候會自動調(diào)用一般用于初始化公用資源
*/
protected void setUp(){
try{
/**
*采用hibernate.properties或者hibernate.cfg.xml
*配置文件的初始化代碼:
*Configuration config = new Configuration();
*config.addClass(Tuser.class);
*/
//采用hiberante.cfg.xml配置文件
//1、configuration的初始化方式
//2、xml文件中已經(jīng)定義了Mapping文件,因此無需在編碼導(dǎo)入
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
}catch(HibernateException e){
e.printStackTrace();
}
}
/**
*與setUp方法相對應(yīng),JUnitTestCase執(zhí)行完畢時,會自動調(diào)用tearDown方法
*一般用于資源釋放
*/
protected void tearDown(){
try{
session.close();
}catch(HibernateException e){
e.printStackTrace();
}
}
/**
*對象持久化
*/
public void testInsert(){
Transaction tran = null;
try{
tran = session.beginTransaction();
Tuser user = new Tuser();
user.setName("Emma");
session.save(user);
tran.commit();
}catch(HiberanteException e){
e.printStackTrance();
}
}
}
Hibernate基礎(chǔ)代碼包括POJO類和Hibernate映射文件。
POJO在Hibernate語義中理解為數(shù)據(jù)庫表所對應(yīng)的Domain Object.字面上來講就是無格式普通Java對象,可以簡單的理解為一個不包含邏輯代碼的值對象(Value Object簡稱VO),從數(shù)據(jù)層面上看,POJO作為數(shù)據(jù)實體的對象化表現(xiàn)形式,也成為實體類。
Hibernate是一種對象-關(guān)系型數(shù)據(jù)映射組件,它使用映射文件將對象與關(guān)系型數(shù)據(jù)相關(guān)聯(lián)。在Hibernate中,映射文件通常以.hbm.xml作為后綴。
配置文件名默認(rèn)為hibernate.cfg.xml,Hibernate初始化期間會自動在CLASSPATH中尋找這個文件,并讀取其中的配置信息,為后期數(shù)據(jù)庫操作做好準(zhǔn)備。
一個典型的hibernate.cfg.xml配置文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<!--數(shù)據(jù)庫URL-->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/sample
</property>
<!--數(shù)據(jù)庫JDBC驅(qū)動-->
<property name="hibernate.connection.driver_class">
org.git.mm.mysql.Driver
</property>
<!--數(shù)據(jù)庫用戶名-->
<property name="hibernate.connection.username">
User
</property>
<!--數(shù)據(jù)庫密碼-->
<property name="hibernate.connection.password">
Mypass
</property>
<!--dialect,每個數(shù)據(jù)庫都有其對應(yīng)的Dialect以匹配其平臺特性-->
<property name="hibernate.dialect.MySQLDialect">
net.sf.hibernate.dialect.MySQLDialect
</property>
<!--是否將運行期生成的SQL輸出到日志以供調(diào)試-->
<property name="hibernate.show_sql">
True
</property>
<!--是否使用數(shù)據(jù)庫外連接-->
<property name="hibernate.use_outer_join">
True
</property>
<!--事務(wù)管理類型,這里我們使用JDBC Transaction-->
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JDBCTransactionFactory
</property>
<!--映射文件配置,注意配置文件名必須包含其相對于根的全路徑-->
<mapping resource="com/redsage/quickstart/Tuser.hbm.xml"/>
</session-factory>
</hibernate-configuration>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<!--數(shù)據(jù)庫URL-->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/sample
</property>
<!--數(shù)據(jù)庫JDBC驅(qū)動-->
<property name="hibernate.connection.driver_class">
org.git.mm.mysql.Driver
</property>
<!--數(shù)據(jù)庫用戶名-->
<property name="hibernate.connection.username">
User
</property>
<!--數(shù)據(jù)庫密碼-->
<property name="hibernate.connection.password">
Mypass
</property>
<!--dialect,每個數(shù)據(jù)庫都有其對應(yīng)的Dialect以匹配其平臺特性-->
<property name="hibernate.dialect.MySQLDialect">
net.sf.hibernate.dialect.MySQLDialect
</property>
<!--是否將運行期生成的SQL輸出到日志以供調(diào)試-->
<property name="hibernate.show_sql">
True
</property>
<!--是否使用數(shù)據(jù)庫外連接-->
<property name="hibernate.use_outer_join">
True
</property>
<!--事務(wù)管理類型,這里我們使用JDBC Transaction-->
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JDBCTransactionFactory
</property>
<!--映射文件配置,注意配置文件名必須包含其相對于根的全路徑-->
<mapping resource="com/redsage/quickstart/Tuser.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Hibernate3中對包名進行了修改(net.sf.hibernate=>org.hibernate)如果采用hibernate3除了包名修改外,DTD文件也要做對應(yīng)修改http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd
在hibernate項目的SRC目錄下,創(chuàng)建內(nèi)容同上的hibernate.cfg.xml文件。
Hibernate采用Apache common logging,并結(jié)合Apache log4j作為日志輸出組件。
現(xiàn)在眾多應(yīng)用服務(wù)器以及開源社區(qū)中,都提供了完備的數(shù)據(jù)庫連接池組件,選擇采用這些成熟穩(wěn)定的組件作為我們產(chǎn)品開發(fā)的基石,在絕大多數(shù)情況下是比選擇自己實現(xiàn)更聰明的決策,還是那句老話:不要重復(fù)發(fā)明輪子。
2個數(shù)據(jù)庫連接池組件:
Apache Jakarta Commons DBCP
Proxool
JDBC程序設(shè)計中,除了數(shù)據(jù)庫連接,還有另外一個往往被忽視的重要資源---Statement,通過使用PreparedStatement,在絕大多數(shù)情況下可以有效提高重復(fù)性數(shù)據(jù)庫調(diào)用的性能。
借助Connection實例創(chuàng)建PreparedStatement對象相當(dāng)簡單,不過簡單的表面下卻隱藏著復(fù)雜的實現(xiàn),當(dāng)PreparedStatement對象創(chuàng)建時,數(shù)據(jù)庫會對這個PreparedStatement中的SQL進行語法檢查、語義分析、選擇優(yōu)化器并創(chuàng)建相應(yīng)的執(zhí)行計劃。
目前,無論是商業(yè)領(lǐng)域還是開源社區(qū),都已經(jīng)為我們提供了豐富且久經(jīng)考驗的持久層組件,使用這些成熟可靠的已有實現(xiàn)可以在很大程度上規(guī)避技術(shù)上的風(fēng)險,同時迅速提高應(yīng)用系統(tǒng)開發(fā)的勞動產(chǎn)出比。
第一章終于看完了,好累,每看一次,每次的感覺都不一樣。方興未艾。
Decorator模式:簡單來講,就是通過一個Decorator對原有對象進行封裝,同事實現(xiàn)與原有對象相同的接口,從而得到一個基于原有對象的,對既有接口的增強型實現(xiàn)。
首先引入一個ConnectionDecorator類:
public class ConnectionDecorator implements Connection{
Connection dbconn;
public ConnectionDecorator(Connnection conn){
this.dbconn = conn;//實際從數(shù)據(jù)庫獲得的Connection引用
}
public void close()throws SQLException{
this.dbconn.close();
}
public void commit()throws SQLException{
this.dbconn.commit();//調(diào)用實際連接的commit方法
}

}
ConnectionDecorator類實際上是對傳入的數(shù)據(jù)庫連接加上了一個外殼,它實現(xiàn)了java.sql.Connection接口,不過本身并沒有實現(xiàn)任何實際內(nèi)容,只是簡單的把方法的實現(xiàn)委托給運行期實際獲得的Connection實例,而從外部看,ConnectionDecorator與普通的Connection實例沒有什么區(qū)別。Connection dbconn;
public ConnectionDecorator(Connnection conn){
this.dbconn = conn;//實際從數(shù)據(jù)庫獲得的Connection引用
}
public void close()throws SQLException{
this.dbconn.close();
}
public void commit()throws SQLException{
this.dbconn.commit();//調(diào)用實際連接的commit方法
}

}
public class PooledConnection extends ConnectionDecorator implements Connection{
private ConnectionPool connPool;
public PooledConnection(ConnectionPool pool,Connection conn){
super(conn);
connPool = pool;
}
//覆蓋close方法,將數(shù)據(jù)庫連接返回連接池中,而不是直接關(guān)閉連接
public void close()throws SQLException{
connPool.releaseConnection(this.dbconn);
}
}
private ConnectionPool connPool;
public PooledConnection(ConnectionPool pool,Connection conn){
super(conn);
connPool = pool;
}
//覆蓋close方法,將數(shù)據(jù)庫連接返回連接池中,而不是直接關(guān)閉連接
public void close()throws SQLException{
connPool.releaseConnection(this.dbconn);
}
}
動態(tài)代理:
public class ConnectionHandler implements InvocationHandler{
Connection dbconn;
ConnectionPool pool;
public ConnectionHandler(ConnectionPool connPool){
this.pool = connPool;
}
//將動態(tài)代理綁定到指定Connection
public Connection bind(Connection conn){
this.dbconn = conn;
Connection proxyConn = (Connection)Proxy.newProxyInstance(conn.getClass().getClassLoader(),conn.getClass().getInterfaces(),this);
return proxyConn;
}
//方法調(diào)用攔截器
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
Object obj =null;
if("close".equals(method.getName())){
pool.releaseConnection(dbconn);
}else{
obj = method.invoke(dbconn,args);
}
return obj;
}
}
ConnectionHandler connHandler = new ConnectionHandler(this);
return connHandler.bind(conn);
可以看到,基于Dynamic Proxy模式的實現(xiàn)相對Decorator更加簡潔明了。Connection dbconn;
ConnectionPool pool;
public ConnectionHandler(ConnectionPool connPool){
this.pool = connPool;
}
//將動態(tài)代理綁定到指定Connection
public Connection bind(Connection conn){
this.dbconn = conn;
Connection proxyConn = (Connection)Proxy.newProxyInstance(conn.getClass().getClassLoader(),conn.getClass().getInterfaces(),this);
return proxyConn;
}
//方法調(diào)用攔截器
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
Object obj =null;
if("close".equals(method.getName())){
pool.releaseConnection(dbconn);
}else{
obj = method.invoke(dbconn,args);
}
return obj;
}
}
ConnectionHandler connHandler = new ConnectionHandler(this);
return connHandler.bind(conn);
無論是怎樣的應(yīng)用系統(tǒng),都無法脫離對資源的管理和使用。而對于持久層而言,資源的合理管理和調(diào)度則顯得尤為重要。
資源管理機制的設(shè)計對于系統(tǒng)整體表現(xiàn)往往可以產(chǎn)生關(guān)鍵性影響。同時,除去性能之外,良好的資源管理機制還能為系統(tǒng)的伸縮性、可維護性帶來相當(dāng)?shù)奶嵘?br /> Connection Pool:數(shù)據(jù)庫連接池技術(shù)帶來的優(yōu)勢
1、資源重用
由于數(shù)據(jù)庫連接得以重用,避免了頻繁創(chuàng)建、釋放連接引起的大量性能開銷。在減少系統(tǒng)消耗的基礎(chǔ)上,另一方面也增進了系統(tǒng)運行環(huán)境的平穩(wěn)性。
2、更快的系統(tǒng)響應(yīng)速度
數(shù)據(jù)庫連接池在初始化過程中,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫連接池置于池中備用。此時連接的初始化工作均已完成。對于業(yè)務(wù)請求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時間開銷,從而縮減了系統(tǒng)整體響應(yīng)時間。
3、新的資源分配手段
對于多應(yīng)用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應(yīng)用層通過數(shù)據(jù)庫連接池的配置,實現(xiàn)某一應(yīng)用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應(yīng)用獨占所有數(shù)據(jù)庫資源
4、統(tǒng)一的連接管理,避免數(shù)據(jù)庫連接泄露
在較為完備的數(shù)據(jù)庫連接池實現(xiàn)中,可根據(jù)預(yù)先的連接占用超時設(shè)定,強制收回被占用連接。從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄露。
public class DBConnectionPool implements ConnectionPool{
private statci Vector pool;
private final int POOL_MAX_SIZE = 20;
//獲取數(shù)據(jù)庫連接,如果當(dāng)前池中有可用連接,則將池中最后一個返回,如果沒有,則新建一個返回
public synchronized Connection getConnection()throws DBException{
if(pool==null){
pool = new Vector();
}
Connection conn;
if(pool.isEmpty()){
conn = createConnection();
}else{
int last_idx = pool.size()-1;
conn = (Connection)pool.get(last_idx);
pool.remove(pool.get(last_idx));
}
return conn;
}
//將使用完畢的數(shù)據(jù)庫連接放回備用池中
public synchronized void releaseConnection(Connection conn){
if(pool.size()>POOL_MAX_SIZE){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}else{
pool.add(conn);
}
}
//讀取數(shù)據(jù)庫配置信息,從數(shù)據(jù)庫連接池中獲得數(shù)據(jù)庫連接
private static Connection createConnection()throws DBException{
Connection conn;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:oracle","personal","personal");
return conn;
}cacth(ClassNotFoundException e){
throw new DBException("ClassNotFoundException when loading JDBC Driver");
}
}
}
private statci Vector pool;
private final int POOL_MAX_SIZE = 20;
//獲取數(shù)據(jù)庫連接,如果當(dāng)前池中有可用連接,則將池中最后一個返回,如果沒有,則新建一個返回
public synchronized Connection getConnection()throws DBException{
if(pool==null){
pool = new Vector();
}
Connection conn;
if(pool.isEmpty()){
conn = createConnection();
}else{
int last_idx = pool.size()-1;
conn = (Connection)pool.get(last_idx);
pool.remove(pool.get(last_idx));
}
return conn;
}
//將使用完畢的數(shù)據(jù)庫連接放回備用池中
public synchronized void releaseConnection(Connection conn){
if(pool.size()>POOL_MAX_SIZE){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}else{
pool.add(conn);
}
}
//讀取數(shù)據(jù)庫配置信息,從數(shù)據(jù)庫連接池中獲得數(shù)據(jù)庫連接
private static Connection createConnection()throws DBException{
Connection conn;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:oracle","personal","personal");
return conn;
}cacth(ClassNotFoundException e){
throw new DBException("ClassNotFoundException when loading JDBC Driver");
}
}
}
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 1 | 2 | 3 | |||
4 | 5 | 6 | 7 | 8 | 9 | 10 | |||
11 | 12 | 13 | 14 | 15 | 16 | 17 | |||
18 | 19 | 20 | 21 | 22 | 23 | 24 | |||
25 | 26 | 27 | 28 | 29 | 30 | 31 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 |
常用鏈接
留言簿(1)
隨筆分類
- EJB學(xué)習(xí)筆記(13)
- HIBERNATE(25)
- J2SE(1)
- JAVASCRIPT
- SOA
- SPRING(16)
- WEBWORK
- 人生隨筆(7)
- 開發(fā)實踐
- 設(shè)計思想(4)
- 財經(jīng)新聞
隨筆檔案
關(guān)注blogs
- Anders小明的Blog
- DWR學(xué)習(xí)手冊
- IBM解決方案
- j2ee api
- JavaEye Java
- java技術(shù)賽迪網(wǎng)
- jdk詳解
- J道論壇
- mldn解惑
- robbin的自言自語
- SpringFramework中文論壇
- validation詳細解釋
- 一只小螞蟻
- 中國it實驗室
- 啊密果
- 當(dāng)當(dāng)網(wǎng)
- 林信良學(xué)習(xí)筆記
- 灰狐動力
- 鼠標(biāo)的咖啡屋
搜索
最新評論

- 1.?re: 心中的那個她[未登錄]
- 如果心情能那么容易放開就好了,碰到她是我的緣分,但是她的緣分不知道在哪里。
- --王永慶
- 2.?re: 心中的那個她[未登錄]
- 兄弟,喜歡就大膽去追好了,就是因為喜歡才會有不愉快,如果想一輩子沒有這些煩惱,找一個可有可無的人就好了。這種事講的是緣分吧。別人對你好不好其實不太重要。放開心情就好了。
- --萍水相逢
- 3.?re: 心中的那個她
- 只能同甘不能共苦,就他媽算了吧,程序員也是人啊!我現(xiàn)在也很討厭女的不理解人情。
- --咖啡妝
- 4.?re: 難以割舍的那份情感
- 評論內(nèi)容較長,點擊標(biāo)題查看
- --王永慶
- 5.?re: 難以割舍的那份情感
- 評論內(nèi)容較長,點擊標(biāo)題查看
- --隔葉黃鶯