java學習筆記

1.相同對象的hashcode一定相同,但相同的hashcode不一定是相同的對象。
2.深複製和淺複製
淺複製:被複制對象的所有變量都含有與原來對象相同的值,而所有的對其他對象的引用任然指向原來的對象,淺複製僅僅考慮複製的對象,不復制它所引用的對象。
深複製:被複制對象的所有變量都含有與原來對象相同的值,除去那些引用其他對象的變量,那些引用其他對象的變量將指向被複制過的新對象,而不再是原有的那些被引用的對象,深複製把複製的對象所引用的對象都複製了一遍。
3.什麼是servlet?
servlet是用來處理客戶端請求併產生動態網頁內容的java類,servlet主要是用來處理 或者是存儲HTML表單提交的數據,產生動態內容,在無狀態的HTTP協議下管理狀態信息
4.說一下servlet的體系結構
所有的servlet都必須要實現的核心接口是 javax.servlect.Servlect,每一個Servlect都必須直接或間接的實現這個接口,或者是繼承javax.servlet.GenericServlet,Servlect使用多線程可以並行爲多個請求服務。
5.Servlect的生命週期
對每一個客戶端的請求,Servlect引擎載入Servlect,調用它的init方法,完成Servlect的初始化,然後Servlect對象通過爲每一個請求單獨調用service方法來處理所有隨後來自客戶端的請求,最後調用Servlect的destroy方法把servlect刪除掉。
6.doGet和doPost方法的區別
doGet:GET方法把名值對追加在請求的URL後面,因爲URL對字符數目有限制,進而限制了用客戶端請求的參數值的數目,並且請求中的參數值是可見的,因此,敏感信息不能使用這種方式傳遞。
doPost:POST方法通過把請求參數值放在請求體中來克服GET方法的限制,因此,可以發送參數的數目是沒有限制的,最後通過POST請求傳遞的敏感信息對外部客戶端是不可見的。
7.jdk和jre的區別
java運行時環境(jre)是將要執行java程序的java虛擬機,它同時也包含了執行applet需要的瀏覽器插件,java考法工具包(jdk)是完整的java軟件開發包,包含了jre,編譯器和其他工具(比如:javadoc,java調試器),可以讓開發者開發,編譯,執行java程序。
8.是否可以在static環境中訪問非static變量
static變量在java中是屬於類的,它在所有的實例中的值是一樣的。當類被java虛擬機載入的時候會對static變量進行初始化,如果你的代碼嘗試不用實例來訪問非static的變量,編譯器會報錯,因爲這些變量還沒有被創建出來,還沒有跟任何實例關聯上。
9.java中的方法覆蓋和方法重載是什麼意思
java中的方法重載發生在同一個類裏面兩個或是多個方法的方法名相同但是參數不同的情況。與此相對,方法覆蓋是說類重新定義了父類的方法。方法覆蓋必須有相同的方法名,參數列表和返回類型。覆蓋者可能不會限制他/她所覆蓋的方法的訪問。
10.java中,什麼是構造函數,什麼是構造函數重載,什麼是複製構造函數
當新對象被創建的時候,構造函數會被調用。每一個類都有構造函數,在程序員沒有給類提供構造函數的情況下,java編譯器會爲這個類創建一個默認的構造函數。
11.什麼是值傳遞和引用傳遞?
對象被值傳遞,意味着傳遞了對象的一個副本。因此,就算是改變了對象的副本,也不會影響原對象的值。對象被引用傳遞,意味着傳遞的並不是實際的對象,而是對象的引用。因此外部對引用對象的改變會反映到全部的對象上。
12.線程的幾種可用狀態
就緒
運行中
等待中
睡眠中
i/o阻塞
同步阻塞
死亡
13.同步方法和同步代碼塊的區別是什麼?
在java語言中,每一個對象有一把鎖。線程可以使用synchronized關鍵字來獲取對象上的鎖,synchronized關鍵字可應用在方法級別(粗粒度鎖)或者是代碼塊級別(細粒度鎖)。
14.在監視器(Monitor)內部,是如何做線程同步的?程序應該做哪種級別的同步?
監視器和鎖在java虛擬機中是一塊使用的。監視器監視一塊同步代碼塊,確保一次只有一個線程執行同步代碼塊。每一個監視器都和一個對象引用相關聯。線程在獲取鎖之前不允許使用同步代碼塊。
15.什麼是死鎖?
兩個進程都在等待對方執行完畢才能繼續往下執行的時候就發生了死鎖,結果就是兩個進程都陷入了無限等待中。
16.如何確保N個線程可以訪問N個資源同事又不導致死鎖?
使用多線程時,一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序,並強制線程按照指定的順序獲取鎖。因此,如果所有的線程都是以同樣的順序加鎖和釋放。就不會出現死鎖了。
17.java集合類框架的基本接口有哪些?
java集合類提供了一套設計良好的支持對一組對象進行操作的接口和類,java集合類裏面最基本的接口有:
Collection:代表一組對象,每一個對象都是它的子元素
Set:不包含重複元素的Collection
List:有順序的collection,並且可以包含重複元素
Map:可以把鍵映射到值的對象,鍵不能重複
18.爲什麼集合類沒有實現Cloneable和Serializable接口
集合類接口指定了一組叫做元素的對象。集合類接口的每一種具體實現類都可以選擇以它自己的方式對元素進行保存和排序。有的集合類允許重複的建,有些不允許。
19.什麼是迭代器(Iterator)?
Iterator接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。
克隆或者是序列化的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化。
20.Iterator和ListIterator的區別是什麼?
iterator可用來遍歷list和set集合,但是ListIterator只能用來遍歷list
Iterator對 集合只能是前向遍歷,ListIterator既可以前向也可以後向。
ListIterator實現了Iterator接口,幷包含其他的功能,比如:增加元素,替換元素,獲取前一個和後一個元素的索引
21.java中的HashMap的工作原理是什麼?
java中的HashMap是以鍵值對的形式存儲元素的,HashMap需要一個hash函數,它使用hashCode()
和equals()方法來想集合/從集合添加和檢索元素,當調用put()方法的時候,HashMap會計算key的hash的值,然後把鍵值對存儲在集合中合適的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量,負載因子和擴容極限
22.hashCode和equals方法的重要性提現在什麼地方?
java中的hashMap使用hashaCode和equals方法來確認鍵值對的索引,當根據鍵獲取值的時候也會用到這兩個方法。如果沒有正確是的實現這兩個方法,兩個不同的鍵可能會有相同的hash值,因此可能會被集合認爲是相等的。而且,這兩個方法也用來發現重複元素,所以這兩個方法的實現對hashmap的精確性和正確性是至關重要的。
23.hshMap和HashTable有什麼區別?
不同點:
HashMap允許鍵和值都是null,而HashTable不允許鍵或者是值是null
HashTable是同步的,而HashMap不是,因此,HashMap更適合於單線程環境,而hashTable更適合於多線程環境
HshMap提供了可供應用迭代的集合,因此,HashMap是快速失敗的,另一方面,HashTable提供了對鍵的列舉。
24.數組(Array)和列表(ArrayList)有什麼區別?什麼時候應該用Array而不是ArrayList?
Array可以包含基本類型和對象類型,ArrayList只能包含對象類型
Array大小是固定的,ArrayList的大小是動態變化的
ArrayList提供了更多的方法和特性,比如:addAll,removeAll,iterator等
對於基本類型數據,集合使用自動裝箱來減少編碼工作量,但是在處理固定大小的基本數據類型的時候,這中方式相對比較慢
25.ArrayList和LinkedList有什麼區別?
ArrayList是基於索引的數據接口,它的底層是數組,它可以以O(1)時間複雜度對元素進行隨機訪問,與此對應,LinkedList是以元素列表的形式存儲它的數據,每一個元素都和它的前一個和後一個連接在一起,在這種情況下,查找某個元素的時間複雜度是O(n)。
相對於A讓rayList,LinkedList的插入,添加,刪除操作速度更快,因爲當元素被添加到集合任意位置的時候,不需要像數組那樣重新計算大小或者是更新索引。
LinkedList比ArrayList更佔內存,因爲LinkedList爲每一個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
26.HshSet和TreeSet有什麼區別?
HashSet是由一個hash表來實現的,因此,它的元素是無序的,add,remove,contains方法的時間複雜度都是O(1)。另一方面,TreeSet是由一個樹形的結構來實現的,它裏面的元素是有序的,因此,add,remove,contains方法的時間複雜度是O(logn)。
27.java的兩種異常類型是什麼?它們有什麼區別?
java中有兩種異常:受檢查的異常和不受檢查的異常,不受檢查的異常不需要在方法或者是構造函數上聲明,就算方法或者是構造函數的執行可能會拋出這樣的異常,並且不受檢查的異常可以傳播到方法或者是構造函數的外面,相反,受檢查的異常必須要throws語句在方法或者是構造函數上聲明
28.java中Exception和Error有什麼區別?
Exception和Error都是Throwable的子類,Exception用於用戶程序可以捕捉的異常情況,Error定義了不期望被用戶程序捕捉的異常。
29.throw和throws有什麼區別?
throw關鍵字用來在程序中明確的拋出異常,相反,throws語句用來表名方法不能處理的異常,每一個方法都必須要指定哪些異常不能處理,所以方法的調用者才能確保處理可能發生的異常,多個異常使用逗號分隔的。
30.finally代碼塊和finalize方法有什麼區別?
無論是否拋出異常,finally代碼塊都會執行,它主要是用來釋放應用佔用的資源,finalize方法是Object類的一個protected方法,它是對象被垃圾回收之前由java虛擬機來調用的。
31.什麼是JDBC?
JDBC是允許用戶在不同數據庫之間做選擇的一個抽象層,JDBC允許開發者用java寫數據庫應用程序,而不需要關心底層特定數據庫的細節。
32.Class.forName()方法有什麼作用?
這個方法用來載入跟數據庫建立連接的驅動。
33.PreparedStatement比Statement有什麼優勢?
PreparedStatement是預編譯的,因此,性能會更好,同時,不同的查詢參數值,PreparedStatement可以重用。
34.什麼時候使用CallableStatement?用來準備CallableStatement的方法是什麼?
CallableStatement用來執行存儲過程,存儲過程是由數據庫存儲和提供的,存儲過程可以接受輸入參數,也可以有返回結果,非常鼓勵使用存儲過程,因爲它提供了安全和模塊化,準備一個CallableStatement的方法是:
CallableStatement.prepareaCall();
35.數據庫連接池是什麼意思?
像打開關閉數據庫連接這種和數據庫的交互可能是很費時的,尤其是當客戶數量增加的時候,會消耗大量的資源,成本是非常高的。可以在應用服務器啓動的時候建立很多個數據庫連接並維護在一個池中。連接請求由池中的連接提供,在連接使用完畢以後,把連接歸還池中,以用於滿足將來更多的請求。
36.GenericServlect和HttpServlect有什麼區別?
GenericServlect是一個通用的協議無關的Servlect,它實現了Servlect和ServlectConfig接口,繼承自GenericServlect的Servlect應該要覆蓋service()方法,最後,爲了開發一個能用在網頁上服務於使用HTTP協議請求的Servlect,你的Servlect必須要繼承自HttpServlect。
37.什麼Servlect鏈?
Servlect是把一個Servlect的輸出發送給另一個Servlect的方法,第二個Servlect輸出可以發送給第三個Servlect,以此類推,鏈條上最後一個Servlect負責把響應發送給客戶端。
38.如何知道是哪一個客戶端的幾期正在請求你的Servlect?
ServlectRequest類可以找出客戶端幾期的IP地址或者是主機名,getRemoteAddr()方法獲取客戶端主機的IP地址,getRemoteHost()可以獲取主機名。
39.HTTP響應的結構是怎麼樣的?
HTTP響應由三個部分組成:
狀態碼:描述了響應的狀態,可以用來檢查是否成功的完成了請求,請求失敗的情況下,狀態碼可用來找出失敗的原因,如果Servlect沒有返回狀態碼,默認會返回成功的狀態碼,HttpServlectResponse.SC_OK。
HTTP頭部:它們包含了更多關於響應的信息,比如:頭部可以指定認爲響應的過期日期,或者是指定用來給用戶安全的傳輸實體內容的編碼格式。
主體:它包含了響應的內容,它可以包含HTML代碼,圖片等等,主體是由傳輸在HTTP消息中緊跟在頭部後面的數據字節組成的。
40.什麼是Cookie?Session和Cookie有什麼區別?
cookie是Web服務器發送給瀏覽器的一塊信息,瀏覽器會在本地文件中給每一個Web服務器存儲cookie,以後服務器在給特定的Web服務器發請求的時候,同時會發送所有爲該服務器存儲的cookie
cookie和session的區別:
無論客戶端瀏覽器做怎麼樣的設置,session都應該能正常工作,客戶端可以選擇禁用cookie,但是session任然是能夠工作的,因爲客戶端無法禁用服務器端的session。
在存儲的數據量方面cookie和session也是不一樣的,session能夠存儲任意的java對象,cookie只能存儲String類型的對象。
41.瀏覽器和Servlect通信使用的是什麼協議?
瀏覽器和Servlect通信使用的是HTTP協議。
42.什麼是HTTP隧道?
HTTP隧道是一種利用HTTP或者是HTTPS把多種網絡協議封裝起來進行通信的技術,因此,HTTP協議扮演了一個打通用於通信的網絡協議的管道的包裝期的角色,把其他協議的請求掩蓋成HTTP的請求就是HTTP隧道。
43.什麼是JSP頁面?
JSP頁面是一種包含了靜態數據和JSP元素兩種類型的文本的文本文檔,靜態數據可以用任何基於文本的格式來表示,比如:HTML或者XML,JSP是一種混合了靜態內容和動態產生的內容的技術。
44.JSP請求是如何被處理的?
瀏覽器首先要請求一個以.JSP擴展名結尾的頁面,發起JSP請求,然後,Web服務器讀取這個請求,使用JSP編譯器把JSP頁面轉化成一個Servlect類。需要注意的是,只有當第一次請求頁面或者是JSP
文件發生改變的時候JSP文件纔會被編譯,然後服務器調用Servlect類,處理瀏覽器的請求,一旦請求執行結束,servlect會把響應發送給客戶端。
45.JSP有什麼優點?
JSP頁面是被動態編譯成Servlect的,因此,開發者可以很容易的更新展現代碼。
JSP頁面是可以被預編譯的
JSP頁面可以很容易的和靜態模版結合,包括:HTML或者XML,也可以很容易的和產生動態內容的代碼結合起來。
開發者可以提供讓頁面設計者以類XML格式來訪問的自定義的JSP標籤庫
開發者可以在組件層做邏輯上的改變,而不需要編輯單獨使用了應用層邏輯的頁面
46.什麼是JSP指令?JSP中有哪些不同類型的指令?
Directive是當JSP頁面被編譯成Servlect的時候,JSP引擎要處理的指令。Directive用來設置頁面級別的指令,從外部文件插入數據,指定自定義的標籤庫。Directive是定義在<%@ 和 %>之間的,下面列出來了不同類型的Directive:
包含指令:用來包含文件和合並文件內容到當前的頁面
頁面指令:用來定義JSP頁面中特定的屬性,比如錯誤頁面和緩衝區
Taglib指令:用來聲明頁面中使用的自定義的標籤庫
47.什麼是JSP動作?
JSP動作以XML語法的結構來控制Servlect引擎的行爲,當JSP頁面被請求的時候,JSP動作會被執行,它們可以被動態的插入到文件中,重用JavaBean組件,轉發用戶到其他的頁面,或者是給java插件產生HTML代碼,下面列出了可用的動作:
jsp:include-當JSP頁面被請求的時候包含一個文件
jsp:useBean-找出或者是初始化JavaBean
jsp:setProperty-設置JavaBean的屬性
jsp:getProperty-獲取JavaBean的屬性
jsp:forward-把請求轉發到新的頁面
jsp:plugin-產生特定瀏覽器的代碼
48.什麼是Scriptlets?
JSP技術中,scriptlets是嵌入在JSP頁面中的一段java代碼,scriptlet是位於標籤內部的所有的東西,在標籤與標籤之間,用戶可以添加任意有效的scriptlet。
49.聲明(Decalaration)在哪裏?
聲明跟java的變量聲明很相似,它用來聲明隨後要被表達或者scriptlet使用的變量,添加的聲明必須要開始和結束標籤包起來。
50.什麼是表達式(Expression)?
JSP表達式是Web服務器把腳本語言表達式的值轉化成一個String對象,插入到返回給客戶端的數據流中,表達式是在<%= 和 %>這兩個標籤之間定義的。
51.隱含對象是什麼意思?有哪些隱含對象?
JSP隱含對象是頁面中的一些Java對象,JSP容器讓這些Java對象可以爲開發者所用,開發者不用明確的聲明就可以使用他們,JSP隱含對象也叫做預定義變量,下面列出了JSP的隱含對象:
application,page,request,response,session,exception,out,config,pageContext
52.java多線程中的死鎖
死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種相互等待的現象,若無外力作用,它們都將無法推進下去。死鎖會讓你的程序掛起無法完成任務,造成死鎖必須滿足四條件:
互斥條件,一個資源只能被一個進程使用
請求與保持條件,一個進程因請求資源而阻塞時,對已經獲得的資源保持不放
不剝奪條件,進程已獲得的資源,在未使用完之前,不能強行剝奪
循環等待條件,若干進程之間行程一種頭尾相接的循環等待資源關係
避免死鎖最賤的方法就是組織循環等待條件,將系統中所有的資源設置成標誌位,排序,規定所有的進程申請資源必須以一定的順序(升序或降序)做操作來避免死鎖
53.java中死鎖和活鎖有什麼區別?
活鎖和死鎖類似,不同之處在於處於活鎖的線程或進程是不斷改變的,活鎖可以認爲是一種特殊的飢餓,一個現實的活鎖例子是兩個人在狹小的走廊碰到,兩個人都試着避讓對方讓彼此通過,但是因爲避讓的方向都一樣導致誰都不能通過,簡單的說就是,活鎖和死鎖的主要區別就是前者進程的狀態可以改變但是卻不能繼續執行
54.怎麼檢查一個線程是否擁有鎖?
在java.lang.Thread中有一個方法叫holdsLock,它返回true如果當且僅當當前線程擁有某個具體對象的鎖
55.有三個線程T1,T2,T3,怎麼確保它們按順序執行
可以使用join方法在一個線程中啓動另一個線程,另外一個線程完成該線程繼續執行,爲了確保三個線程的順序你應該先啓動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成
56.Thread類中的yield方法有什麼作用?
Yield方法可以暫停當前正在執行的線程對象,讓其他擁有相同優先級的線程執行,它是一種靜態方法 ,而且只保證當前線程放棄CPU佔用而不能保證線程一定能佔用CPU,執行yield的線程可能在進入到暫停狀態後馬上又被執行。
57.說出Servlet的生命週期,並說出Servlet和CGI的區別
Servlet被服務器實例化後,容器運行其init方法,請求到達時運行service方法,service方法自動派遣運行與請求對應的doXXX方法(doGet,doPost)等,當服務器決定將實例銷燬的時候調用destroy方法,與cgi的區別在於servlet處於服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務於多個請求,並且其實例一般不會銷燬,而CGI對每個請求都產生新的進程,服務完成後銷燬,所以效率上低於servlet。
58.Statement和PreparedStatement有什麼區別?哪個性能更好?
與Statement相比:
1)PreparedStatement接口代表預編譯的語句,它主要的優勢在於可以減少SQL的編譯錯誤並增加SQL的安全性(減少SQL注射攻擊的可能性);
2)PreparedStatement中的SQL語句是可以帶參數的,避免了用字符串連接拼接SQL語句的麻煩和不安全;
3)當批量處理SQL或頻繁執行相同的查詢時,PreparedStatement有明顯的性能上的優勢,由於數據庫可以將編譯優化後的SQL語句緩存起來,下次執行相同結構的語句時就會很快。
59.使用JDBC操作數據庫時,如何提升讀取數據的性能?如何提升更新數據的性能?
要提升讀取數據的性能,可以指定通過結果集(ResultSet)對象的setFetchSize()方法指定每次讀取的記錄數(空間換時間),要提升更新數據的性能可以使用PreparedStatement語句構建批處理,將若干SQL語句置於一個批處理中執行。
60.在進行數據庫編程時,連接池有什麼作用?
由於創建連接和釋放連接都有很大的開銷(尤其是數據庫服務器不在本地時,每次建立連接都需要進行TCP的三次握手,釋放連接需要進行TCP四次握手,造成的開銷是不可忽視的),爲了提升系統訪問數據庫的性能,可以事先創建若干連接置於連接池中,需要時直接從連接池獲取,使用結束時歸還連接池而不必關閉連接,從而避免頻繁創建和釋放連接所造成的開銷,這是典型的用空間換時間的策略(浪費了空間存儲連接,但節省了創建和釋放連接的時間)。
61.事務的ACID是什麼?
原子性(Atomic):事務中各項操作,要麼全做要麼全不做,任何一項操作的失敗都會導致整個事務的失敗;
一致性(Consistent):事務結束後系統狀態是一致的;
隔離性(Isolated):併發執行的事務批次無法看到對象的中間狀態;
持久性(Durable):事務完成後所做的改動都會被持久化,即使發生災難性的失敗,通過日誌和同步備份可以在故障發生後重建數據。
髒讀(Dirty Read):A事務讀取B事務尚未提交的數據並在此基礎上操作,而B事務執行回滾,那麼A讀取到的數據就是髒數據。
不可重複度(Unrepeatable Read):事務A重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務B修改過了。
幻讀(Phantom Read):事務A重新執行一個查詢,返回一系列符合查詢條件的行,發現其中插入了被事務B提交的行。
第1類丟失更新:事務A撤銷時,把已經提交的事務B的更新數據覆蓋了。
第2類丟失更新:事務A覆蓋事務B已經提交的數據,造成事務B所做的操作丟失。
數據併發訪問所產生的問題,在有些場景下可能是允許的,但是有些場景下可能就是致命的,數據庫通常會通過鎖機制來解決數據併發訪問問題,按鎖定對象不同可以分爲表級鎖和行級鎖;按併發事務鎖關係可以分爲共享鎖和獨佔鎖。
直接使用鎖非常麻煩的,爲此數據庫用戶提供了自動鎖機制,只要用戶指定會話的事務隔離級別,數據庫就會通過分析SQL語句然後爲事務訪問的資源加上合適的鎖,此外,數據庫還會維護這些鎖通過各種手段提高系統的性能,這些對用戶來說是透明的

需要說明的是,事務隔離級別和數據訪問的併發性是對立的,事務隔離級別越高併發性就越差。所以要根據具體的應用來確定合適的事務隔離級別,這個地方沒有萬能的原則。
62.獲得一個類的類對象的方式有哪些?
1):類型.class,例如:String.class
2):對象.getClass(),例如:”hello”.getClass()
3):Class.forName(),例如:Class.forName(“java.lang.string”)
63.如何通過反射創建對象?
1)通過類對象調用newInstance()方法,例如:
String.class.newInstance()
2)通過類對象的getConstructor()或getDeclaredConstructor()方法獲得構造器(Constructor)對象並調用其newInstance()方法創建對象,例如:
String.class.getConstructor(String.class).newInstance(“Hello”);
63.如何通過反射調用對象的方法?
class MethodInvokeTest { public static void main(String[] args) throws Exception { String str = “hello”; Method m = str.getClass().getMethod(“toUpperCase”); System.out.println(m.invoke(str)); // HELLO }
}
64.簡述一下面向對象的“六原則-法則”
單一職責原則:一個類值做它該做的事,高內聚,低耦合
開閉原則:軟件實體對擴展開放,對修改關閉
依賴倒轉原則:面向接口編程
里氏替換原則:任何時候都可以用子類型替換掉父類型
接口隔離原則:接口小而專,絕不能大而全
合成聚合複用原則:優先使用聚合或合成關係複用代碼
迪米特法則:最少知道原則,一個對象應該對其他對象有儘可能少的瞭解(低耦合)
這裏寫圖片描述
圖一:不符合迪米特法則的設計
這裏寫圖片描述
圖二:符合迪米特法則的設計
65.設計模式
工廠模式:工廠類可以根據條件生成不同的子類實例,這些子類有一個公共的抽象父類並且實現了相同的方法,但是這些方法針對不同的數據進行了不同的操作(多態方法),當得到子類的實例後,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的實例
代理模式:給一個對象提供一個代理對象,並由代理對象控制原對象的引用。實際開發中,按照使用目的的不同,代理可以分爲:遠程代理,虛擬代理,保護代理,Cache代理,防火牆代理,同步化代理,智能引用代理。
適配器模式:把一個類的接口換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起使用的類能夠一起工作。
模版方法模式:提供一個抽象類,將部分邏輯以具體方法或構造器的形式實現,然後聲明一些抽象方法來迫使子類實現剩餘的邏輯,不同的子類可以以不同的方式實現這些抽象方法,從而實現不同的業務邏輯。
66.排序算法
1)冒泡排序
2)二分查找
67.Servlet接口中有哪些方法?
Servlet接口定義了5個方法,其中前三個方法與Servlet生命週期有關:
void init(ServletConfig config) throws ServletException
void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
void destory()
java.lang.String getServletInfo()
ServletConfig getServletConfig()
Web容器加載Servlet並將其實例化後,Servlet生命週期開始,容器運行其init()方法進行Servlet的初始化;請求到達時調用Servlet的service()方法,service()方法會根據需要調用與請求對應的doGet或doPost等方法;當前服務器關閉或項目被卸載時服務器會將Servlet實例銷燬,此時調用Servlet的destroy()方法。
68.get和post請求的區別
1)get請求用來從服務器上獲得資源,而post是用來向服務器提交數據;
2)get將表單中數據按照anme = value的形式,添加到action所指向的URL後面,並且兩者使用“?”連接,而兩個變量之間使用“&”連接;post是將表單中的數據放在HTTP協議的請求頭或消息體中,傳遞到action所指向URL;
3)get傳輸的數據收到URL長度限制(1024字節);而post可以傳輸大量數據,上傳文件通常要使用post方式;
4)使用get時參數會顯示在地址欄上,如果這些數據不是敏感數據,那麼可以使用get;對於敏感數據還是應該使用post;
5)get使用MIME類型application/x-www-form-urlencoded的URL編碼(也叫百分號編碼)文本的格式傳遞參數,保證被傳送的參數由遵循規範的文本組成,例如一個空格的編碼是“%20”。
69.講解JSP中的四種作用域。
JSP中的四種作用域包括page,request,session,application
page代表一個與頁面相關的對象和屬性
request代表與web客戶機發出的一個請求相關的對象和屬性,一個請求可能跨越多個頁面,涉及多個web組件,需要在頁面顯示的臨時數據可以置於此作用域
session代表與某個用戶與服務器建立的一次會話相關的對象和屬性,跟某個用戶相關的數據應該放在用戶自己的session中
application代表與整個web應用程序相關的對象和屬性,它實質上是跨越整個web應用程序,包括多個頁面,請求和會話的一個全局作用域。
70.你的項目中使用過哪些JSTL標籤?
項目中主要使用了JSTL的核心標籤庫,包括、、、、等,主要用於構造循環和分支結構以控制顯示邏輯。
71.Servlet3中的異步處理指的是什麼?
如果一個任務處理時間相當長,那麼Servlet或Filter會一直佔用着請求處理線程直到任務結束,隨着併發用戶的增加,容器將會遭遇線程超出的風險,這種情況下很多的請求將會堆積起來而後續的請求可能會遭遇拒絕服務,直到有資源可以處理請求爲止,異步特性可以幫助應用節省容器中的線程,特別適合執行時間長而且用戶需要得到結果的任務,如果用戶不需要得到結果則直接將一個Runnable對象交給Executor並立即返回即可。
72.Servlet中如何獲取用戶提交的查詢參數或表單數據?
可以通過請求對象(HttpServletRequest)的getParameter()方法通過參數名獲得參數值,如果有包含多個值的參數(例如複選框),可以通過請求對象的getParameterValues()方法獲得,當然也可以通過請求對象的getParameterMap()獲得一個參數名和參數值的映射(Map)。
73.Servlet中如何獲取用戶配置的初始化參數以及服務器上下文參數?
可以通過重寫Servlet接口的init(ServletConfig)方法並通過ServletConfig對象的getInitParameter()方法來獲取Servlet的初始化參數。可以通過ServletConfig對象的getServletContext()方法獲取ServletContext對象,並通過該對象的getInitParameter()方法來獲取服務器上下文參數。當然,ServletContext對象也在處理用戶請求的方法(如doGet()方法)中通過請求對象的getServletContext()方法來獲得。
74.如何設置請求的編碼以及響應內容的類型?
通過請求對象(ServletRequest)的setCharacterEncoding(String)方法可以設置請求的編碼,其實要徹底解決亂碼問題就應該讓頁面、服務器、請求和響應、Java程序都使用統一的編碼,最好的選擇當然是UTF-8;通過響應對象(ServletResponse)的setContentType(String)方法可以設置響應內容的類型,當然也可以通過HttpServletResponsed對象的setHeader(String, String)方法來設置。
75.網絡應用模式
典型的網絡應用:B/S、C/S、P2P
B2B(如阿里巴巴)、B2C(如噹噹、亞馬遜、京東)、C2C(如淘寶、拍拍)、C2B(如威客)、O2O(如美團、餓了麼)
76.概念解釋:SOAP,WSDL,UDDI
SOAP:簡單對象訪問協議(SimpleObjectAccessProtocol),是Web Service中交換數據的一種協議規範。
WSDL:Web服務描述語言(Web Service Description Language),它描述了Web服務的公共接口。這是一個基於XML的關於如何與Web服務通訊和使用的服務描述;也就是描述與目錄中列出的Web服務進行交互時需要綁定的協議和信息格式。通常採用抽象語言描述該服務支持的操作和信息,使用的時候再將實際的網絡協議和信息格式綁定給該服務。
UDDI:統一描述、發現和集成(Universal Description, Discovery and Integration),它是一個基於XML的跨平臺的描述規範,可以使世界範圍內的企業在互聯網上發佈自己所提供的服務。簡單的說,UDDI是訪問各種WSDL的一個門面(可以參考設計模式中的門面模式)。
77.什麼是ORM(Object-Relational Mapping,簡稱ORM)?
對象關係映射是一種爲了解決程序的面向對象模型與數據庫的關係模型互不匹配問題的技術;ORM是通過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關係數據庫中或者將關係數據庫中的行轉換成java對象,實質上是將數據從一種形式轉換到另外一種形式
78.持久層設計要考慮的問題有哪些?你用過的持久層框架有哪些?
所謂“持久”就是將數據保存到可掉電式存儲設備中以便今後使用,簡單的說,就是將內存中的數據保存到關係型數據庫,文件系統,消息隊列等提供持久化支持的設備中,持久層就是刺痛中專注於實現數據持久化的相對獨立的層面。
持久層設計的目標包括:
數據存儲邏輯的分離,提供抽象化的數據訪問接口。
數據訪問底層實現的分離,可以在不修改代碼的情況下切換底層實現。
資源管理和調度的分離,在數據訪問層實現統一的資源調度(如緩存機制)。
數據抽象,提供更面向對象的數據操作。
持久層框架有:
Hibernate
MyBatis
TopLink
Guzz
jOOQ
Spring Data
ActiveJDBC
79.Hibernate中SessionFactory是線程安全的嗎?Session是線程安全的嗎(兩個線程能夠共享同一個Session嗎)?
SessionFactory對應Hibernate的一個數據存儲的概念,它是線程安全的,可以被多個線程併發訪問。SessionFactory一般只會在啓動的時候構建。對於應用程序,最好將SessionFactory通過單例模式進行封裝以便於訪問。Session是一個輕量級非線程安全的對象(線程間不能共享Session),它表示與數據庫進行交互的一個工作單元,Session是由SessionFactory創建的,在任務完成之後它會被關閉,Session是持久層服務對外提供的主要接口。Session會延遲獲取數據庫連接(也就是在需要的時候才獲取),爲了避免創建太多的Session,可以使用ThreadLocal將Session和當前線程綁定在一起,這樣可以讓同一個線程獲得的總是同一個session,Hibernate3中的SessionFactory的getCurrentSession()方法就可以得到。
80.Hibernate中Session的load和get方法的區別是什麼?
主要有三個區別:
1):如果沒有找到符合條件的記錄,get返回null,load方法拋出異常。
2):get方法直接返回實體類對象,load方法返回實體類對象的代理
3):在Hibernate3之前,get方法只在一級緩存中進行數據查找,如果沒有找到對應的數據則越過二級緩存,直接發出SQL語句完成數據讀取;load方法則可以從二級緩存中獲取數據;從Hibernate3開始。get方法不再是對二級緩存只寫不讀,它也是可以訪問二級緩存的。
81.闡述Session加載實體對象的過程。
Session加載實體對象的步驟是:
1)Session在調用數據庫查詢功能之前,首先會在一級緩存中通過實體類型和主鍵進行查找,如果一級緩存查找命中切數據狀態合法,則直接返回;
2)如果一級緩存沒有命中,接下來Session會在當前NonExists記錄(相當於一個查詢黑名單,如果出現重複的無效查詢可以迅速做出判斷,從而提升性能)中查找,如果NonExists中存在同樣的查詢條件,則返回null;
3)如果一級緩存查詢失敗則查詢二級緩存,如果二級緩存命中則直接返回;
4)如果之前的查詢都沒有命中,則發出SQL語句,如果查詢未發現對應記錄則將此次查詢添加到Session的NonExists中加以記錄,並返回null;
5)根據映射配置和SQL語句得到ResultSet,並創建對應的實體對象;
6)將對象納入Session的管理;
7)如果有對應的攔截器,則進行攔截器的onLoad方法;
8)如果開啓設置了要使用二級緩存,則將數據對象納入二級緩存;
9)返回數據對象
82.Hibernate如何實現分頁查詢?
通過Hibernate實現分頁查詢,開發人員只需要提供HQL語句(調用Session的createQuery()方法)或查詢條件(調用Session的createCriteria()方法)、設置查詢起始行數(調用Query或Criteria接口的setFirstResult()方法)和最大查詢行數(調用Query或Criteria接口的setMaxResults()方法),並調用Query或Criteria接口的list()方法,Hibernate會自動生成分頁查詢的SQL語句。
83.鎖機制有什麼用?簡述Hibernated額悲觀鎖和樂觀鎖機制
悲觀鎖,認爲在數據處理過程中極有可能存在修改數據的併發事務,於是將處理的數據設置爲鎖定狀態。
樂觀鎖,對併發事務持樂觀態度(認爲對數據的併發操作不會經常性的發生),通過更加寬鬆的鎖機制來解決悲觀鎖排他性的數據訪問對系統性能造成的嚴重影響。
84.闡述實體對象的三種狀態以及轉換關係
四種種狀態分別是:瞬時態(new, or transient)、持久態(managed, or persistent)、遊狀態(detached)和移除態(removed,以前Hibernate文檔中定義的三種狀態中沒有移除態):
這裏寫圖片描述
圖三:Hibernate實體對象狀態轉換圖
瞬時態:當new一個實體對象後,這個對象處於瞬時態,即這個對象只是一個保存臨時數據的內存區域,如果沒有變量引用這個對象,則會被JVM的垃圾回收機制回收。這個對象所保存的數據與數據庫沒有任何關係,除非通過Session的save()、saveOrUpdate()、persist()、merge()方法把瞬時態對象與數據庫關聯,並把數據插入或者更新到數據庫,這個對象才轉換爲持久態對象。
持久態:持久態對象的實例在數據庫中有對應的記錄,並擁有一個持久化標識(ID)。對持久態對象進行delete操作後,數據庫中對應的記錄將被刪除,那麼持久態對象與數據庫記錄不再存在對應關係,持久態對象變成移除態(可以視爲瞬時態)。持久態對象被修改變更後,不會馬上同步到數據庫,直到數據庫事務提交。
遊離態:當Session進行了close()、clear()、evict()或flush()後,實體對象從持久態變成遊離態,對象雖然擁有持久和與數據庫對應記錄一致的標識值,但是因爲對象已經從會話中清除掉,對象不在持久化管理之內,所以處於遊離態(也叫脫管態)。遊離態的對象與臨時狀態對象是十分相似的,只是它還含有持久化標識。
85.如何理解Hibernate的延遲加載機制?在實際應用中,延遲加載與Session關閉的矛盾是如何處理的?
延遲加載就是並不是在讀取的時候就把數據加載進來,而是等到使用時再加載。Hibernate使用了虛擬代理機制實現延遲加載,我們使用Session的load()方法加載數據或者一對多關聯映射在使用延遲加載的情況下從一的一方加載多的一方,得到的都是虛擬代理,簡單的說返回給用戶的並不是實體本身,而是實體對象的代理。代理對象在用戶調用getter方法時纔會去數據庫加載數據。但加載數據就需要數據庫連接。而當我們把會話關閉時,數據庫連接就同時關閉了。
延遲加載與session關閉的矛盾一般可以這樣處理:
① 關閉延遲加載特性。這種方式操作起來比較簡單,因爲Hibernate的延遲加載特性是可以通過映射文件或者註解進行配置的,但這種解決方案存在明顯的缺陷。首先,出現”no session or session was closed”通常說明系統中已經存在主外鍵關聯,如果去掉延遲加載的話,每次查詢的開銷都會變得 很大。
② 在session關閉之前先獲取需要查詢的數據,可以使用工具方法Hibernate.isInitialized()判斷對象是否被加載,如果沒有被加載則可以使用Hibernate.initialize()方法加載對象。
③ 使用攔截器或過濾器延長Session的生命週期直到視圖獲得數據。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是這種做法。
86.談一下你對繼承映射的理解。
繼承關係的映射策略有三種:
① 每個繼承結構一張表(table per class hierarchy),不管多少個子類都用一張表。
② 每個子類一張表(table per subclass),公共信息放一張表,特有信息放單獨的表。
③ 每個具體類一張表(table per concrete class),有多少個子類就有多少張表。
第一種方式屬於單表策略,其優點在於查詢子類對象的時候無需表連接,查詢速度快,適合多態查詢;缺點是可能導致表很大。後兩種方式屬於多表策略,其優點在於數據存儲緊湊,其缺點是需要進行連接查詢,不適合多態查詢。
87.簡述Hibernate常見優化策略。
① 制定合理的緩存策略(二級緩存、查詢緩存)。
② 採用合理的Session管理機制。
③ 儘量使用延遲加載特性。
④ 設定合理的批處理參數。
⑤ 如果可以,選用UUID作爲主鍵生成器。
⑥ 如果可以,選用基於版本號的樂觀鎖替代悲觀鎖。
⑦ 在開發過程中, 開啓hibernate.show_sql選項查看生成的SQL,從而瞭解底層的狀況;開發完成後關閉此選項。
88.談一談Hibernate的一級緩存、二級緩存和查詢緩存。
Hibernate的Session提供了一級緩存的功能,默認總是有效的,當應用程序保存持久化實體、修改持久化實體時,Session並不會立即把這種改變提交到數據庫,而是緩存在當前的Session中,除非顯示調用了Session的flush()方法或通過close()方法關閉Session。通過一級緩存,可以減少程序與數據庫的交互,從而提高數據庫訪問性能。SessionFactory級別的二級緩存是全局性的,所有的Session可以共享這個二級緩存。不過二級緩存默認是關閉的,需要顯示開啓並指定需要使用哪種二級緩存實現類(可以使用第三方提供的實現)。一旦開啓了二級緩存並設置了需要使用二級緩存的實體類,SessionFactory就會緩存訪問過的該實體類的每個對象,除非緩存的數據超出了指定的緩存空間。
一級緩存和二級緩存都是對整個實體進行緩存,不會緩存普通屬性,如果希望對普通屬性進行緩存,可以使用查詢緩存。查詢緩存是將HQL或SQL語句以及它們的查詢結果作爲鍵值對進行緩存,對於同樣的查詢可以直接從緩存中獲取數據。查詢緩存默認也是關閉的,需要顯示開啓。
89.什麼是IoC和DI?DI是如何實現的?
IoC叫控制反轉,是Inversion of Control的縮寫,DI(Dependency Injection)叫依賴注入,是對IoC更簡單的詮釋。控制反轉是把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的”控制反轉”就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器,由容器來創建對象並管理對象之間的依賴關係。IoC體現了好萊塢原則 - “Don’t call me, we will call you”。依賴注入的基本原則是應用組件不應該負責查找資源或者其他依賴的協作對象。配置對象的工作應該由容器負責,查找資源的邏輯應該從應用組件的代碼中抽取出來,交給容器來完成。DI是對IoC更準確的描述,即組件之間的依賴關係由容器在運行期決定,形象的來說,即由容器動態的將某種依賴關係注入到組件之中。
依賴注入可以通過setter方法注入(設值注入)、構造器注入和接口注入三種方式來實現,Spring支持setter注入和構造器注入,通常使用構造器注入來注入必須的依賴關係,對於可選的依賴關係,則setter注入是更好的選擇,setter注入需要類提供無參構造器或者無參的靜態工廠方法來創建對象。
90.解釋一下什麼叫AOP(面向切面編程)?
AOP(Aspect-Oriented Programming)指一種程序設計範型,該範型以一種稱爲切面(aspect)的語言構造爲基礎,切面是一種新的模塊化機制,用來描述分散在對象、類或方法中的橫切關注點(crosscutting concern)。
91.你是如何理解”橫切關注”這個概念的?
“橫切關注”是會影響到整個應用程序的關注功能,它跟正常的業務邏輯是正交的,沒有必然的聯繫,但是幾乎所有的業務邏輯都會涉及到這些關注功能。通常,事務、日誌、安全性等關注就是應用中的橫切關注功能。
92.你如何理解AOP中的連接點(Joinpoint)、切點(Pointcut)、增強(Advice)、引介(Introduction)、織入(Weaving)、切面(Aspect)這些概念?
連接點(Joinpoint):程序執行的某個特定位置(如:某個方法調用前、調用後,方法拋出異常後)。一個類或一段程序代碼擁有一些具有邊界性質的特定點,這些代碼中的特定點就是連接點。Spring僅支持方法的連接點。
切點(Pointcut):如果連接點相當於數據中的記錄,那麼切點相當於查詢條件,一個切點可以匹配多個連接點。Spring AOP的規則解析引擎負責解析切點所設定的查詢條件,找到對應的連接點。
增強(Advice):增強是織入到目標類連接點上的一段程序代碼。Spring提供的增強接口都是帶方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。很多資料上將增強譯爲“通知”,這明顯是個詞不達意的翻譯,讓很多程序員困惑了許久。
引介(Introduction):引介是一種特殊的增強,它爲類添加一些屬性和方法。這樣,即使一個業務類原本沒有實現某個接口,通過引介功能,可以動態的未該業務類添加接口的實現邏輯,讓業務類成爲這個接口的實現類。
織入(Weaving):織入是將增強添加到目標類具體連接點上的過程,AOP有三種織入方式:①編譯期織入:需要特殊的Java編譯期(例如AspectJ的ajc);②裝載期織入:要求使用特殊的類加載器,在裝載類的時候對類進行增強;③運行時織入:在運行時爲目標類生成代理實現增強。Spring採用了動態代理的方式實現了運行時織入,而AspectJ採用了編譯期織入和裝載期織入的方式
切面(Aspect):切面是由切點和增強(引介)組成的,它包括了對橫切關注功能的定義,也包括了對連接點的定義。
93.Spring中自動裝配的方式有哪些?
no:不進行自動裝配,手動設置Bean的依賴關係。
byName:根據Bean的名字進行自動裝配。
byType:根據Bean的類型進行自動裝配。
constructor:類似於byType,不過是應用於構造器的參數,如果正好有一個Bean與構造器的參數類型相同則可以自動裝配,否則會導致錯誤。
autodetect:如果有默認的構造器,則通過constructor的方式進行自動裝配,否則使用byType的方式進行自動裝配。
94.Spring中如何使用註解來配置Bean?有哪些相關的註解?
首先需要在Spring配置文件中增加如下配置:

然後可以用@Component、@Controller、@Service、@Repository註解來標註需要由Spring IoC容器進行對象託管的類。這幾個註解沒有本質區別,只不過@Controller通常用於控制器,@Service通常用於業務邏輯類,@Repository通常用於倉儲類(例如我們的DAO實現類),普通的類用@Component來標註。
95.Spring支持的事務管理類型有哪些?你在項目中使用哪種方式?
Spring支持編程式事務管理和聲明式事務管理。許多Spring框架的用戶選擇聲明式事務管理,因爲這種方式和應用程序的關聯較少,因此更加符合輕量級容器的概念。聲明式事務管理要優於編程式事務管理,儘管在靈活性方面它弱於編程式事務管理,因爲編程式事務允許你通過代碼控制業務。
事務分爲全局事務和局部事務。全局事務由應用服務器管理,需要底層服務器JTA支持(如WebLogic、WildFly等)。局部事務和底層採用的持久化方案有關,例如使用JDBC進行持久化時,需要使用Connetion對象來操作事務;而採用Hibernate進行持久化時,需要使用Session對象來操作事務。
Spring提供瞭如下所示的事務管理器。
這裏寫圖片描述
96.Spring MVC的工作原理是怎樣的?
Spring MVC的工作原理如下圖所示:
這裏寫圖片描述
① 客戶端的所有請求都交給前端控制器DispatcherServlet來處理,它會負責調用系統的其他模塊來真正處理用戶的請求。
② DispatcherServlet收到請求後,將根據請求的信息(包括URL、HTTP協議方法、請求頭、請求參數、Cookie等)以及HandlerMapping的配置找到處理該請求的Handler(任何一個對象都可以作爲請求的Handler)。
③在這個地方Spring會通過HandlerAdapter對該處理器進行封裝。
④ HandlerAdapter是一個適配器,它用統一的接口對各種Handler中的方法進行調用。
⑤ Handler完成對用戶請求的處理後,會返回一個ModelAndView對象給DispatcherServlet,ModelAndView顧名思義,包含了數據模型以及相應的視圖的信息。
⑥ ModelAndView的視圖是邏輯視圖,DispatcherServlet還要藉助ViewResolver完成從邏輯視圖到真實視圖對象的解析工作。
⑦ 當得到真正的視圖對象後,DispatcherServlet會利用視圖對象對模型數據進行渲染。
⑧ 客戶端得到響應,可能是一個普通的HTML頁面,也可以是XML或JSON字符串,還可以是一張圖片或者一個PDF文件。
97.選擇使用Spring框架的原因(Spring框架爲企業級開發帶來的好處有哪些)?
非侵入式:支持基於POJO的編程模式,不強制性的要求實現Spring框架中的接口或繼承Spring框架中的類。
IoC容器:IoC容器幫助應用程序管理對象以及對象之間的依賴關係,對象之間的依賴關係如果發生了改變只需要修改配置文件而不是修改代碼,因爲代碼的修改可能意味着項目的重新構建和完整的迴歸測試。有了IoC容器,程序員再也不需要自己編寫工廠、單例,這一點特別符合Spring的精神”不要重複的發明輪子”。
AOP(面向切面編程):將所有的橫切關注功能封裝到切面(aspect)中,通過配置的方式將橫切關注功能動態添加到目標代碼上,進一步實現了業務邏輯和系統服務之間的分離。另一方面,有了AOP程序員可以省去很多自己寫代理類的工作。
MVC:Spring的MVC框架是非常優秀的,從各個方面都可以甩Struts 2幾條街,爲Web表示層提供了更好的解決方案。
事務管理:Spring以寬廣的胸懷接納多種持久層技術,並且爲其提供了聲明式的事務管理,在不需要任何一行代碼的情況下就能夠完成事務管理。
其他:選擇Spring框架的原因還遠不止於此,Spring爲Java企業級開發提供了一站式選擇,你可以在需要的時候使用它的部分和全部,更重要的是,你甚至可以在感覺不到Spring存在的情況下,在你的項目中使用Spring提供的各種優秀的功能。
98.Spring IoC容器配置Bean的方式?
基於XML文件進行配置。
基於註解進行配置。
基於Java程序進行配置(Spring 3+)
99.闡述Spring框架中Bean的生命週期?
① Spring IoC容器找到關於Bean的定義並實例化該Bean。
② Spring IoC容器對Bean進行依賴注入。
③ 如果Bean實現了BeanNameAware接口,則將該Bean的id傳給setBeanName方法。
④ 如果Bean實現了BeanFactoryAware接口,則將BeanFactory對象傳給setBeanFactory方法。
⑤ 如果Bean實現了BeanPostProcessor接口,則調用其postProcessBeforeInitialization方法。
⑥ 如果Bean實現了InitializingBean接口,則調用其afterPropertySet方法。
⑦ 如果有和Bean關聯的BeanPostProcessors對象,則這些對象的postProcessAfterInitialization方法被調用。
⑧ 當銷燬Bean實例時,如果Bean實現了DisposableBean接口,則調用其destroy方法。
100.依賴注入時如何注入集合屬性?
可以在定義Bean屬性時,通過 / / / 分別爲其注入列表、集合、映射和鍵值都是字符串的映射屬性。
101.Spring中的自動裝配有哪些限制?
如果使用了構造器注入或者setter注入,那麼將覆蓋自動裝配的依賴關係。
基本數據類型的值、字符串字面量、類字面量無法使用自動裝配來注入。
優先考慮使用顯式的裝配來進行更精確的依賴注入而不是使用自動裝配。
102.在Web項目中如何獲得Spring的IoC容器?
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
103. 大型網站在架構上應當考慮哪些問題?
分層:分層是處理任何複雜系統最常見的手段之一,將系統橫向切分成若干個層面,每個層面只承擔單一的職責,然後通過下層爲上層提供的基礎設施和服務以及上層對下層的調用來形成一個完整的複雜的系統。計算機網絡的開放系統互聯參考模型(OSI/RM)和Internet的TCP/IP模型都是分層結構,大型網站的軟件系統也可以使用分層的理念將其分爲持久層(提供數據存儲和訪問服務)、業務層(處理業務邏輯,系統中最核心的部分)和表示層(系統交互、視圖展示)。需要指出的是:(1)分層是邏輯上的劃分,在物理上可以位於同一設備上也可以在不同的設備上部署不同的功能模塊,這樣可以使用更多的計算資源來應對用戶的併發訪問;(2)層與層之間應當有清晰的邊界,這樣分層纔有意義,才更利於軟件的開發和維護。
分割:分割是對軟件的縱向切分。我們可以將大型網站的不同功能和服務分割開,形成高內聚低耦合的功能模塊(單元)。在設計初期可以做一個粗粒度的分割,將網站分割爲若干個功能模塊,後期還可以進一步對每個模塊進行細粒度的分割,這樣一方面有助於軟件的開發和維護,另一方面有助於分佈式的部署,提供網站的併發處理能力和功能的擴展。
分佈式:除了上面提到的內容,網站的靜態資源(JavaScript、CSS、圖片等)也可以採用獨立分佈式部署並採用獨立的域名,這樣可以減輕應用服務器的負載壓力,也使得瀏覽器對資源的加載更快。數據的存取也應該是分佈式的,傳統的商業級關係型數據庫產品基本上都支持分佈式部署,而新生的NoSQL產品幾乎都是分佈式的。當然,網站後臺的業務處理也要使用分佈式技術,例如查詢索引的構建、數據分析等,這些業務計算規模龐大,可以使用Hadoop以及MapReduce分佈式計算框架來處理。
集羣:集羣使得有更多的服務器提供相同的服務,可以更好的提供對併發的支持。
緩存:所謂緩存就是用空間換取時間的技術,將數據儘可能放在距離計算最近的位置。使用緩存是網站優化的第一定律。我們通常說的CDN、反向代理、熱點數據都是對緩存技術的使用。
異步:異步是實現軟件實體之間解耦合的又一重要手段。異步架構是典型的生產者消費者模式,二者之間沒有直接的調用關係,只要保持數據結構不變,彼此功能實現可以隨意變化而不互相影響,這對網站的擴展非常有利。使用異步處理還可以提高系統可用性,加快網站的響應速度(用Ajax加載數據就是一種異步技術),同時還可以起到削峯作用(應對瞬時高併發)。&quot;能推遲處理的都要推遲處理”是網站優化的第二定律,而異步是踐行網站優化第二定律的重要手段。
冗餘:各種服務器都要提供相應的冗餘服務器以便在某臺或某些服務器宕機時還能保證網站可以正常工作,同時也提供了災難恢復的可能性。冗餘是網站高可用性的重要保證。
104.你用過的網站前端優化的技術有哪些?
① 瀏覽器訪問優化:
減少HTTP請求數量:合併CSS、合併JavaScript、合併圖片(CSS Sprite)
使用瀏覽器緩存:通過設置HTTP響應頭中的Cache-Control和Expires屬性,將CSS、JavaScript、圖片等在瀏覽器中緩存,當這些靜態資源需要更新時,可以更新HTML文件中的引用來讓瀏覽器重新請求新的資源
啓用壓縮
CSS前置,JavaScript後置
減少Cookie傳輸
② CDN加速:CDN(Content Distribute Network)的本質仍然是緩存,將數據緩存在離用戶最近的地方,CDN通常部署在網絡運營商的機房,不僅可以提升響應速度,還可以減少應用服務器的壓力。當然,CDN緩存的通常都是靜態資源。
③ 反向代理:反向代理相當於應用服務器的一個門面,可以保護網站的安全性,也可以實現負載均衡的功能,當然最重要的是它緩存了用戶訪問的熱點資源,可以直接從反向代理將某些內容返回給用戶瀏覽器。
105.你使用過的應用服務器優化技術有哪些?
① 分佈式緩存:緩存的本質就是內存中的哈希表,如果設計一個優質的哈希函數,那麼理論上哈希表讀寫的漸近時間複雜度爲O(1)。緩存主要用來存放那些讀寫比很高、變化很少的數據,這樣應用程序讀取數據時先到緩存中讀取,如果沒有或者數據已經失效再去訪問數據庫或文件系統,並根據擬定的規則將數據寫入緩存。對網站數據的訪問也符合二八定律(Pareto分佈,冪律分佈),即80%的訪問都集中在20%的數據上,如果能夠將這20%的數據緩存起來,那麼系統的性能將得到顯著的改善。當然,使用緩存需要解決以下幾個問題:
頻繁修改的數據;
數據不一致與髒讀;
緩存雪崩(可以採用分佈式緩存服務器集羣加以解決,memcached是廣泛採用的解決方案);
緩存預熱;
緩存穿透(惡意持續請求不存在的數據)。
② 異步操作:可以使用消息隊列將調用異步化,通過異步處理將短時間高併發產生的事件消息存儲在消息隊列中,從而起到削峯作用。電商網站在進行促銷活動時,可以將用戶的訂單請求存入消息隊列,這樣可以抵禦大量的併發訂單請求對系統和數據庫的衝擊。目前,絕大多數的電商網站即便不進行促銷活動,訂單系統都採用了消息隊列來處理。
③ 使用集羣。
④ 代碼優化:
多線程:基於Java的Web開發基本上都通過多線程的方式響應用戶的併發請求,使用多線程技術在編程上要解決線程安全問題,主要可以考慮以下幾個方面:A. 將對象設計爲無狀態對象(這和麪向對象的編程觀點是矛盾的,在面向對象的世界中被視爲不良設計),這樣就不會存在併發訪問時對象狀態不一致的問題。B. 在方法內部創建對象,這樣對象由進入方法的線程創建,不會出現多個線程訪問同一對象的問題。使用ThreadLocal將對象與線程綁定也是很好的做法,這一點在前面已經探討過了。C. 對資源進行併發訪問時應當使用合理的鎖機制。
非阻塞I/O: 使用單線程和非阻塞I/O是目前公認的比多線程的方式更能充分發揮服務器性能的應用模式,基於Node.js構建的服務器就採用了這樣的方式。Java在JDK 1.4中就引入了NIO(Non-blocking I/O),在Servlet 3規範中又引入了異步Servlet的概念,這些都爲在服務器端採用非阻塞I/O提供了必要的基礎。
資源複用:資源複用主要有兩種方式,一是單例,二是對象池,我們使用的數據庫連接池、線程池都是對象池化技術,這是典型的用空間換取時間的策略,另一方面也實現對資源的複用,從而避免了不必要的創建和釋放資源所帶來的開銷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章