Java知識整理(下)

數據庫

NOSQL

CAP理論

在理論計算機科學中,CAP定理(CAP theorem)指出對於一個分佈式計算系統來講,不可能同時知足如下三點:前端

  • 一致性(Consistency):同一個數據在集羣中的全部節點,同一時刻是否都是一樣的值。
  • 可用性(Availability):集羣中一部分節點故障後,集羣總體是否還能處理客戶端的更新請求。
  • 分區容忍性(Partition tolerance):是否容許數據的分區,分區的意思是指是否容許集羣中的節點之間沒法通訊。

但實際上用戶關心的是,只要寫入數據成功了,那我下次讀取該數據時,老是能讀取到最新寫入的數據。因此,只要咱們的數據庫作到了這一點,那數據庫裏的數據對於用戶而言,就是具備一致性的。 NRW算法java

假設總共有五個節點(N),咱們只要保證寫入數據的節點數(W)+ 讀取數據的節點數(R)大於總節點數便可。即保證W+R>N,那就能保證對客戶端而言,老是能讀取到它最新寫入的數據。好比,總節點數爲5,寫入節點數爲3,讀取節點數爲3,那咱們就能保證客戶端老是能讀取到它最新寫入的數據。有了這樣的數據公式的做爲理論保證。咱們就能夠根據狀況靈活選擇W,R了。因爲咱們不須要保證5臺機器所有都寫入成功,只須要保證3臺寫入成功便可。這就意味着,咱們容許5臺機器中的2臺出現問題,也就是提升了系統的可用性。這樣的設計,雖然集羣節點之間,也許有些節點的數據不是最新的,也就是沒有作到CAP中的C,但對用戶來講,數據老是一致的。web

有了NRW算法,咱們就能作到,在知足AP的前提下,咱們徹底還能夠作到對用戶而言的數據一致性,因此大多數NOSQL數據庫選擇了A(可用性)與P(分區可容忍性)。算法

MongoDB

MongoDB 是一個可擴展的高性能,開源,模式自由,面向文檔的分佈式文件存儲數據庫。模式自由,高性能,易擴展,靈活查詢,弱事物。spring

  • 面向集合的存儲:適合存儲對象及JSON形式的數據。
  • 動態查詢:Mongo 支持豐富的查詢方式,查詢指令使用 JSON 形式的標記,可輕易查詢文檔中內嵌的對象及數組。
  • 完整的索引支持:包括文檔內嵌對象及數組。Mongo 的查詢優化器會分析查詢表達式,並生成一個高效的查詢計劃。
  • 查詢監視:Mongo包含一個監控工具用於分析數據庫操做性能。
  • 複製及自動故障轉移:Mongo 數據庫支持服務器之間的數據複製,支持主-從模式及服務器之間的相互複製。複製的主要目的是提供冗餘及自動故障轉移。
  • 高效的傳統存儲方式:支持二進制數據及大型對象(如:照片或圖片)。
  • 自動分片以支持雲級別的伸縮性:自動分片功能支持水平的數據庫集羣,可動態添加額外的機器。

適用場景sql

  • 實時數據:Mongo 很是適合實時的插入,更新與查詢,並具有網站實時數據存儲所需的複製及高度伸縮性。
  • 緩存:因爲性能很高,Mongo 也適合做爲信息基礎設施的緩存層。在系統重啓以後,由 Mongo 搭建的持久化緩存能夠避免下層的數據源過載。
  • 日誌數據:適合存儲大量的非結構化的低價值數據。
  • 高伸縮性:Mongo很是適合由數十或數百臺服務器組成的數據庫
  • 結構鬆散:用於對象及JSON數據的存儲:Mongo的BSON數據格式很是適合文檔格式化的存儲及查詢
  • 大型文件存儲:分佈式的文件存儲
  • 地理位置:基於地理位置,物理空間的搜索

不適合的場景數據庫

  • 高度事務性的系統:例如銀行或會計系統。傳統的關係型數據庫目前仍是更適用於須要大量原子性複製事物的應用程序。
  • 傳統的商業智能應用:針對特定問題的 BI 數據庫會對產生高度優化的查詢方式。對於此類應用,數據倉庫可能時更適合的選擇(如Hadoop套件中的Hive)。
  • 須要SQL的問題。

MongoDB高可用集羣

  1. Master-Slave主從結構 enter description here 主從架構通常用於備份或者作讀寫分離。通常有一主一從設計和一主多從設計。由兩種角色構成: (1)主(Master) 可讀可寫,當數據有修改的時候,會將oplog同步到全部鏈接的salve上去。 (2)從(Slave) 只讀不可寫,自動從Master同步數據。 特別的,對於Mongodb來講,並不推薦使用Master-Slave架構,由於Master-Slave其中Master宕機後不能自動恢復,推薦使用Replica Set。編程

  2. Relica Set副本集 enter description here Mongodb的Replica Set即副本集方式主要有兩個目的,一個是數據冗餘作故障恢復使用,當發生硬件故障或者其它緣由形成的宕機時,可使用副本進行恢復。另外一個是作讀寫分離,讀的請求分流到副本上,減輕主(Primary)的讀壓力。 (1)主節點(Primary) 接收全部的寫請求,而後把修改同步到全部Secondary。一個Replica Set只能有一個Primary節點,當Primary掛掉後,其餘Secondary或者Arbiter節點會從新選舉出來一個主節點。默認讀請求也是發到Primary節點處理的,須要轉發到Secondary須要客戶端修改一下鏈接配置。 (2)副本節點(Secondary) 與主節點保持一樣的數據集。當主節點掛掉的時候,參與選主。 (3)仲裁者(Arbiter) 不保有數據,不參與選主,只進行選主投票。使用Arbiter能夠減輕數據存儲的硬件需求,Arbiter跑起來幾乎沒什麼大的硬件資源需求數組

  3. Sharding分片技術 enter description here MongoDB分片技術相似MySQL的水平切分和垂直切分,數據庫主要由兩種方式作Sharding:垂直擴展和橫向切分。垂直擴展的方式就是進行集羣擴展,添加更多的CPU,內存,磁盤空間等。橫向切分則是經過數據分片的方式,經過集羣統一提供服務: A.數據分片(Shards) 用來保存數據,保證數據的高可用性和一致性。能夠是一個單獨的mongod實例,也能夠是一個副本集。在生產環境下Shard通常是一個Replica Set,以防止該數據片的單點故障。全部Shard中有一個PrimaryShard,裏面包含未進行劃分的數據集合: B.查詢路由(Query Routers) 路由就是mongos的實例,客戶端直接鏈接mongos,由mongos把讀寫請求路由到指定的Shard上去。一個Sharding集羣,能夠有一個mongos,也能夠有多mongos以減輕客戶端請求的壓力。 C.配置服務器(Config servers) 保存集羣的元數據(metadata),包含各個Shard的路由規則。瀏覽器

  4. 總結 自動分片是一個很是理想的選擇,但自動分片在真實的應用場景中仍是會有不少的坑,除非咱們在這條路上不斷踩坑並不斷填坑,擁有足夠的實力、足夠的經驗,掌控好其每一個細節,那咱們不妨能夠選擇自動分片。但不少公司仍是避開這條路,選擇手動分片方式,其最大緣由就是手動分片可控能力強。

數據安全機制

對於數據安全,MongoDB2.6+ 就有了很是完善的機制,並且還很靈活。從不返回結果、確認主服務器寫內存、確認主服務器寫journal日誌、確認同步到大多數服務器到強制寫入磁盤,MongoDB數據安全級別逐漸提升。開發者能夠根據不一樣的應用場景選擇適合的安全級別,在數據安全和寫操做的性能之間找到平衡。 根據以往踩過的坑和同行經驗,總結出如下幾點建議。

最低WriterConcern.SAFE:若是沒有特殊要求,最低級別也要使用WriterConcern.SAFE,即w=1。對於不重要的數據,好比log日誌,可使用WriterConcern.NONE或者WriterConcern.NORMAL,即w=-1或者w=0,省去等待網絡的時間。

集羣WriterConcern.MAJORITY:通常來講,在集羣中使用WriterConcern.MAJORITY設置。在一個集羣是健壯的部署的狀況下(足夠網絡帶寬,機器沒有滿負荷),這個能夠知足絕大部分數據安全的要求。由於MongoDB的複製在正常狀況下是毫秒級別的,每每在Journal刷盤以前已經複製到從節點了。若是你追求完美,那麼能夠再進一步使用 {w: 「majority」,j:1} 。

批量操做,一次getLastError:對大量的不連續的數據寫入,若是每次寫入都調用getLastError會下降性能,由於等待網絡的時間太長,這種狀況下,能夠每過N次調用一下getLastError。可是在Shard結構上,這種方式不必定確保以前的寫入是成功的。對連續的批量寫入(batchs of write),要在批量寫入結束的時候調用getlastError,這不只能確保最後一次寫入正確,並且也能確保全部的寫入都能到達服務器。若是連續寫入上萬條記錄而不調用getlastError,那麼不能確保在同一個TCP socket裏全部的寫入都成功。這在併發的狀況下可能就會有問題。避免這個併發問題,能夠參考如何在一個連接(請求)裏完成批量操做,MongoDB Java Driver併發。 保證安全:對數據安全要求很是高的的配置:j=true,w="majority",db.runCommand({getlasterror:1,j:true,w:'majority',wtimeout:10000}) 靈活設置:大多數語言的驅動程序均可以在MongoOption中設置,MongoOption中的這些設置是全局的,對於單獨的一個鏈接或一次操做,還能夠分別設置。

Oracle

特性

功能豐富、穩定性、安全性、易管理、高性能、復瑣事務、分佈式、跨平臺,還有商業支持 缺點是收費高、不開源。

索引

Oracle中常見的索引分類有B樹索引和位圖索引。

  1. B樹索引(默認索引,保存講過排序過的索引列和對應的rowid值) enter description here oracle中最經常使用的索引;B樹索引就是一顆二叉樹;葉子節點(雙向鏈表)包含索引列和指向表中每一個匹配行的ROWID值 全部葉子節點具備相同的深度,於是無論查詢條件怎樣,查詢速度基本相同 可以適應精確查詢、模糊查詢和比較查詢 分類: UNIQUE,NON-UNIQUE(默認),REVERSE KEY(數據列中的數據是反向存儲的) 建立例子 craete index index_sno on student('sno'); 適合使用場景:列基數(列不重複值的個數)大時適合使用B數索引

  2. 位圖索引 建立位圖索引時,oracle會掃描整張表,併爲索引列的每一個取值創建一個位圖(位圖中,對錶中每一行使用一位(bit,0或者1)來標識該行是否包含該位圖的索引列的取值,若是爲1,表示對應的rowid所在的記錄包含該位圖索引列值),最後經過位圖索引中的映射函數完成位到行的ROWID的轉換 建立例子 create bitmap index index_sno on student(sno); 適合場景:對於基數小的列適合簡歷位圖索引(例如性別等)

  3. 單列索引和複合索引(基於多個列建立) 注意:即若是索引創建在多個列上,只有它的第一個列被where子句引用時,優化器纔會使用該索引,即至少要包含組合索引的第一列

  4. 函數索引 說明: 當常常要訪問一些函數或者表達式時,能夠將其存儲在索引中,這樣下次訪問時,該值已經計算出來了,能夠加快查詢速度。 函數索引既可使用B數索引,也可使用位圖索引;當函數結果不肯定時採用B樹索引,結果是固定的某幾個值時使用位圖索引。 函數索引中能夠水泥用len、trim、substr、upper(每行返回獨立結果),不能使用如sum、max、min、avg等。

原則

  1. 若是有兩個或者以上的索引,其中有一個惟一性索引,而其餘是非惟一,這種狀況下oracle將使用惟一性索引而徹底忽略非惟一性索引
  2. 至少要包含組合索引的第一列(即若是索引創建在多個列上,只有它的第一個列被where子句引用時,優化器纔會使用該索引)
  3. 小表不要簡歷索引,值不夠分散適合使用位圖索引
  4. 對於基數大的列適合創建B樹索引,對於基數小的列適合簡歷位圖索引
  5. 列中有不少空值,但常常查詢該列上非空記錄時應該創建索引
  6. 常常進行鏈接查詢的列應該建立索引
  7. 使用create index時要將最常查詢的列放在最前面
  8. LONG(可變長字符串數據,最長2G)和LONG RAW(可變長二進制數據,最長2G)列不能建立索引 9.限制表中索引的數量(建立索引耗費時間,而且隨數據量的增大而增大;索引會佔用物理空間;當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,下降了數據的維護速度)

設立封鎖機制主要是爲了對併發操做進行控制,對干擾進行封鎖,保證數據的一致性和準確性。Oracle數據庫封鎖方式有三種:共享鎖,獨佔鎖,共享更新鎖 內部級封鎖 內部級封鎖是用於保護ORACLE內部結構,由系統內部實現,用戶不能訪問,所以咱們沒必要對此作過多的瞭解。 DDL級封鎖(字典/語法分析封鎖) DDL級封鎖也是由ORACLE RDBMS來控制,它用於保護數據字典和數據定義改變時的一致性和完整性。它是系統在對SQL定義語句做語法分析時自動地加鎖,無需用戶幹予。字典/語法分析封鎖共分三類: (1)、字典操做鎖:用於對字典操做時,鎖住數據字典,此封鎖是獨佔的,從而保護任何一個時刻僅能對一個字典操做。 (2)、字典定義鎖:用於防止在進行字典操做時又進行語法分析,這樣能夠避免在查詢字典的同時改動某個表的結構。 (3)、表定義鎖:用於 一個SQL語句正當訪問某個表時,防止字典中與該表有關的項目被修改。 DML級封鎖 DML級封鎖用於控制併發事務中的數據操縱,保證數據的一致性和完整性,其封鎖對象能夠是表或行。 對用戶的數據操縱,Oracle能夠自動爲操縱的數據進行封鎖,但若是有操縱受權,則爲知足併發操縱的須要另外實施封鎖。DML封鎖可由一個用戶進程以顯式的方式加鎖,也可經過某些SQL語句隱含方式實現。 DML鎖有以下三種封鎖方式: (1)、共享封鎖方式(SHARE) (2)、獨佔封鎖方式(EXCLUSIVE) (3)、共享更新封鎖(SHARE UPDATE)

  1. 共享方式的表封鎖 共享方式的表封鎖是對錶中的全部數據進行封鎖防止其它用戶對已封鎖的表進行更更新。共享該表的全部用戶只能查詢表中的數據,但不能更新。共享方式的表封鎖只能由用戶用SQL語句來設置: LOCK TABLE <表名>[,<表名>]... IN SHARE MODE [NOWAIT] 執行該語句,對一個或多個表施加共享方式的表封鎖。當指定了選擇項NOWAIT,若該封鎖暫時不能施加成功,則返回並由用戶決定是進行等待,仍是先去執行別的語句。 持有共享鎖的事務,在出現以下之一的條件時,便釋放其共享鎖: A、執行COMMIT或ROLLBACK語句。 B、退出數據庫(LOG OFF)。 C、程序中止運行。 共享方式表封鎖經常使用於一致性查詢過程,即在查詢數據期間表中的數據不發生改變。
  2. 獨佔方式表封鎖 獨佔方式表封鎖是用於封鎖表中的全部數據,擁有該獨佔方式表封鎖的用戶,便可以查詢該表,又能夠更新該表,其它的用戶不能再對該表施加任何封鎖(包括共享、獨佔或共享更新封鎖),但能夠查詢該表。 獨佔方式的表封鎖可經過以下的SQL語句來顯示地得到: LOCK TABLE <表名>[,<表名>].... IN EXCLUSIVE MODE [NOWAIT] 獨佔方式的表封鎖也能夠在用戶執行DML語句INSERT、UPDATE、DELETE時隱含得到。擁有獨佔方式表封鎖的事務。 獨佔方式封鎖一般用於更新數據,當某個更新事務涉及多個表時,可減小發生死鎖。
  3. 共享更新封鎖方式 共享更新封鎖是對一個表的一行或多行進行封鎖,於是也稱做行級封鎖。表級封鎖雖然保證了數據的一致性,但卻減弱了操做數據的並行性。行級封鎖確保在用戶取得被更新的行到該行進行更新這段時間內不被其它用戶所修改。於是行級鎖便可保證數據的一致性又能提升數據操做的迸發性。 可經過以下的兩種方式來得到行級封鎖: (1)、執行以下的SQL封鎖語句,以顯示的方式得到: LOCK TABLE <表名>[,<表名>].... IN SHARE UPDATE MODE [NOWAIT] (2)、用以下的SELECT ...FOR UPDATE語句得到: SELECT <列名>[,<列名>]... FROM <表名> WHERE <條件> FOR UPDATE OF <列名>[,<列名>].....[NOWAIT] 一旦用戶對某個行施加了行級封鎖,則該用戶能夠查詢也能夠更新被封鎖的數據行,其它用戶只能查詢但不能更新被封鎖的數據行。真正對錶進行更新時,是以獨佔方式封鎖表,一直到提交或復原該事務爲止。行鎖永遠是獨佔方式鎖。

事務隔離

事務隔離級別:一個事務對數據庫的修改與並行的另外一個事務的隔離程度。兩個併發事務同時訪問數據庫表相同的行時,可能存在如下三個問題:

一、幻想讀:事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,剛好知足T1的where條件。而後T1使用相同的條件再次查詢,結果集中能夠看到T2插入的記錄,這條新紀錄就是幻想。 二、不可重複讀取:事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,而後T1再次查詢,發現與第一次讀取的記錄不一樣,這稱爲不可重複讀。 三、髒讀:事務T1更新了一行記錄,還未提交所作的修改,這個T2讀取了更新後的數據,而後T1執行回滾操做,取消剛纔的修改,因此T2所讀取的行就無效,也就是髒數據。

爲了處理這些問題,SQL標準定義瞭如下幾種事務隔離級別

READ UNCOMMITTED 幻想讀、不可重複讀和髒讀都容許。 READ COMMITTED 容許幻想讀、不可重複讀,不容許髒讀 REPEATABLE READ 容許幻想讀,不容許不可重複讀和髒讀 SERIALIZABLE 幻想讀、不可重複讀和髒讀都不容許

Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。

  • READ COMMITTED 這是ORACLE缺省的事務隔離級別。 事務中的每一條語句都聽從語句級的讀一致性。 保證不會髒讀;但可能出現非重複讀和幻像。
  • SERIALIZABLE 簡單地說,serializable就是使事務看起來象是一個接着一個地順序地執行。僅僅能看見在本事務開始前由其它事務提交的更改和在本事務中所作的更改(也就是說其它事務在本事務開始後所作的修改,即便提交了,本事務也看不到)保證不會出現非重複讀和幻像。 Serializable隔離級別提供了read-only事務所提供的讀一致性(事務級的讀一致性),同時又容許DML操做。
  • Read Only 聽從事務級的讀一致性,僅僅能看見在本事務開始前由其它事務提交的更改。不容許在本事務中進行DML操做。 read only是serializable的子集。它們都避免了非重複讀和幻像。Read only和Serializable相似,惟一不一樣的是它不容許在本事務中進行DML操做。

UNDO/REDO

Undo日誌記錄某數據被修改前的值,能夠用來在事務失敗時進行rollback;Redo日誌記錄某數據塊被修改後的值,能夠用來恢復未寫入data file的已成功事務更新的數據。

例如某一事務的事務序號爲T1,其對數據X進行修改,設X的原值是5,修改後的值爲15,那麼Undo日誌爲<T1, X, 5>,Redo日誌爲<T1, X, 15>。

  1. UNDO
  1. UNDO表空間用於存放UNDO數據。當執行DML操做時,Oracle會將這些操做的舊數據寫入UNDO段。管理UNDO數據不只可使用回滾段,還可使用UNDO表空間
  2. UNDO數據的做用:當用戶執行DML操做修改數據時,UNDO數據被存放在UNDO段,而新數據則被存放到數據段中,若是事務操做存在問題,就須要回退事務,以取消事物變化。 例如:執行完UPDATE emp SET sal=1000 WHERE empno=7788後,發現應該修改僱員7963的工資,而不是7788.此時應該執行ROLLBACK語句。
  3. 讀一致性 用戶檢索數據時,ORACLE老是使用戶只能看到被提交過的數據,這是由Oracle自動提供的。當用戶修改數據,可是沒有提交時,另一個用戶使用select語句查找該值時,該值就是從undo表空間中取得的。
  4. 事務恢復 事務恢復是例程恢復的一部分,它是由Oracle Server自動完成的。若是在數據庫運行過程當中出線例程失敗,那麼當啓動Oracle Server時,後臺進程SMON會自動執行例程恢復。執行例程恢復時,Oracle會重作全部未應用的記錄。而後打開數據庫,回退未提交事務。 UNDO數據是數據修改前的備份,主要是保證用戶的讀一致性和事務回滾 在事務修改數據時產生,至少保存到事務結束
  1. REDO REDO記錄transaction logs,分爲online和archived。以恢復爲目的。 好比,機器停電,那麼在重起以後須要online redo logs去恢復系統到失敗點。 好比,磁盤壞了,須要用archived redo logs和online redo logs區恢復數據。 好比,truncate一個表或其餘的操做,想恢復到以前的狀態,一樣也須要。 redo日誌應首先持久化在磁盤上,而後事務的操做結果才寫入db buffer。

若是此時恰好系統故障,好比斷電,在系統重啓後,會讀取之前的磁盤數據,而後查看redo日誌,將那些已經寫入redo日誌,但沒有更新磁盤的內容【重作】,這樣就恢復到了系統故障前的那個點上。 因此,redo日誌是很關鍵的東西。若是其丟失或者損壞了,則你極可能丟失了部分數據(不是必定)。

總結: 操做順序redo--> undo-->datafile 當insert一條記錄時, 表跟undo的信息都會放進 redo 中, 在commit 或以前, redo 的信息會放進硬盤上. 故障時, redo 即可恢復那些已經commit 了的數據. redo->每次操做都先記錄到redo日誌中,當出現實例故障(像斷電),致使數據未能更新到數據文件,則數據庫重啓時須redo,從新把數據更新到數據文件

1.undo記錄數據修改以前的操做,redo記錄磁盤數據將要進行的操做. 2.undo用於數據的回滾操做,和實現一致性讀,redo用於前滾數據庫操做 3.undo存儲在回滾段裏,redo存儲在重作日誌文件裏 4.undo用於在多用戶併發的系統裏保證一致性讀,redo用於防止數據丟失

Oracle多版本

Oracle還實現了一種多版本控制(multi-versioning)體系結構,這種體系結構提供了一種受控但高度併發的數據訪問。多版本控制是指oracle能同時物化多個版本的數據,這也是oracle提供數據讀一致視圖(即相對於某個時間點有一致的結果)的機制。"讀一致性"反映了一個事實:Oracle中的查詢會從某個一致的時間點開始返回,查詢使用的每一個塊都從同一個時間點開始,即便它在你執行查詢時被修改或鎖定。當你修改數據的時候,Oracle將會在兩個不一樣的位置建立記錄,一個是重作日誌,另外一個是回滾段。某一行的數據被修改,該行會增長一個行級鎖,當讀取這行數據時發現有行級鎖則讀取回滾段,從而保證讀一致。多版本控制有一個至關使人驚喜的連帶效果,即數據的讀取器絕對不會被數據的寫入器所阻塞。它不會與其餘會話發生死鎖,並且不可能獲得數據庫中根本不存在的答案。

表分區

當表中的數據量不斷增大,查詢數據的速度就會變慢,應用程序的性能就會降低,這時就應該考慮對錶進行分區。表進行分區後,邏輯上表仍然是一張完整的表,只是將表中的數據在物理上存放到多個表空間(物理文件上)。分區可使某些查詢以及維護操做的性能大大提升。 何時使用分區表:

表的大小超過2GB。 表中包含歷史數據,新的數據被增長都新的分區中。

表分區有如下優勢:

  1. 改善查詢性能:對分區對象的查詢能夠僅搜索本身關心的分區,提升檢索速度。
  2. 加強可用性:若是表的某個分區出現故障,表在其餘分區的數據仍然可用;
  3. 維護方便:若是表的某個分區出現故障,須要修復數據,只修復該分區便可;
  4. 均衡I/O:能夠把不一樣的分區映射到磁盤以平衡I/O,改善整個系統性能。 範圍分區表、列表分區表、哈希分區表、組合分區表。 索引 對於分區表的不分區索引 對於分區表的不分區索引

enter description here 對於分區表的分區索引

enter description here LOCAL索引結構

輕量級J2EE框架

Spring

spring原理

IoC 容器:最主要是完成了完成對象的建立和對象之間依賴關係的管理注入。Spring就是在運行時,根據xml 配置文件,利用java反射來動態的建立對象。讓對象與對象(模塊與模塊)之間的關係沒有經過代碼硬關聯,都是經過配置類說明管理的。Spring是一個容器,凡是在容器裏的對象纔會有Spring所提供的這些服務和功能。

當Spring IoC容器完成了Bean定義資源的定位、載入和解析註冊之後,IoC容器中已經管理類Bean定義的相關數據,可是此時IoC容器尚未對所管理的Bean進行依賴注入,依賴注入在如下兩種狀況發生: (1)用戶第一次經過getBean方法向IoC容索要Bean時,IoC容器觸發依賴注入。 (2)當用戶在Bean定義資源中爲<Bean>元素配置了lazy-init屬性,即讓容器在解析註冊Bean定義時進行預實例化,觸發依賴注入。

AOP:就是面向切面編程,經過動態代理的方式能夠爲某一類對象 進行監督和控制(也就是 在調用這類對象的具體方法的先後去調用你指定的 模塊)從而達到對一個模塊擴充的功能。 動態代理模式圖解 enter description here

代理模式的代理角色最起碼要考慮三個階段:

  1. 切入點(Point Cut)對哪些方法做代理實現
  2. 攔截行爲(Advice)對應的的類方法的執行哪些時期作加強處理(方法調用前、調用異常、方法返回)
  3. 具體加強處理的內容

代理實現的方式 默認狀況下,接口使用JDK動態代理,對象使用CGLIB代理。如何強制使用CGLIB實現AOP?

  • 添加CGLIB庫,SPRING_HOME/cglib/*.jar
  • 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

spring的三種注入方式是 setter、interface、constructor

Spring事務管理

事務有四個特性:ACID

原子性(Atomicity):事務是一個原子操做,由一系列動做組成。事務的原子性確保動做要麼所有完成,要麼徹底不起做用。 一致性(Consistency):一旦事務完成(無論成功仍是失敗),系統必須確保它所建模的業務處於一致的狀態,而不會是部分完成部分失敗。在現實中的數據不該該被破壞。 隔離性(Isolation):可能有許多事務會同時處理相同的數據,所以每一個事務都應該與其餘事務隔離開來,防止數據損壞。 持久性(Durability):一旦事務完成,不管發生什麼系統錯誤,它的結果都不該該受到影響,這樣就能從任何系統崩潰中恢復過來。一般狀況下,事務的結果被寫到持久化存儲器中。

Spring並不直接管理事務,而是提供了多種事務管理器,他們將事務管理的職責委託給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。 enter description here enter description here

事務的傳播行爲 事務的第一個方面是傳播行爲(propagation behavior)。當事務方法被另外一個事務方法調用時,必須指定事務應該如何傳播。 |傳播行爲 |含義| |:------|:-------| |PROPAGATION_REQUIRED| 表示當前方法必須運行在事務中。若是當前事務存在,方法將會在該事務中運行。不然,會啓動一個新的事務| |PROPAGATION_SUPPORTS| 表示當前方法不須要事務上下文,可是若是存在當前事務的話,那麼該方法會在這個事務中運行| |PROPAGATION_MANDATORY| 表示該方法必須在事務中運行,若是當前事務不存在,則會拋出一個異常| |PROPAGATION_REQUIRED_NEW| 表示當前方法必須運行在它本身的事務中。一個新的事務將被啓動。若是存在當前事務,在該方法執行期間,當前事務會被掛起。若是使用JTATransactionManager的話,則須要訪問TransactionManager| |PROPAGATION_NOT_SUPPORTED |表示該方法不該該運行在事務中。若是存在當前事務,在該方法運行期間,當前事務將被掛起。若是使用JTATransactionManager的話,則須要訪問TransactionManager| |PROPAGATION_NEVER| 表示當前方法不該該運行在事務上下文中。若是當前正有一個事務在運行,則會拋出異常| |PROPAGATION_NESTED| 表示若是當前已經存在一個事務,那麼該方法將會在嵌套事務中運行。嵌套的事務能夠獨立於當前事務進行單獨地提交或回滾。若是當前事務不存在,那麼其行爲與PROPAGATION_REQUIRED同樣。注意各廠商對這種傳播行爲的支持是有所差別的。能夠參考資源管理器的文檔來確認它們是否支持嵌套事務|

Spring MVC

Spring web MVC框架提供了MVC(模型 - 視圖 - 控制器)架構和用於開發靈活和鬆散耦合的Web應用程序的組件。 MVC模式致使應用程序的不一樣方面(輸入邏輯,業務邏輯和UI邏輯)分離,同時提供這些元素之間的鬆散耦合。

  • 模型(Model)封裝了應用程序數據,一般它們將由POJO類組成。
  • 視圖(View)負責渲染模型數據,通常來講它生成客戶端瀏覽器能夠解釋HTML輸出。
  • 控制器(Controller)負責處理用戶請求並構建適當的模型,並將其傳遞給視圖進行渲染。

enter description here enter description here Spring MVC框架是一個基於請求驅動的Web框架,而且使用了前端控制器模式來進行設計,再根據請求映射規則分發給相應的頁面控制器(動做/處理器)進行處理。

(1) Http請求:客戶端請求提交到DispatcherServlet。 
(2) 尋找處理器:由DispatcherServlet控制器查詢一個或多個HandlerMapping,找處處理請求的Controller。 
(3) 調用處理器:DispatcherServlet將請求提交到Controller。 
(4)(5)調用業務處理和返回結果:Controller調用業務邏輯處理後,返回ModelAndView。 
(6)(7)處理視圖映射並返回模型: DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖。 
(8) Http響應:視圖負責將結果顯示到客戶端。
  1. DispatcherServlet接口: Spring提供的前端控制器,全部的請求都有通過它來統一分發。在DispatcherServlet將請求分發給Spring Controller以前,須要藉助於Spring提供的HandlerMapping定位到具體的Controller。
  2. HandlerMapping接口: 可以完成客戶請求到Controller映射。
  3. Controller接口: 須要爲併發用戶處理上述請求,所以實現Controller接口時,必須保證線程安全而且可重用。 Controller將處理用戶請求,這和Struts Action扮演的角色是一致的。一旦Controller處理完用戶請求,則返回ModelAndView對象給DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和視圖(View)。 從宏觀角度考慮,DispatcherServlet是整個Web應用的控制器;從微觀考慮,Controller是單個Http請求處理過程當中的控制器,而ModelAndView是Http請求過程當中返回的模型(Model)和視圖(View)。
  4. ViewResolver接口: Spring提供的視圖解析器(ViewResolver)在Web應用中查找View對象,從而將相應結果渲染給客戶。

MyBatis

MyBatis是目前很是流行的ORM框架,它的功能很強大,然而其實現卻比較簡單、優雅

框架設計

enter description here enter description here ####接口層 和數據庫交互有兩種方式: a.使用傳統的MyBatis提供的API;

這是傳統的傳遞Statement Id 和查詢參數給 SqlSession 對象,使用 SqlSession對象完成和數據庫的交互;MyBatis 提供了很是方便和簡單的API,供用戶實現對數據庫的增刪改查數據操做,以及對數據庫鏈接信息和MyBatis 自身配置信息的維護操做。 enter description here enter description here 首先建立一個和數據庫打交道的SqlSession對象,而後根據Statement Id 和參數來操做數據庫,這種方式當然很簡單和實用,可是它不符合面嚮對象語言的概念和麪向接口編程的編程習慣。

b. 使用Mapper接口

MyBatis 將配置文件中的每個<mapper> 節點抽象爲一個 Mapper 接口,而這個接口中聲明的方法和跟<mapper> 節點中的<select|update|delete|insert> 節點項對應,即<select|update|delete|insert> 節點的id值爲Mapper 接口中的方法名稱,parameterType 值表示Mapper 對應方法的入參類型,而resultMap 值則對應了Mapper 接口表示的返回值類型或者返回結果集的元素類型。 enter description here enter description here 根據MyBatis 的配置規範配置好後,經過SqlSession.getMapper(XXXMapper.class) 方法,MyBatis 會根據相應的接口聲明的方法信息,經過動態代理機制生成一個Mapper 實例,咱們使用Mapper 接口的某一個方法時,MyBatis 會根據這個方法的方法名和參數類型,肯定Statement Id,底層仍是經過SqlSession.select("statementId",parameterObject);或者SqlSession.update("statementId",parameterObject); 等等來實現對數據庫的操做,

數據處理層

數據處理層能夠說是MyBatis 的核心,從大的方面上講,它要完成三個功能:

  1. 參數映射

參數映射指的是對於Java 數據類型和jdbc數據類型之間的轉換:這裏有包括兩個過程:查詢階段,咱們要將java類型的數據,轉換成jdbc類型的數據,經過 preparedStatement.setXXX() 來設值;另外一個就是對resultset查詢結果集的jdbcType 數據轉換成java 數據類型。

  1. 動態SQL語句生成

動態語句生成能夠說是MyBatis框架很是優雅的一個設計,MyBatis 經過傳入的參數值,使用 Ognl 來動態地構造SQL語句,使得MyBatis 有很強的靈活性和擴展性。

  1. 封裝查詢結果集成List<E>

動態SQL語句生成以後,MyBatis 將執行SQL語句,並將可能返回的結果集轉換成List<E> 列表。MyBatis 在對結果集的處理中,支持結果集關係一對多和多對一的轉換,而且有兩種支持方式,一種爲嵌套查詢語句的查詢,還有一種是嵌套結果集的查詢。

框架支撐層

  1. 事務管理機制 MyBatis的事務管理分爲兩種形式: 1、使用JDBC的事務管理機制:即利用java.sql.Connection對象完成對事務的提交(commit())、回滾(rollback())、關閉(close())等 2、使用MANAGED的事務管理機制:這種機制MyBatis自身不會去實現事務管理,而是讓程序的容器如(JBOSS,Weblogic)來實現對事務的管理

  2. 鏈接池管理機制 enter description here 今後結果能夠清楚地看出,建立一個Connection對象,用了250 毫秒;而執行SQL的時間用了170毫秒。建立一個Connection對象用了250毫秒!這個時間對計算機來講能夠說是一個很是奢侈的! MyBatis將鏈接池中的PooledConnection分爲兩種狀態: 空閒狀態(idle)和活動狀態(active),這兩種狀態的PooledConnection對象分別被存儲到PoolState容器內的idleConnections和activeConnections兩個List集合中:

  3. 緩存機制 一級緩存的工做機制是會話級別的,一個SqlSession對象會使用一個Executor對象來完成會話操做,Executor對象會維護一個Cache緩存,以提升查詢性能。 二級緩存的工做機制的關鍵就是對這個Executor對象作文章。若是用戶配置了"cacheEnabled=true",那麼MyBatis在爲SqlSession對象建立Executor對象時,會對Executor對象加上一個裝飾者:CachingExecutor,這時SqlSession使用CachingExecutor對象來完成操做請求。CachingExecutor對於查詢請求,會先判斷該查詢請求在Application級別的二級緩存中是否有緩存結果,若是有查詢結果,則直接返回緩存結果;若是緩存中沒有,再交給真正的Executor對象來完成查詢操做,以後CachingExecutor會將真正Executor返回的查詢結果放置到緩存中,而後在返回給用戶。

  4. SQL語句的配置方式 傳統的MyBatis 配置SQL 語句方式就是使用XML文件進行配置的,可是這種方式不能很好地支持面向接口編程的理念,爲了支持面向接口的編程,MyBatis 引入了Mapper接口的概念,面向接口的引入,對使用註解來配置SQL 語句成爲可能,用戶只須要在接口上添加必要的註解便可,不用再去配置XML文件了,可是,目前的MyBatis 只是對註解配置SQL 語句提供了有限的支持,某些高級功能仍是要依賴XML配置文件配置SQL 語句。

相關文章
相關標籤/搜索