面試(六)

JVM的類加載機制是什麼?有哪些實現方式?

  • 類加載機制:javascript

類的加載指的是將類的.class文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,而後在堆區建立一個java.lang.Class對象,用來封裝在方法區內的數據結構。類的加載最終是在堆區內的Class對象,Class對象封裝了類在方法區內的數據結構,而且向Java程序員提供了訪問方法區內的數據結構的接口。html

  • 類加載有三種方式:

1)命令行啓動應用時候由JVM初始化加載前端

2)經過Class.forName()方法動態加載java

3)經過ClassLoader.loadClass()方法動態加載mysql

List 和 Set 的區別

1.List和Set都是接口繼承於Collection接口。程序員

2.最大的不一樣就是List是能夠重複的。而Set是不能重複的。(注意:元素雖然無放入順序,可是元素在set 中的位置是有該元素的HashCode決定的,其位置實際上是固定的) web

3.List接口有三個實現類:LinkedList,ArrayList,Vector ,Set接口有兩個實現類:HashSet(底層由HashMap實現),LinkedHashSet面試

4.List適合常常追加數據,插入,刪除數據。但隨機取數效率比較低。ajax

5.Set適合常常地隨機儲存,插入,刪除。可是在遍歷時效率比較低。redis

MVC模式完成分頁功能的基本思路是什麼?

1)頁面提交頁碼(第幾頁)到Servlet中

2)Servlet接收到頁碼後,將頁碼傳遞給分頁工具類(PageBean)

3)Servlet中調用Service層傳入PageBean對象

4)Service層調用DAO層傳入PageBean對象

5)Servlet中獲得查詢出來的數據,並setAttribute保存

6)在頁面中獲得(getAttribute)數據,遍歷輸出

MyBatis什麼狀況下用註解綁定,什麼狀況下用xml綁定?

當Sql語句比較簡單時候,用註解綁定;當SQL語句比較複雜時候,用xml綁定,通常用xml綁定的比較多

MyBatis實現一對一有幾種方式?具體怎麼操做的?

有聯合查詢和嵌套查詢

  • 聯合查詢:聯合查詢是幾個表聯合查詢,只查詢一次,經過在resultMap裏面配置association節點配置一對一的類就能夠完成;

  • 嵌套查詢:嵌套查詢是先查一個表,根據這個表裏面的結果的外鍵id,去再另一個表裏面查詢數據,也是經過association配置

MyBatis接口綁定有幾種實現方式,分別是怎麼實現的?

接口綁定有兩種實現方式:註解綁定和經過xml寫sql綁定

  • 註解綁定:就是在接口的方法上面加上@Select@Update等註解裏面包含Sql語句來綁定,

  • XML綁定:另一種就是經過xml裏面寫SQL來綁定,在這種狀況下,要指定xml映射文件裏面的namespace必須爲接口的全路徑名.

MyBatis的優點

  • MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎全部的JDBC代碼和參數的手工設置以及結果集的檢索。

  • MyBatis 使用簡單的 XML或註解用於配置和原始映射,將接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

MyBatis裏面的動態Sql是怎麼設定的?用什麼語法?

       MyBatis裏面的動態Sql通常是經過if節點來實現,經過OGNL語法來實現,可是若是要寫的完整,必須配合where,trim節點,where節點是判斷包含節點有內容就插入where,不然不插入,trim節點是用來判斷若是動態語句是以and 或or開始,那麼會自動把這個and或者or取掉。

MYSQL如何優化?結合你的經驗

1.數據庫的設計 (儘可能把數據庫設計的更小的佔磁盤空間.)

1).儘量使用更小的整數類型.(mediumint就比int更合適).

2).儘量的定義字段爲not null,除非這個字段須要null.

3).若是沒有用到變長字段的話好比varchar,那就採用固定大小的紀錄格式好比char.

4).表的主索引應該儘量的短.這樣的話每條紀錄都有名字標誌且更高效.

5).只建立確實須要的索引。索引有利於檢索記錄,可是不利於快速保存記錄。若是老是要在表的組合字段上作搜索,那麼就在這些字段上建立索引。索引的第一部分必須是最常使用的字段.若是老是須要用到不少字段,首先就應該多複製這些字段,使索引更好的壓縮。

6).全部數據都得在保存到數據庫前進行處理。

7).全部字段都得有默認值。

8).在某些狀況下,把一個頻繁掃描的表分紅兩個速度會快好多。在對動態格式表掃描以取得相關記錄時,它可能使用更小的靜態格式表的狀況下更是如此。

2.系統的用途

1).儘可能使用長鏈接.

2).explain 複雜的SQL語句。

3).若是兩個關聯表要作比較話,作比較的字段必須類型和長度都一致.

4).LIMIT語句儘可能要跟order by或者 distinct.這樣能夠避免作一次full table scan.

5).若是想要清空表的全部記錄,建議用truncate table tablename而不是delete from tablename.

6).能使用STORE PROCEDURE 或者 USER FUNCTION的時候.

7).在一條insert語句中採用多重紀錄插入格式.並且使用load data infile來導入大量數據,這比單純的indert快好多.

8).常常OPTIMIZE TABLE 來整理碎片.

9).還有就是date 類型的數據若是頻繁要作比較的話儘可能保存在unsigned int 類型比較快。

3.系統的瓶頸

1).磁盤搜索. 並行搜索,把數據分開存放到多個磁盤中,這樣能加快搜索時間.

2).磁盤讀寫(IO) 能夠從多個媒介中並行的讀取數據。

3).CPU週期 數據存放在主內存中.這樣就得增長CPU的個數來處理這些數據。

4).內存帶寬 當CPU要將更多的數據存放到CPU的緩存中來的話,內存的帶寬就成了瓶頸.

JSP的9個內置對象和4個域對象?

(1)9個內置對象:

①request:封裝客戶端的請求,其中包含來自GET或POST請求的參數;

②application:封裝服務器運行環境的對象;

③response:封裝服務器對客戶端的響應;

④session:封裝用戶會話的對象;

⑤page:JSP頁面自己(至關於Java程序中的this);

⑥config:Web應用的配置對象;

⑦exception:封裝頁面拋出異常的對象;

⑧pageContext:經過該對象能夠獲取其餘對象;

⑨out:用來傳送回應的輸出;

(2)4個域對象

①page(當前頁面)

②reques(一次請求)

③session( 一次會話)

④application(整個會話)

Maven的工程類型有哪些?

 

  • POM工程

POM工程是邏輯工程。用在父級工程或聚合工程中。用來作jar包的版本控制。

 

  • JAR工程

將會打包成jar用做jar包使用。即常見的本地工程 - Java Project。

  • WAR工程

 

將會打包成war,發佈在服務器上的工程。如網站或服務。即常見的網絡工程 - Dynamic Web Project。war工程默認沒有WEB-INF目錄及web.xml配置文件,IDE一般會顯示工程錯誤,提供完整工程結構能夠解決。

 

Maven經常使用命令有哪些?

  • install 本地安裝, 包含編譯,打包,安裝到本地倉庫

  • 編譯 - javac

  • 打包 - jar, 將java代碼打包爲jar文件 安裝到本地倉庫 - 將打包的jar文件,保存到本地倉庫目錄中。

  • clean 清除已編譯信息。 刪除工程中的target目錄。

  • compile 只編譯。 javac命令

  • deploy 部署。 常見於結合私服使用的命令。 至關因而install+上傳jar到私服。 包含編譯,打包,安裝到本地倉庫,上傳到私服倉庫。

  • package 打包。 包含編譯,打包兩個功能。

foreach的語句格式:

for(元素類型t 元素變量x : 遍歷對象obj){

引用了x的java語句;

}

面向對象都有哪些特性以及你對這些特性的理解

1)繼承:繼承是從已有類獲得繼承信息建立新類的過程。提供繼承信息的類被稱爲父類(超類、基類);獲得繼承信息的類被稱爲子類(派生類)。繼承讓變化中的軟件系統有了必定的延續性,同時繼承也是封裝程序中可變因素的重要手段。

2) 封裝:一般認爲封裝是把數據和操做數據的方法綁定起來,對數據的訪問只能經過已定義的接口。面向對象 的本質就是將現實世界描繪成一系列徹底自治、封閉的對象。咱們在類中編寫的方法就是對實現細節的一種封裝;我 們編寫一個類就是對數據和數據操做的封裝。能夠說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。

3) 多態性:多態性是指容許不一樣子類型的對象對同一消息做出不一樣的響應。簡單的說就是用一樣的對象引用調 用一樣的方法可是作了不一樣的事情。多態性分爲編譯時的多態性和運行時的多態性。方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。運行時的多態是面向對象最精髓的東西,要實現多態須要作 兩件事:

  1. 方法重寫(子類繼承父類並重寫父類中已有的或抽象的方法);

  2. 對象造型(用父類型引用引用子類型對 象,這樣一樣的引用調用一樣的方法就會根據子類對象的不一樣而表現出不一樣的行爲)。

4)抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行爲抽象兩方面。抽象只關注對 象有哪些屬性和行爲,並不關注這些行爲的細節是什麼。

String 類是 final 類,不能夠被繼承。

爲何函數不能根據返回類型來區分重載?

由於調用時不能指定類型信息,編譯器不知道你要調用哪一個函數。

char 型變量中能不能存儲一箇中文漢字,爲何?

char 類型能夠存儲一箇中文漢字,由於Java中使用的編碼是 Unicode,一個 char 類型佔 2 個字節(16 比特),因此放一箇中文是沒問題的。

抽象類(abstract class)和接口(interface)有什麼異同?

不一樣點:

抽象類:

1.抽象類中能夠定義構造器

2.能夠有抽象方法和具體方法

3.接口中的成員全都是public的

4.抽象類中能夠定義成員變量

5.有抽象方法的類必須被聲明爲抽象類,而抽象類未必要有抽象方法

6.抽象類中能夠包含靜態方法

7.一個類只能繼承一個抽象類

接口:

1.接口中不能定義構造器

2.方法所有都是抽象方法

3.抽象類中的成員能夠是 private、默認、protected、public

4.接口中定義的成員變量實際上都是常量

5.接口中不能有靜態方法

6.一個類能夠實現多個接口

相同:

1.不可以實例化

2.能夠將抽象類和接口類型做爲引用類型

3.一個類若是繼承了某個抽象類或者實現了某個接口都須要對其中的抽象方法所有進行實現,不然該類仍然須要被聲明爲抽象類

break和continue的區別?

break和continue都是用來控制循環的語句。 break用於徹底結束一個循環,跳出循環體執行循環後面的語句。 continue用於跳過本次循環,執行下次循環。

請寫出你最多見的5個RuntimeException

1)java.lang.NullPointerException 空指針異常;出現緣由:調用了未經初始化的對象或者是不存在的對象。

2)java.lang.ClassNotFoundException 指定的類找不到;出現緣由:類的名稱和路徑加載錯誤;一般都是程序 試圖經過字符串來加載某個類時可能引起異常。

3)java.lang.NumberFormatException 字符串轉換爲數字異常;出現緣由:字符型數據中包含非數字型字符。

4)java.lang.IndexOutOfBoundsException 數組角標越界異常,常見於操做數組對象時發生。

5)java.lang.IllegalArgumentException 方法傳遞參數錯誤。

6)java.lang.ClassCastException 數據類型轉換異常。

throw和throws的區別

throw:

1)throw語句用在方法體內,表示拋出異常,由方法體內的語句處理。

2)throw是具體向外拋出異常的動做,因此它拋出的是一個異常實例,執行throw必定是拋出了某種異常。

throws:

1)throws語句是用在方法聲明後面,表示若是拋出異常,由該方法的調用者來進行異常的處理。

2)throws主要是聲明這個方法會拋出某種類型的異常,讓它的使用者要知道須要捕獲的異常的類型。

3)throws表示出現異常的一種可能性,並不必定會發生這種異常。

final、finally、finalize的區別

1)final:用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,被其修飾的類不可繼承。

2)finally:異常處理語句結構的一部分,表示老是執行。

3)finalize:Object類的一個方法,在垃圾回收器執行的時候會調用被回收對象的此方法,能夠覆蓋此方法提供垃圾收集時的其餘資源回收,例如關閉文件等

Math.round(11.5)等於多少?Math.round(- 11.5) 又等於多少?

Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四捨五入的原理是在參數上加 0.5而後進行取整。

數組沒有 length()方法,而是有 length 的屬性。String 有 length()方法

short s1 = 1; s1 = s1 + 1; 有錯嗎?short s1 = 1; s1 += 1 有錯嗎;

前者不正確,後者正確。對於 short s1 = 1; s1 = s1 + 1;因爲1是 int 類型,所以 s1+1 運算結果也是 int 型, 須要強制轉換類型才能賦值給 short 型。而 short s1 = 1; s1 += 1;能夠正確編譯,由於 s1+= 1;至關於 s1 = (short)(s1 + 1);其中有隱含的強制類型轉換。

下面Integer類型的數值比較輸出的結果爲?

首先須要注意的是 f一、f二、f三、f4 四個變量都是 Integer 對象引用,因此下面的==運算比較的不是值而是引用。

若是整型字面量的值在-128 到 127 之間,那麼不會 new 新的 Integer 對象,而是直接引用常量池中的 Integer 對象,因此上面的面試題中 f1==f2 的結果是 true,而 f3==f4 的結果是 false。

String、StringBuffer、StringBuilder的區別?

(1)、可變不可變

String:字符串常量,在修改時不會改變自身;若修改,等於從新生成新的字符串對象。

StringBuffer:在修改時會改變對象自身,每次操做都是對StringBuffer對象自己進行修改,不是生成新的對象;使用場景:對字符串常常改變狀況下,主要方法:append(),insert()等。

2)、線程是否安全

String:對象定義後不可變,線程安全。

StringBuffer:是線程安全的(對調用方法加入同步鎖),執行效率較慢,適用於多線程下操做字符串緩衝區大量數據。

StringBuilder:是線程不安全的,適用於單線程下操做字符串緩衝區大量數據。

3)、共同點

StringBuilder與StringBuffer有公共父類AbstractStringBuilder(抽象類)。 StringBuilder、StringBuffer的方法都會調用AbstractStringBuilder中的公共方法,如super.append(...)。只是 StringBuffer 會在方法上加 synchronized 關鍵字,進行同步。最後,若是程序不是多線程的,那麼使用StringBuilder效率高於StringBuffer。

Java中有幾種類型的流

  • 按照流的方向:輸入流(inputStream)和輸出流(outputStream)。
  • 按照實現功能分:節點流和處理流。

節點流:能夠從或向一個特定的地方(節點)讀寫數據。如 FileReader

處理流:對一個已存在的流的鏈接和封裝,經過所封裝的流的功能調用實現數據讀寫。

  • 按照處理數據的單位:字節流和字符流。

字節流繼承於 InputStream 和 OutputStream,字符流繼承於InputStreamReader 和OutputStreamWriter。

字節流如何轉爲字符流

  • 字節輸入流轉字符輸入流經過InputStreamReader實現,該類的構造函數能夠傳入InputStream對象。

  • 字節輸出流轉字符輸出流經過OutputStreamWriter實現,該類的構造函數能夠傳入OutputStream對象。

如何將一個java對象序列化到文件裏

在java中可以被序列化的類必須先實現Serializable接口,該接口沒有任何抽象方法只是起到一個標記做用。

  1. //對象輸出流 
    ObjectOutputStream objectOutputStream =
        new ObjectOutputStream(new FileOutputStream(new File("D://obj")));
     objectOutputStream.writeObject(new User("zhangsan", 100)); 
        objectOutputStream.close();

     

  2. //對象輸入流 
    ObjectInputStream objectInputStream = 
      new ObjectInputStream(new FileInputStream(new File("D://obj"))); 
     User user = (User)objectInputStream.readObject(); 
       System.out.println(user); 
       objectInputStream.close();

字節流和字符流的區別

  • 字節流能夠處理全部類型數據,如:圖片,MP3,AVI 視頻文件,而字符流只能處理字符數據。

  • 只要是處理純文本數據,就要優先考慮使用字符流,除此以外都用字節流。

  • 字節流主要是操做 byte類型數據,以 byte 數組爲準,主要操做類就是OutputStream、 InputStream

  • 字符流處理的單元爲2個字節的Unicode字符,分別操做字符、字符數組或字符串,而字節流處理單元爲1個字節,操做字節和字節數組。

List的三個子類的特色

ArrayList 底層結構是數組,底層查詢快,增刪慢。

LinkedList 底層結構是鏈表型的,增刪快,查詢慢。

voctor 底層結構是數組 線程安全的,增刪慢,查詢慢。

List和Map、Set的區別

結構特色
  • List 和 Set 是存儲單列數據的集合,Map 是存儲鍵和值這樣的雙列數據的集合;
  • List 中存儲的數據是有順序,而且容許重複;
  • Map 中存儲的數據是沒有順序的,其鍵是不能重複的,它的值是能夠有重複的,Set 中存儲的數據是無序的,且不容許有重複,但元素在集合中的位置由元素的hashcode決定,位置是固定的
實現類
  • List接口有三個實現類(LinkedList:基於鏈表實現,鏈表內存是散亂的,每個元素存儲自己內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢;ArrayList:基於數組實現,非線程安全的,效率高,便於索引,但不便於插入刪除;Vector:基於數組實現,線程安全的,效率低)。

  • Map 接口有三個實現類(HashMap:基於 hash 表的 Map 接口實現,非線程安全,高效,支持 null 值和 null鍵;HashTable:線程安全,低效,不支持null值和null鍵;LinkedHashMap:是 HashMap的一個子類,保存了記錄的插入順序;SortMap接口:TreeMap,可以把它保存的記錄根據鍵排序,默認是鍵值的升序排序)。

  • Set 接口有兩個實現類(HashSet:底層是由 HashMap 實現,不容許集合中有重複的值,使用該方式時須要重寫 equals()和 hashCode()方法;LinkedHashSet:繼承與 HashSet,同時又基於 LinkedHashMap 來進行實現,底層使用的是LinkedHashMp)。

    區別
  • List 集合中對象按照索引位置排序,能夠有重複對象,容許按照對象在集合中的索引位置檢索對象,例如經過list.get(i)方法來獲取集合中的元素;

  • Map中的每個元素包含一個鍵和一個值,成對出現,鍵對象不能夠重複,值對象能夠重複;

  • Set集合中的對象不按照特定的方式排序,而且沒有重複對象,但它的實現類能對集合中的對象按照特定的方式排序,例如TreeSet類,能夠按照默認順序,也能夠經過實現Java.util.Comparator<Type>接口來自定義排序方式

數組和鏈表的區別

數組:數組是將元素在內存中連續存儲的

優勢:由於數據是連續存儲的,內存地址連續,因此在查找數據的時候效率比較高

缺點:在存儲以前,咱們須要申請一塊連續的內存空間,而且在編譯的時候就必須肯定好它的空間的大小。在運行的時候空間的大小是沒法隨着你的須要進行增長和減小而改變的,當數據兩比較的時候,有可能會出現越界的狀況,數據比較的時候,又有可能會浪費掉內存空間。在改變數據個數時,增長、插入、刪除數據效率比較低 。

鏈表:動態申請內存空間,不須要像數組須要提早申請好內存的大小

鏈表只需在用的時候申請就能夠,根據須要來動態申請或者刪除內存空間,對於數據增長和刪除以及插入比數組靈活。還有就是鏈表中數據在內存中能夠在任意的位置,經過應用來關聯數據(就是經過存在元素的指針來聯繫 。

List a=new ArrayList()和ArrayList a =new ArrayList()的區別?

List list = new ArrayList();這句建立了一個ArrayList的對象後把上溯到了List。此時它是一個List對象了,有些ArrayList 有可是 List 沒有的屬性和方法,它就不能再用了。

而 ArrayList list=new ArrayList();建立一對象則保留了ArrayList的全部屬性。 因此須要用到ArrayList獨有的方法的時候不能用前者。

要對集合更新操做時,ArrayList和LinkedList哪一個更適合?

1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。

2.若是集合數據是對於集合隨機訪問get和set,ArrayList絕對優於LinkedList,由於LinkedList要移動指針。

3.若是集合數據是對於集合新增和刪除操做 add 和 remove,LinedList 比較佔優點,由於 ArrayList 要移動數據。

多線程的建立方式

(1)、繼承 Thread類:但Thread本質上也是實現了Runnable 接口的一個實例,它表明一個線程的實例,而且,啓動線程的惟一方法就是經過 Thread 類的 start()實例方法。start()方法是一個 native 方法,它將啓動一個新線程,並執行run()方法。這種方式實現多線程很簡單,經過本身的類直接extend Thread,並複寫run()方法,就能夠啓動新線程並執行本身定義的run()方法。

(2)、實現Runnable接口的方式實現多線程,而且實例化Thread,傳入本身的Thread實例,調用run( )方法

在 java 中 wait 和 sleep 方法的不一樣?

最大的不一樣是在等待時wait會釋放鎖,而sleep一直持有鎖。wait一般被用於線程間交互,sleep一般被用於暫停執行。

synchronized 和 volatile 關鍵字的做用

1.volatile僅能使用在變量級別; synchronized則能夠使用在變量、方法、和類級別的

2.volatile僅能實現變量的修改可見性,並不能保證原子性; synchronized則能夠保證變量的修改可見性和原子性

3.volatile不會形成線程的阻塞; synchronized可能會形成線程的阻塞。

4.volatile標記的變量不會被編譯器優化; synchronized標記的變量能夠被編譯器優化

經常使用的線程池有哪些

newSingleThreadExecutor:建立一個單線程的線程池,此線程池保證全部任務的執行順序按照任務的提交順序執行。

newFixedThreadPool:建立固定大小的線程池,每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。

newCachedThreadPool:建立一個可緩存的線程池,此線程池不會對線程池大小作限制,線程池大小徹底依賴於操做系統(或者說JVM)可以建立的最大線程大小。

newScheduledThreadPool:建立一個大小無限的線程池,此線程池支持定時以及週期性執行任務的需求。

newSingleThreadExecutor:建立一個單線程的線程池。此線程池支持定時以及週期性執行任務的需求。

請敘述一下您對線程池的理解

(若是問到了這樣的問題,能夠展開的說一下線程池如何用、線程池的好處、線程池的啓動策略)

合理利用線程池可以帶來三個好處:

 第一:下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。

第二:提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。

第三:提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。

什麼是線程池,如何使用

線程池就是事先將多個線程對象放到一個容器中,當使用的時候就不用new線程而是直接去池中拿線程便可,節省了開闢子線程的時間,提升的代碼執行效率。 在JDK的java.util.concurrent.Executors中提供了生成多種線程池的靜態方法。

ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);

ScheduledExecutorService newScheduledThreadPool =Executors.newScheduledThreadPool

ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();

而後調用他們的 execute 方法便可。

線程池的啓動策略?

一、線程池剛建立時,裏面沒有一個線程。任務隊列是做爲參數傳進來的。不過,就算隊列裏面有任務,線程池也不會立刻執行它們。

二、當調用execute() 方法添加一個任務時,線程池會作以下判斷:

                a. 若是正在運行的線程數量小於 corePoolSize,那麼立刻建立線程運行這個任務;

                b. 若是正在運行的線程數量大於或等於 corePoolSize,那麼將這個任務放入隊列。

                c. 若是這時候隊列滿了,並且正在運行的線程數量小於 maximumPoolSize,那麼仍是要建立線程運行這個任務;

                d. 若是隊列滿了,並且正在運行的線程數量大於或等於 maximumPoolSize,那麼線程池會拋出異常,告訴調用者「我不能再接受任務了」。

三、當一個線程完成任務時,它會從隊列中取下一個任務來執行。

四、當一個線程無事可作,超過必定的時間(keepAliveTime)時,線程池會判斷,若是當前運行的線程數大於 corePoolSize,那麼這個線程就被停掉。因此線程池的全部任務完成後,它最終會收縮到 corePoolSize 的大小。

如何控制某個方法容許併發訪問線程的個數

能夠使用Semaphore控制

同一個類中的 2 個方法都加了同步鎖,多個線程能同時訪問同一個類中的這兩個方法嗎?

這個問題須要考慮到Lock與synchronized 兩種實現鎖的不一樣情形。

  • Lock可讓等待鎖的線程響應中斷,Lock獲取鎖,以後須要釋放鎖,多個線程不可 訪問同一個類中的2個加了Lock鎖的方法。

  • 使用synchronized時,當咱們訪問同一個類對象的時候,是同一把鎖,因此能夠訪問 該對象的其餘synchronized方法。

什麼狀況下致使線程死鎖,遇到線程死鎖該怎麼解決

  • 首先,死鎖的定義:所謂死鎖是指多個線程因競爭資源而形成的一種僵局(互相等待),若無外力做用,這些進程都將沒法向前推動。

  • 死鎖產生的必要條件:

互斥條件:線程要求對所分配的資源(如打印機)進行排他性控制,即在一段時間內某資源僅爲一個線程所佔有。此時如有其餘線程請求該資源,則請求線程只能等待。

不剝奪條件:線程所得到的資源在未使用完畢以前,不能被其餘線程強行奪走,即只能由得到該資源的線程本身來釋放(只能是主動釋放)。

請求和保持條件:線程已經保持了至少一個資源,但又提出了新的資源請求,而該資源已被其餘線程佔有,此時請求進程被阻塞,但對本身已得到的資源保持不放。

循環等待條件:存在一種線程資源的循環等待鏈,鏈中每個線程已得到的資源同時被鏈中下一個線程所請求。

  • 如何避免死鎖 :

1)加鎖順序(線程按照必定的順序加鎖)

2)加鎖時限(線程嘗試獲取鎖的時候加上必定的時限,超過期限則放棄對該鎖的請求,並釋放本身佔有的鎖)

Java 中多線程間的通訊怎麼實現?

線程通訊的方式:

1.共享變量 。線程間通訊能夠經過發送信號,發送信號的一個簡單方式是在共享對象的變量裏設置信號值。線程A在一個同步塊裏設置boolean型成員變量hasDataToProcess爲true,線程B也在同步塊裏讀取hasDataToProcess這個成員變量。

2.wait/notify機制 。以資源爲例,生產者生產一個資源,通知消費者就消費掉一個資源,生產者繼續生產資源,消費者消費資源,以此循環。

同步線程及線程調度相關的方法?

  • wait():使一個線程處於等待(阻塞)狀態,而且釋放所持有的對象的鎖; sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;

  • notify():喚醒一個處於等待狀態的線程,固然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且與優先級無關;

  • notityAll():喚醒全部處於等待狀態的線程,該方法並非將對象的鎖給全部線程,而是讓它們競爭,只有得到鎖 的線程才能進入就緒狀態;

啓動一個線程是調用 run()方法仍是 start()方法

啓動一個線程是調用 start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由 JVM 調度並執行,這並不意味着線程就會當即運行。 run()方法是線程啓動後要進行回調(callback)的方法

說說你對Java中反射的理解

Java 中的反射首先是可以獲取到 Java 中要反射類的字節碼,獲取字節碼有三種方法:

 1.Class.forName(className)

2.類名.class

3.this.getClass()。

而後將字節碼中的方法,變量,構造函數等映射成相應的Method、Filed、Constructor等類,這些類提供了豐富的方法能夠被咱們所使用

寫一個ArrayList的動態代理類(筆試題)

final List<String> list = new ArrayList<String>();

List<String> proxyInstance =(List<String>)Proxy.newProxyInstance(list.getClass().getClassLoader(),

list.getClass().getInterfaces(),

new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(list, args);

}

});

proxyInstance.add("你好");

System.out.println(list);

動靜態代理的區別,什麼場景使用

           靜態代理一般只代理一個類,動態代理是代理一個接口下的多個實現類。 靜態代理事先知道要代理的是什麼,而動態代理不知道要代理什麼東西,只有在運行時才知道。 動態代理是實現JDK裏的 InvocationHandler接口的 invoke方法,但注意的是代理的是接口,也就是你的業務類必需要實現接口,經過Proxy裏的newProxyInstance獲得代理對象。 還有一種動態代理 CGLIB,代理的是類,不須要業務類繼承接口,經過派生的子類來實現代理。經過在運行時,動態修改字節碼達到修改類的目的。 AOP編程就是基於動態代理實現的,好比著名的Spring框架、Hibernate框架等等都是動態代理的使用例子。

單例設計模式

最好理解的一種設計模式,分爲懶漢式和餓漢式。

懶漢式:

 

public class Singleton { 
 // 聲明變量 
   private static volatile Singleton singleton = null; 
 // 私有構造函數 
   private Singleton() { 
 }
// 提供對外方法 
   public static Singleton getInstance() { 
     if (singleton == null) { 
       synchronized (Singleton.class) { 
     if (singleton == null) {
       singleton = new Singleton();

      } 
   } 
 } 
 return singleton; 
 } 
}

 

 

餓漢式:

 

public class Singleton { 
// 直接建立對象 
  public static Singleton instance = new Singleton(); 
 // 私有化構造函數 
  private Singleton() { 
 } 
// 返回對象實例 
  public static Singleton getInstance() { 
    return instance; 
  } 
}

 

工廠設計模式

工廠模式分爲工廠方法模式和抽象工廠模式。

  • 工廠方法模式:

 

工廠方法模式分爲三種:

普通工廠模式,就是創建一個工廠類,對實現了同一接口的一些類進行實例的建立。

多個工廠方法模式,是對普通工廠方法模式的改進,在普通工廠方法模式中,若是傳遞的字符串出錯,則不能正確建立對象,而多個工廠方法模式是提供多個工廠方法,分別建立對象。

靜態工廠方法模式,將上面的多個工廠方法模式裏的方法置爲靜態的,不須要建立實例,直接調用便可。

 

  • 抽象工廠模式:

 

       工廠方法模式有一個問題就是,類的建立依賴工廠類,也就是說,若是想要拓展程序,必須對工廠類進行修改,這違背了閉包原則,因此,從設計角度考慮,有必定的問題,如何解決?就用到抽象工廠模式,建立多個工廠類,這樣一旦須要增長新的功能,直接增長新的工廠類就能夠了,不須要修改以前的代碼。

 

建造者模式

      工廠類模式提供的是建立單個類的模式,而建造者模式則是將各類產品集中起來進行管理,用來建立複合對象,所謂複合對象就是指某個類具備不一樣的屬性,其實建造者模式就是前面抽象工廠模式和最後的 Test 結合起來獲得的。

適配器設計模式

適配器模式將某個類的接口轉換成客戶端指望的另外一個接口表示,目的是消除因爲接口不匹配所形成的類的兼容性問題。主要分爲三類:類的適配器模式、對象的適配器模式、接口的適配器模式。

裝飾模式

裝飾模式就是給一個對象增長一些新的功能,並且是動態的,要求裝飾對象和被裝飾對象實現同一個接口,裝飾對象持有被裝飾對象的實例。

策略模式

       策略模式定義了一系列算法,並將每一個算法封裝起來,使他們能夠相互替換,且算法的變化不會影響到使用算法的客戶。須要設計一個接口,爲一系列實現類提供統一的方法,多個實現類實現該接口,設計一個抽象類(無關緊要,屬於輔助類),提供輔助函數。策略模式的決定權在用戶,系統自己提供不一樣算法的實現,新增或者刪除算法,對各類算法作封裝。所以,策略模式多用在算法決策系統中,外部用戶只須要決定用哪一個算法便可。

觀察者模式

      觀察者模式很好理解,相似於郵件訂閱和 RSS 訂閱,當咱們瀏覽一些博客或 wiki 時,常常會看到 RSS 圖標,就這的意思是,當你訂閱了該文章,若是後續有更新,會及時通知你。其實,簡單來說就一句話:當一個對象變化時,其它依賴該對象的對象都會收到通知,而且隨着變化!對象之間是一種一對多的關係。

java內存分配

一、基礎數據類型直接在空間分配;

二、方法的形式參數,直接在棧空間分配,當方法調用完成後從棧空間回收;

三、引用數據類型,須要用new來建立,既在棧空間分配一個地址空間,又在堆空間分配對象的類變量;

​四、方法的引用參數,在棧空間分配一個地址空間,並指向堆空間的對象區,當方法調用完後從棧空間回收;

五、局部變量 new 出來時,在棧空間和堆空間中分配空間,當局部變量生命週期結束後,棧空間馬上被回收,堆空間區域等待GC 回收;

六、方法調用時傳入的實際參數,先在棧空間分配,在方法調用完成後從棧空間釋放;

七、字符串常量在 DATA 區域分配 ,this 在堆空間分配;

八、數組既在棧空間分配數組名稱, 又在堆空間分配數組實際的大小

Java中引用類型都有哪些?(重要)

Java中對象的引用分爲四種級別,這四種級別由高到低依次爲:強引用、軟引用、弱引用和虛引用。

  • 強引用:若是一個對象被被人擁有強引用,那麼垃圾回收器毫不會回收它。當內存空間不足,Java 虛擬機寧願拋出 OutOfMemoryError 錯誤,使程序異常終止,也不會靠隨意回收具備強引用的對象來解決內存不足問題

  • 軟引用:若是一個對象只具備軟引用,那麼若是內存空間足夠,垃圾回收器就不會回收它,若是內存空間不足了,就會回收這些對象的內存。軟引用是主要用於內存敏感的高速緩存。在 jvm 報告內存不足以前會清除全部的軟引用,這樣以來 gc 就有可能收集軟可及的對象,可能解決內存吃緊問題,避免內存溢出。

  • 弱引用:若是一個對象只具備弱引用,那該類就是無關緊要的對象,由於只要該對象被 gc 掃描到了隨時都會把它幹掉。弱引用與軟引用的區別在於:只具備弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器是一個優先級很低的線程, 所以不必定會很快發現那些只具備弱引用的對象。

  • 虛引用:"虛引用"顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收。虛引用主要用來跟蹤對象被垃圾回收的活動。 虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之關聯的引用隊列中。程序能夠經過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。程序若是發現某個虛引用已經被加入到引用隊列,那麼就能夠在所引用的對象的內存被回收以前採起必要的行動。

heap(堆)和stack(棧)有什麼區別

  1. 申請方式

    stack:由系統自動分配。

heap:須要程序員本身申請,並指明大小。

  1. 申請後系統的響應

stack:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,不然將報異常提示棧溢出。

heap:首先應該知道操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時, 會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序。另外,因爲找到的堆結點的大小不必定正好等於申請的大小,系統會自動的將多餘的那部分從新放入空閒鏈表中。

        3.申請大小的限制

stack:棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,若是申請的空間超過棧的剩餘空間時,將提示overflow。所以,能從棧得到的空間較小。

heap:堆是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。

  1. 申請效率的比較

 

stack:由系統自動分配,速度較快。但程序員是沒法控制的。

heap:由new分配的內存,通常速度比較慢,並且容易產生內存碎片,不過用起來最方便。

 

  1. heap和stack中的存儲內容

stack: 在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址,而後是函數的各個參數,當本次函數調用結束後,局部變量先出棧,而後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。

heap:通常是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。

  1. 數據結構層面的區別

這裏的堆實際上指的就是(知足堆性質的)優先隊列的一種數據結構,第1個元素有最高的優先權;棧實際上就是知足先進後出的性質的數學或數據結構。

解釋內存中的棧 (stack) 、堆 (heap) 和方法區 (method area) 的用法

           一般咱們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用 JVM 中的棧空間;而經過new關鍵字和構造器建立的對象則放在堆空間,堆是垃圾收集器管理的主要區域,因爲如今的垃圾收集器都採用分代收集算法,因此堆空間還能夠細分爲新生代和老生代,再具體一點能夠分爲 Eden、Survivor(又可分爲 From Survivor 和 To Survivor、Tenured;方法區和堆都是各個線程共享的內存區域,用於存儲已經被JVM加載的類信息、常量、靜態變量、JIT 編譯器編譯後的代碼等數據;程序中的字面量(literal)如直接書寫的 100、"hello"和常量都是放在常量池中,常量池是方法區的一部分。棧空間操做起來最快可是棧很小,一般大量的對象都是放在堆空間,棧和堆的大小均可以經過 JVM 的啓動參數來進行調整,棧空間用光了會引起 StackOverflowError,而堆和常量池空間不足則會引起 OutOfMemoryError。 String str = new String("hello"); 上面的語句中變量 str 放在棧上,用 new 建立出來的字符串對象放在堆上,而"hello"這個字面量是放在方法區 的。

Java的類加載器的種類都有哪些?

一、根類加載器(Bootstrap) --C++寫的 ,看不到源碼

二、擴展類加載器(Extension) --加載位置 :jre\lib\ext中

三、系統(應用)類加載器(System\App) --加載位置 :classpath中

四、自定義加載器(必須繼承ClassLoader)

類何時被初始化?

1)建立類的實例,也就是new一個對象

2)訪問某個類或接口的靜態變量,或者對該靜態變量賦值

3)調用類的靜態方法

4)反射(Class.forName("com.lyj.load"))

5)初始化一個類的子類(會首先初始化子類的父類)

6)JVM啓動時標明的啓動類,即文件名和類名相同的那個類

只有這6中狀況纔會致使類的類的初始化。

類的初始化步驟:

1)若是這個類尚未被加載和連接,那先進行加載和連接

2)假如這個類存在直接父類,而且這個類尚未被初始化(注意:在一個類加載器中,類只能初始化一次),那就初始化直接的父類(不適用於接口)

3)假如類中存在初始化語句(如static變量和static塊),那就依次執行這些初始化語句。

java 是一種類型安全的語言,它有四類稱爲安全沙箱機制的安全機制來保證語言的安全性,這四類安全沙箱分別是:

1) 類加載體系

2) .class文件檢驗器

3) 內置於Java虛擬機(及語言)的安全特性

4) 安全管理器及Java API

類的加載體系:

 

java程序中的 .java文件編譯完會生成 .class文件,而 .class文件就是經過被稱爲類加載器的ClassLoader加載的,而ClassLoder在加載過程當中會使用「雙親委派機制」來加載 .class文件。

前面談到了ClassLoader的幾類加載器,而ClassLoader使用雙親委派機制來加載class文件的。ClassLoader的雙親委派機制是這樣的(這裏先忽略掉自定義類加載器CustomClassLoader):

1)當 AppClassLoader加載一個class時,它首先不會本身去嘗試加載這個類,而是把類加載請求委派給父類加載器ExtClassLoader去完成。

2)當 ExtClassLoader 加載一個 class 時,它首先也不會本身去嘗試加載這個類,而是把類加載請求委派給BootStrapClassLoader去完成。

3)若是 BootStrapClassLoader 加載失敗(例如在$JAVA_HOME$/jre/lib 裏未查找到該 class),會使用ExtClassLoader來嘗試加載;

4)若 ExtClassLoader也加載失敗,則會使用AppClassLoader來加載,若是AppClassLoader也加載失敗,則會報出異常ClassNotFoundException。

描述一下JVM加載class

JVM 中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java 中的類加載器是一個重要的 Java 運行時系統組件,它負責在運行時查找和裝入類文件中的類。

因爲 Java 的跨平臺性,通過編譯的 Java 源程序並非一個可執行程序,而是一個或多個類文件。當 Java 程序須要使用某個類時,JVM 會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。類的加載是指把類的.class 文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class 文件,而後產生與所加載類對應的 Class 對象。加載完成後,Class 對象還不完整,因此此時的類還不可用。當類被加載後就進入鏈接階段,這一階段包括驗證、準備 (爲靜態變量分配內存並設置默認的初始值)和解析(將符號引用替換爲直接引用)三個步驟。最後 JVM 對類進行初始化,包括: 若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類; 若是類中存在初始化語句,就依次執行這些初始化語句。

類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader 的子類)。

得到一個類對象有哪些方式

  • 類型.class,例如:String.class
  • 對象.getClass(),例如:」hello」.getClass()
  • Class.forName(),例如:Class.forName(「java.lang.String」)

既然有GC機制,爲何還會有內存泄露的狀況

      理論上 Java 由於有垃圾回收機制(GC)不會存在內存泄露問題(這也是 Java 被普遍使用於服務器端編程的一個重要緣由)。然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被 GC 回收,所以也會致使內存泄露的發生。

例如 hibernate 的 Session(一級緩存)中的對象屬於持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,若是不及時關閉(close)或清空(flush)一級緩存就可能致使內存泄露。

Java中爲何會有GC機制呢?

• 安全性考慮;

• 減小內存泄露;

• 減小程序員工做量。

對於Java的GC哪些內存須要回收

 

            內存運行時 JVM 會有一個運行時數據區來管理內存。它主要包括 5 大部分:程序計數器、虛擬機棧、本地方法棧、方法區、堆. 而其中程序計數器、虛擬機棧、本地方法棧是每一個線程私有的內存空間,隨線程而生,隨線程而亡。例如棧中每個棧幀中分配多少內存基本上在類結構肯定是哪一個時就已知了,所以這 3 個區域的內存分配和回收都是肯定的,無需考慮內存回收的問題。 但方法區和堆就不一樣了,一個接口的多個實現類須要的內存可能不同,咱們只有在程序運行期間纔會知道會創 建哪些對象,這部份內存的分配和回收都是動態的,GC主要關注的是這部份內存。 總而言之,GC 主要進行回收的內存是JVM中的方法區和堆;

 

Java的GC何時回收垃圾(如何判斷一個對象已經死去)

 

     在Java,C#等語言中,比較主流的斷定一個對象已死的方法是:可達性分析(Reachability Analysis). 全部生成的對象都是一個稱爲"GC Roots"的根的子樹。從 GC Roots 開始向下搜索,搜索所通過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈能夠到達時,就稱這個對象是不可達的(不可引用的),也就是能夠被GC 回收了。 不管是引用計數器仍是可達性分析,斷定對象是否存活都與引用有關!那麼,如何定義對象的引用呢?

 

     咱們但願給出這樣一類描述:當內存空間還夠時,可以保存在內存中;若是進行了垃圾回收以後內存空間仍舊很是緊張,則能夠拋棄這些對象。因此根據不一樣的需求,給出以下四種引用,根據引用類型的不一樣,GC回收時也會有不一樣的操做:

1)強引用(Strong Reference):Object obj = new Object();只要強引用還存在,GC永遠不會回收掉被引用的對象。

2)軟引用(Soft Reference):描述一些還有用但非必需的對象。在系統將會發生內存溢出以前,會把這些對象列入回收範圍進行二次回收(即系統將會發生內存溢出了,纔會對他們進行回收。

3)弱引用(Weak Reference):程度比軟引用還要弱一些。這些對象只能生存到下次GC以前。當GC 工做時,不管內存是否足夠都會將其回收(即只要進行GC,就會對他們進行回收。

4)虛引用(Phantom Reference):一個對象是否存在虛引用,徹底不會對其生存時間構成影響。

  • 關於方法區中須要回收的是一些廢棄的常量和無用的類。

1.廢棄的常量的回收。這裏看引用計數就能夠了。沒有對象引用該常量就能夠放心的回收了。

2.無用的類的回收。什麼是無用的類呢? A.該類全部的實例都已經被回收。也就是Java堆中不存在該類的任何實例; B.加載該類的ClassLoader已經被回收; C.該類對應的java.lang.Class對象沒有任何地方被引用,沒法在任何地方經過反射訪問該類的方法。

總而言之: 對於堆中的對象,主要用可達性分析判斷一個對象是否還存在引用,若是該對象沒有任何引用就應該被回收。而根據咱們實際對引用的不一樣需求,又分紅了4中引用,每種引用的回收機制也是不一樣的。 對於方法區中的常量和類,當一個常量沒有任何對象引用它,它就能夠被回收了。而對於類,若是能夠斷定它爲無用類,就能夠被回收了。

Java8中的lambda表達式要點

要點1:lambda表達式的使用位置

預約義使用了 @Functional 註釋的函數式接口,自帶一個抽象函數的方法,或者SAM(Single Abstract Method 單個抽象方法)類型。這些稱爲lambda表達式的目標類型,能夠用做返回類型,或lambda目標代碼的參數。

要點2:lambda表達式和方法引用

lambda 表達式內能夠使用方法引用,僅當該方法不修改 lambda 表達式提供的參數。

若對參數有任何修改,則不能使用方法引用,而需鍵入完整地lambda表達式

要點3:lambda表達式內部引用資源

lambda內部能夠使用靜態、非靜態和局部變量,這稱爲lambda內的變量捕獲。

要點4:lambda表達式也稱閉包

Lambda表達式在Java中又稱爲閉包或匿名函數,因此若是有同事把它叫閉包的時候,不用驚訝。

要點5:lambda表達式的編譯方式

Lambda方法在編譯器內部被翻譯成私有方法,並派發 invokedynamic 字節碼指令來進行調用。能夠使用JDK中的 javap 工具來反編譯class文件。使用 javap -p 或 javap -c -v 命令來看一看lambda表達式生成的字節碼。

要點6:lambda表達式的限制

lambda 表達式有個限制,那就是隻能引用 final 或 final 局部變量,這就是說不能在 lambda 內部修改定義在域外的變量。

在開發中遇到過內存溢出麼?緣由有哪些?解決方法有哪些?

引發內存溢出的緣由有不少種,常見的有如下幾種:

1.內存中加載的數據量過於龐大,如一次從數據庫取出過多數據;

2.集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;

3.代碼中存在死循環或循環產生過多重複的對象實體;

4.使用的第三方軟件中的BUG; 5.啓動參數內存值設定的太小;

內存溢出的解決方案:

  • 第一步,修改JVM啓動參數,直接增長內存。(-Xms,-Xmx參數必定不要忘記加。)

  • 第二步,檢查錯誤日誌,查看「OutOfMemory」錯誤前是否有其它異常或錯誤。

  • 第三步,對代碼進行走查和分析,找出可能發生內存溢出的位置。

重點排查如下幾點:

1.檢查對數據庫查詢中,是否有一次得到所有數據的查詢。通常來講,若是一次取十萬條記錄到內存,就可能引發內存溢出。這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,上線後,數據庫中數據多了,一次查詢就有可能引發內存溢出。所以對於數據庫查詢儘可能採用分頁的方式查詢。

2.檢查代碼中是否有死循環或遞歸調用。

3.檢查是否有大循環重複產生新對象實體

4.檢查List、MAP等集合對象是否有使用完後,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收

  • 第四步,使用內存查看工具動態查看內存使用狀況。

說下原生jdbc操做數據庫流程?

第一步:加載驅動 Class.forName()

第二步:鏈接數據庫

第三步:獲取statement對象

第四步:執行sql語句

第五步:關閉數據庫

什麼要使用PreparedStatement?

一、 PreparedStatement接口繼承Statement, PreparedStatement 實例包含已編譯的 SQL 語句,因此其執行速度要於 Statement 對象。

2 、 做 爲 Statement 的 子 類 , PreparedStatement 繼承了 Statement 的 所 有 功 能 。

三、在 JDBC應用中,在任什麼時候候都不要使用Statement,緣由以下:

1、代碼的可讀性和可維護性:Statement須要不斷地拼接,而PreparedStatement不會。

2、PreparedStatement盡最大可能提升性能:DB有緩存機制,相同的預編譯語句再次被調用不會再次須要編譯。

3、最重要的一點是極大地提升了安全性:Statement 容易被 SQL 注入,而 PreparedStatementc 傳入的內容不會和sql語句發生任何匹配關係。

關係數據庫中鏈接池的機制是什麼?

前提:爲數據庫鏈接創建一個緩衝池。

1:從鏈接池獲取或建立可用鏈接

2:使用完畢以後,把鏈接返回給鏈接池

3:在系統關閉前,斷開全部鏈接並釋放鏈接佔用的系統資源

4:可以處理無效鏈接,限制鏈接池中的鏈接總數不低於或者不超過某個限定值。

其中有幾個概念須要你們理解: 最小鏈接數是鏈接池一直保持的數據鏈接。若是應用程序對數據庫鏈接的使用量不大,將會有大量的數據庫鏈接資源被浪費掉。 最大鏈接數是鏈接池能申請的最大鏈接數。若是數據鏈接請求超過此數,後面的數據鏈接請求將被加入到等待隊列中,這會影響以後的數據庫操做。

綜上所述:數據庫池鏈接數量一直保持一個很多於最小鏈接數的數量,當數量不夠時,數據庫會建立一些鏈接,直到一個最大鏈接數,以後鏈接數據庫就會等待。

http常見的狀態碼有哪些

200 OK //客戶端請求成功

301 Moved Permanently(永久移除),請求的URL已移走。Response中應該包含一個Location URL, 說明資源如今所處的位置

302 found 重定向

400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解

401 Unauthorized //請求未經受權,這個狀態代碼必須和WWW-Authenticate報頭域一塊兒使用

403 Forbidden //服務器收到請求,可是拒絕提供服務

404 Not Found //請求資源不存在,eg:輸入了錯誤的URL 500 Internal Server Error //服務器發生不可預期的錯誤

503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常

GET請求的數據會附在URL以後(就是把數據放置在HTTP協議頭中),以?分割URL和傳輸數據,參數之間以&相連,如:login.action?name=zhagnsan&password=123456。POST把提交的數據則放置在是HTTP包的包體中

http中重定向和請求轉發的區別

本質區別:轉發是服務器行爲,重定向是客戶端行爲。

重定向特色:兩次請求,瀏覽器地址發生變化,能夠訪問本身web以外的資源,傳輸的數據會丟失。

請求轉發特色:一次強求,瀏覽器地址不變,訪問的是本身自己的web資源,傳輸的數據不會丟失。

Cookie和Session的區別

Cookie 是 web 服務器發送給瀏覽器的一塊信息,瀏覽器會在本地一個文件中給每一個 web 服務器存儲 cookie。之後瀏覽器再給特定的web服務器發送請求時,同時會發送全部爲該服務器存儲的cookie。 Session 是存儲在 web 服務器端的一塊信息。session 對象存儲特定用戶會話所需的屬性及配置信息。當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。

Cookie和session的不一樣點:

一、不管客戶端作怎樣的設置,session都可以正常工做。當客戶端禁用cookie時將沒法使用cookie。

二、在存儲的數據量方面:session可以存儲任意的java對象,cookie只能存儲String類型的對象。

session共享怎麼作的(分佈式如何實現session共享)

一、服務器實現的session複製或session共享,這類型的共享session是和服務器緊密相關的,好比webSphere或JBOSS在搭建集羣時候能夠配置實現session複製或session共享,可是這種方式有一個致命的缺點,就是很差擴展和移植,好比咱們更換服務器,那麼就要修改服務器配置。

二、利用成熟的技術作session複製,好比12306使用的gemfire,好比常見的內存數據庫如redis或memorycache,這類方案雖然比較普適,可是嚴重依賴於第三方,這樣當第三方服務器出現問題的時候,那麼將是應用的災難。

三、將 session維護在客戶端,很容易想到就是利用cookie,可是客戶端存在風險,數據不安全,並且能夠存放的數據量比較小,因此將session維護在客戶端還要對session中的信息加密。

         咱們實現的方案能夠說是第二種方案和第三種方案的合體,能夠利用 gemfire 實現 session 複製共享,還能夠將session維護在redis中實現session共享,同時能夠將session維護在客戶端的cookie中,可是前提是數據要加密。 這三種方式能夠迅速切換,而不影響應用正常執行。咱們在實踐中,首選 gemfire 或者 redis 做爲 session 共享的載體,一旦session不穩定出現問題的時候,能夠緊急切換cookie維護session做爲備用,不影響應用提供服務。

在單點登陸中,若是cookie被禁用了怎麼辦

      單點登陸的原理是後端生成一個 session ID,而後設置到 cookie,後面的全部請求瀏覽器都會帶上 cookie,而後服務端從 cookie 裏獲取 session ID,再查詢到用戶信息。因此,保持登陸的關鍵不是 cookie,而是經過 cookie 保存和傳輸的 session ID,其本質是能獲取用戶信息的數據。除了 cookie,還一般使用 HTTP 請求頭來傳輸。可是這個請求頭瀏覽器不會像 cookie 同樣自動攜帶,須要手工處理。

什麼是jsp,什麼是Servlet?jsp和Servlet有什麼區別?

     jsp本質上就是一個Servlet,它是Servlet的一種特殊形式 ,每一個jsp頁面都是一個servlet實例。 Servlet是由 Java提供用於開發 web服務器應用程序的一個組件,運行在服務端,由servlet 容器管理,用來生成動態內容。一個 servlet 實例是實現了特殊接口 Servlet 的 Java 類,全部自定義的 servlet 均必須實現 Servlet 接口。 區別: jsp是html頁面中內嵌的Java代碼,側重頁面顯示; Servlet是html代碼和Java代碼分離,側重邏輯控制,mvc設計思想中jsp位於視圖層,servlet位於控制層。

Jsp運行機制:以下圖

 

 

 

 

   JVM 只能識別 Java 類,並不能識別 jsp 代碼!web 容器收到以.jsp 爲擴展名的 url 請求時,會將訪問請求交給tomcat 中 jsp 引擎處理,每一個 jsp 頁面第一次被訪問時,jsp 引擎將 jsp 代碼解釋爲一個 servlet 源程序,接着編譯servlet源程序生成.class文件,再有web容器servlet引擎去裝載執行servlet程序,實現頁面交互。

jsp有哪些域對象和內置對象及他們的做用

   四大域對象:

(1)pageContext page域-指當前頁面,在當前jsp頁面有效,跳到其它頁面失效

(2)request request域-指一次請求範圍內有效,從http請求到服務器處理結束,返回響應的整個過程。在這個過程當中使用forward(請求轉發)方式跳轉多個jsp,在這些頁面裏你均可以使用這個變量

(3)session session域-指當前會話有效範圍,瀏覽器從打開到關閉過程當中,轉發、重定向都可以使用

(4)application context域-指只能在同一個web中使用,服務器未關閉或者重啓,數據就有效

九大內置對象:

什麼是xml,使用xml的優缺點,xml的解析器有哪幾種,分別有什麼區別?

  • xml是一種可擴展性標記語言,支持自定義標籤(使用前必須預約義)使用DTD和XML Schema標準化XML結構。

  • 優勢:用於配置文件,格式統一,符合標準;用於在互不兼容的系統間交互數據,共享數據方便;

  • 缺點:xml文件格式複雜,數據傳輸佔流量,服務端和客戶端解析xml文件佔用大量資源且不易維護

Xml經常使用解析器有2種,分別是:DOM和SAX; 主要區別在於它們解析xml文檔的方式不一樣。使用DOM解析,xml文檔以DOM 樹形結構加載入內存,而SAX採用的是事件模型

談談你對ajax的認識?

Ajax是一種建立交互式網頁應用的的網頁開發技術

Ajax的優點: 經過異步模式,提高了用戶體驗。 優化了瀏覽器和服務器之間的傳輸,減小沒必要要的數據往返,減小了帶寬佔用。 Ajax引擎在客戶端運行,承擔了一部分原本由服務器承擔的工做,從而減小了大用戶量下的服務器負載。 Ajax的最大特色: 能夠實現局部刷新,在不更新整個頁面的前提下維護數據,提高用戶體驗度。

jsonp原理

      JavaScript是一種在Web開發中常用的前端動態腳本技術。在JavaScript中,有一個很重要的安全性限制,被稱爲「Same-Origin Policy」(同源策略)。這一策略對於JavaScript代碼可以訪問的頁面內容作了很重要的限制,即JavaScript只能訪問與包含它的文檔在同一域下的內容。 JavaScript 這個安全策略在進行多 iframe 或多窗口編程、以及 Ajax 編程時顯得尤其重要。根據這個策略,在 baidu.com 下的頁面中包含的 JavaScript 代碼,不能訪問在 google.com 域名下的頁面內容;甚至不一樣的子域名之間的頁面也不能經過 JavaScript 代碼互相訪問。對於 Ajax 的影響在於,經過 XMLHttpRequest 實現的Ajax 請求,不能向不一樣的域提交請求,例如,在 abc.example.com 下的頁面,不能向 def.example.com 提交Ajax請求,等等。 然而,當進行一些比較深刻的前端編程的時候,不可避免地須要進行跨域操做,這時候「同源策略」就顯得過於苛刻。JSONP跨域GET請求是一個經常使用的解決方案,下面咱們來看一下JSONP跨域是如何實現的,而且探討下JSONP跨域的原理。 jsonp 的最基本的原理是:動態添加一個<script>標籤,使用 script 標籤的 src 屬性沒有跨域的限制的特色實現跨域。首先在客戶端註冊一個 callback, 而後把 callback 的名字傳給服務器。此時,服務器先生成 json 數據。 而後以 javascript 語法的方式,生成一個 function , function 名字就是傳遞上來的參數 jsonp。最後將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。 客戶端瀏覽器,解析script標籤,並執行返回的 javascript 文檔,此時數據做爲參數,傳入到了客戶端預先定義 好的 callback 函數裏。

說一下經常使用的Linux命令

列出文件列表:ls 【參數 -a -l】

建立目錄和移除目錄:mkdir rmdir

用於顯示文件後幾行內容:tail

打包:tar -xvf

打包並壓縮:tar -zcvf

查找字符串:grep

顯示當前所在目錄:pwd

建立空文件:touch

編輯器:vim vi

Linux中如何查看日誌?

動態打印日誌信息:tail –f 日誌文件

Linux怎麼關閉進程

一般用ps 查看進程PID ,用kill命令終止進程。

ps 命令用於查看當前正在運行的進程。 grep 是搜索 例如: ps -ef | grep java 表示查看全部進程裏CMD是java的進程信息。 ps -aux | grep java -aux 顯示全部狀態 kill 命令用於終止進程。 例如: kill -9 [PID]

-9表示強迫進程當即中止。

事務的四大特徵是什麼?

數據庫事務transanction正確執行的四個基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔離性(Isolation)、持久性(Durability)。

(1)原子性:整個事務中的全部操做,要麼所有完成,要麼所有不完成,不可能停滯在中間某個環節。事務在執行過程當中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。

(2)一致性:在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞。

(3)隔離性:隔離狀態執行事務,使它們好像是系統在給定時間內執行的惟一操做。若是有兩個事務,運行在相同的時間內,執行 相同的功能,事務的隔離性將確保每一事務在系統中認爲只有該事務在使用系統。這種屬性有時稱爲串行化,爲了防止事務操做間的混淆, 必須串行化或序列化請 求,使得在同一時間僅有一個請求用於同一數據。

(4)持久性:在事務完成之後,該事務所對數據庫所做的更改便持久的保存在數據庫之中,並不會被回滾。

Mysql 中四種隔離級別分別是什麼

讀未提交(READ UNCOMMITTED):未提交讀隔離級別也叫讀髒,就是事務能夠讀取其它事務未提交的數據。

讀已提交(READ COMMITTED):在其它數據庫系統好比SQL Server默認的隔離級別就是提交讀,已提交讀隔離級別就是在事務未提交以前所作的修改其它事務是不可見的。

可重複讀(REPEATABLE READ):保證同一個事務中的屢次相同的查詢的結果是一致的,好比一個事務一開始查詢了一條記錄而後過了幾秒鐘又執行了相同的查詢,保證兩次查詢的結果是相同的,可重複讀也是mysql的默認隔離級別。

可串行化(SERIALIZABLE):可串行化就是保證讀取的範圍內沒有新的數據插入,好比事務第一次查詢獲得某個範圍的數據,第二次查詢也一樣獲得了相同範圍的數據,中間沒有新的數據插入到該範圍中。

MySQL怎麼建立存儲過程

1、建立MySQL存儲過程 下面代碼建立了一個叫pr_add 的MySQL 存儲過程,這個MySQL 存儲過程有兩個int 類型的輸入參數 「a」、 「b」,返回這兩個參數的和。

1)drop procedure if exists pr_add; (備註:若是存在pr_add的存儲過程,則先刪掉)

2)計算兩個數之和(備註:實現計算兩個整數之和的功能)

create procedure pr_add ( a int, b int ) begin declare c int;

if a is null then set a = 0;

end if; if b is null then set b = 0;

end if;

set c = a + b;

select c as sum;

2、調用 MySQL 存儲過程

call pr_add(10, 20);

MySQL觸發器怎麼寫

MySQL包含對觸發器的支持。觸發器是一種與表操做有關的數據庫對象,當觸發器所在表上出現指定事件時,將 調用該對象,即表的操做事件觸發表上的觸發器的執行。 在MySQL中,建立觸發器語法以下:

CREATE TRIGGER trigger_name

trigger_time

trigger_event ON tbl_name

FOR EACH ROW

trigger_stmt 

其中:

trigger_name:標識觸發器名稱,用戶自行指定;

trigger_time:標識觸發時機,取值爲 BEFORE 或 AFTER;

trigger_event:標識觸發事件,取值爲 INSERT、UPDATE 或 DELETE;

tbl_name:標識創建觸發器的表名,即在哪張表上創建觸發器;

trigger_stmt:觸發器程序體,能夠是一句SQL語句,或者用 BEGIN 和 END 包含的多條語句。

因而可知,能夠創建6種觸發器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE

另外有一個限制是不能同時在一個表上創建2個相同類型的觸發器,所以在一個表上最多創建6個觸發器。

什麼是存儲過程,使用存儲過程的好處

       存儲過程(Stored Procedure )是一組爲了完成特定功能的SQL 語句集,經編譯後存儲在數據庫中。用戶經過指定存儲過程的名字並給出參數(若是該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。

優勢:

(1)容許模塊化程序設計,就是說只須要建立一次過程,之後在程序中就能夠調用該過程任意次。

(2)容許更快執行,若是某操做須要執行大量 SQL 語句或重複執行,存儲過程比 SQL 語句執行的要快。

(3)減小網絡流量,例如一個須要數百行的 SQL 代碼的操做有一條執行語句完成,不須要在網絡中發 送數百行代碼。

(4) 更好的安全機制,對於沒有權限執行存儲過程的用戶,也可受權他們執行存儲過程。

Oracle中字符串用什麼鏈接

Oracle中使用 || 這個符號鏈接字符串 如 ‘abc’ || ‘d’ 的結果是abcd。

Oracle中是如何進行分頁查詢的

Oracle 中使用rownum來進行分頁, 這個是效率最好的分頁方法,hibernate 也是使用 rownum 來進行Oralce分頁的

select * from

( select rownum r,a from tabName where rownum <= 20 )

where r > 10

Oracle存儲過程與SQL的對比?

優點:

一、提升性能

二、下降網絡開銷

三、便於進行代碼移植

四、更強的安全性

劣勢:

一、存儲過程須要專門的數據庫開發人員進行維護,但實際狀況是,每每由程序開發員人員兼職

二、設計邏輯變動,修改存儲過程沒有SQL靈活

你以爲存儲過程和SQL語句該使用哪一個?

一、在一些高效率或者規範性要求比較高的項目,建議採用存儲過程

二、對於通常項目建議採用參數化命令方式,是存儲過程與SQL語句一種折中的方式

三、對於一些算法要求比較高,涉及多條數據邏輯,建議採用存儲過程

Oracle觸發器的做用有哪些

1)觸發器可經過數據庫中的相關表實現級聯更改;經過級聯引用完整性約束能夠更有效地執行這些更改。

2)觸發器能夠強制比用 CHECK 約束定義的約束更爲複雜的約束。與 CHECK 約束不一樣,觸發器能夠引用其它表中的列。例如,觸發器能夠使用另外一個表中的 SELECT 比較插入或更新的數據,以及執行其它操做,如修改數據或顯示用戶定義錯誤信息。

3)觸發器還能夠強制執行業務規則

4)觸發器也能夠評估數據修改先後的表狀態,並根據其差別採起對策。

在千萬級的數據庫查詢中,如何提升效率?

1)數據庫設計方面

a. 對查詢進行優化,應儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。

b. 應儘可能避免在 where 子句中對字段進行 null 值判斷, 能夠在num上設置默認值0,確保表中num列沒有null值

c. 索引並非越多越好

d. 應儘量的避免更新索引數據列

e. 儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型

f. 儘可能使用表變量來代替臨時表

g. 避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。

h. 在新建臨時表時,若是一次性插入數據量很大,那麼能夠使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。

i. 若是使用到了臨時表,在存儲過程的最後務必將全部的臨時表顯式刪除,先 truncate table ,而後 drop table ,這樣能夠避免系統表的較長時間鎖定。

2)SQL語句方面

a. 應儘可能避免在 where 子句中使用!=或<>操做符,不然將引擎放棄使用索引而進行全表掃描。

b. 應儘可能避免在 where 子句中使用 or 來鏈接條件,不然將致使引擎放棄使用索引而進行全表掃描.

c. in 和 not in 也要慎用,不然會致使全表掃描

d. 應儘可能避免在 where 子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。

e. 應儘可能避免在where子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描

f. 不要在 where 子句中的「=」左邊進行函數、算術運算或其餘表達式運算,不然系統將可能沒法正確使用 索引。

g.儘可能避免使用遊標,由於遊標的效率較差

h.儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

i. 儘可能避免大事務操做,提升系統併發能力。

3)java方面:重點內容

a.儘量的少造對象。

b.合理擺正系統設計的位置。大量數據操做,和少許數據操做必定是分開的。大量的數據操做,確定不是ORM框架搞定的。

c.使用jDBC連接數據庫操做數據

d.控制好內存,讓數據流起來,而不是所有讀到內存再處理,而是邊讀取邊處理;

e.合理利用內存,有的數據要緩存

SpringMVC的工做原理

a. 用戶向服務器發送請求,請求被springMVC前端控制器DispatchServlet捕獲;

b. DispatcherServle對請求URL進行解析,獲得請求資源標識符(URL),而後根據該URL調用HandlerMapping將請求映射處處理器HandlerExcutionChain;

c. DispatchServlet根據得到Handler選擇一個合適的HandlerAdapter適配器處理;

d. Handler對數據處理完成之後將返回一個ModelAndView()對象給DisPatchServlet;

e. Handler 返回的 ModelAndView()只是一個邏輯視圖並非一個正式的視圖,DispatcherSevlet 經過ViewResolver試圖解析器將邏輯視圖轉化爲真正的視圖View;

f. DispatcherServle 經過 model 解析出 ModelAndView()中的參數進行解析最終展示出完整的 view 並返回給客戶端;

SpringMVC經常使用註解都有哪些

@requestMapping 用於請求 url 映射。


@RequestBody 註解實現接收 http 請求的 json 數據,將 json 數據轉換爲 java 對象。

@ResponseBody 註解實現將 controller 方法返回對象轉化爲 json 響應給客戶。

如何開啓註解處理器和適配器

咱們在項目中通常會在 springmvc.xml 中經過開啓 http://www.javashuo.com/tag/mvc:annotation-driven來實現註解處 理器和適配器的開啓。

如何解決get和post亂碼問題

解決 post 請求亂碼:咱們能夠在 web.xml 裏邊配置一個 CharacterEncodingFilter 過濾器。 設置爲 utf-8. 解決 get 請求的亂碼:有兩種方法。

  1. 修改 tomcat 配置文件添加編碼與工程編碼一致。

  2. 另 外 一 種 方 法 對 參 數 進 行 重 新 編 碼 String userName = New String(Request.getParameter(「userName」).getBytes(「ISO8859-1」), 「utf-8」);

談談你對Spring的理解

Spring是一個開源框架,爲簡化企業級應用開發而生。Spring能夠是使簡單的JavaBean實現之前只有EJB才能實現的功能。Spring是一個IOC和AOP容器框架。

Spring容器的主要核心是:

控制反轉(IOC),傳統的java開發模式中,當須要一個對象時,咱們會本身使用new或者getInstance等直接或者間接調用構造方法建立一個對象。而在spring開發模式中,spring容器使用了工廠模式爲咱們建立了所須要的對象,不須要咱們本身建立了,直接調用spring提供的對象就能夠了,這是控制反轉的思想。

依賴注入(DI),spring 使用 javaBean 對象的 set 方法或者帶參數的構造方法爲咱們在建立所需對象時將其屬性自動設置所須要的值的過程,就是依賴注入的思想。

面向切面編程(AOP),在面向對象編程(oop)思想中,咱們將事物縱向抽成一個個的對象。而在面向切面編程中,咱們將一個個的對象某些相似的方面橫向抽成一個切面,對這個切面進行一些如權限控制、事物管理,記錄日誌等公用操做處理的過程就是面向切面編程的思想。AOP底層是動態代理,若是是接口採用JDK動態代理,若是是類採用CGLIB方式實現動態代理。

Spring中的設計模式

a. 單例模式——spring中兩種代理方式,若目標對象實現了若干接口,spring使用jdk的java.lang.reflect.Proxy類代理。若目標兌現沒有實現任何接口,spring使用CGLIB庫生成目標類的子類。 單例模式——在spring的配置文件中設置bean默認爲單例模式。

b. 模板方式模式——用來解決代碼重複的問題。 好比:RestTemplate、JmsTemplate、JpaTemplate

c. 前端控制器模式——spring提供了前端控制器DispatherServlet來對請求進行分發。

d. 試圖幫助(view helper)——spring提供了一系列的JSP標籤,高效宏來幫助將分散的代碼整合在試圖中。

e. 依賴注入——貫穿於BeanFactory/ApplacationContext 接口的核心理念。

f. 工廠模式——在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用同一個接口來指向新建立的對象。Spring中使用beanFactory來建立對象的實例。

Spring的經常使用註解

註解裝配在 spring 中默認是關閉的。因此須要在 spring 的核心配置文件中配置一下才能使用基於註解的裝配模式。

配置方式以下: <context:annotation-config />

經常使用的註解: @Required:該註解應用於設值方法

@Autowired:該註解應用於有值設值方法、非設值方法、構造方法和變量。

@Qualifier:該註解和@Autowired搭配使用,用於消除特定bean自動裝配的歧義。

Spring能幫咱們作什麼

a. Spring能幫咱們根據配置文件建立及組裝對象之間的依賴關係。 Spring根據配置文件來進行建立及組裝對象間依賴關係,只須要改配置文件便可

b. Spring 面向切面編程能幫助咱們無耦合的實現日誌記錄,性能統計,安全控制。 Spring 面向切面編程能提供一種更好的方式來完成,通常經過配置方式,並且不須要在現有代碼中添加任何額外代碼,現有代碼專一業務邏輯。

c. Spring能很是簡單的幫咱們管理數據庫事務。 採用Spring,咱們只需獲取鏈接,執行SQL,其餘事物相關的都交給Spring來管理了。

d. Spring還能與第三方數據庫訪問框架(如Hibernate、JPA)無縫集成,並且本身也提供了一套JDBC訪問模板,來方便數據庫訪問。

e. Spring還能與第三方Web(如Struts、JSF)框架無縫集成,並且本身也提供了一套Spring MVC框架,來方便web層搭建。

f. Spring能方便的與Java EE(如Java Mail、任務調度)整合,與更多技術整合(好比緩存框架)。

BeanFactory 經常使用的實現類有哪些?

Bean 工廠是工廠模式的一個實現,提供了控制反轉功能,用來把應用的配置和依賴從正真的應用代碼中分離。經常使用的BeanFactory 實現有DefaultListableBeanFactory 、 XmlBeanFactory 、 ApplicationContext等

簡單介紹一下Spring WEB 模塊

Spring的WEB模塊是構建在application context 模塊基礎之上,提供一個適合web應用的上下文。這個模塊也包括支持多種面向web的任務,如透明地處理多個文件上傳請求和程序級請求參數的綁定到你的業務對象。它也有對Jakarta Struts的支持。

解釋Spring JDBC、Spring DAO和Spring ORM

  • Spring-DAO 並不是 Spring 的一個模塊,它其實是指示你寫 DAO 操做、寫好 DAO 操做的一些規範。所以,對於訪問你的數據它既沒有提供接口也沒有提供實現更沒有提供模板。在寫一個 DAO 的時候,你應該使用 @Repository 對其進行註解,這樣底層技術(JDBC,Hibernate,JPA,等等)的相關異常才能一致性地翻譯爲相應的 DataAccessException 子類。
  • Spring-JDBC 提供了 Jdbc 模板類,它移除了鏈接代碼以幫你專一於 SQL 查詢和相關參數。Spring-JDBC 還提供了一個 JdbcDaoSupport,這樣你能夠對你的 DAO 進行擴展開發。它主要定義了兩個屬性:一個 DataSource 和一個 JdbcTemplate,它們均可以用來實現 DAO 方法。JdbcDaoSupport 還提供了一個將 SQL 異常轉換爲 Spring DataAccessExceptions 的異常翻譯器。
  • Spring-ORM 是一個囊括了不少持久層技術(JPA,JDO,Hibernate,iBatis)的總括模塊。對於這些技術中的每個,Spring 都提供了集成類,這樣每一種技術都可以在遵循 Spring 的配置原則下進行使用,並平穩地和 Spring 事務管理進行集成。

Spring配置文件有什麼做用

Spring配置文件是個XML 文件,這個文件包含了類信息,描述瞭如何配置它們,以及如何相互調用。

什麼是Spring IOC 容器

IOC 控制反轉:Spring IOC 負責建立對象,管理對象。經過依賴注入(DI),裝配對象,配置對象,而且管理這些對象的整個生命週期。

有哪些不一樣類型的IOC(依賴注入)方式

Spring提供了多種依賴注入的方式。

1.Set注入

2.構造器注入

3.靜態工廠的方法注入

4.實例工廠的方法注入

什麼是Spring beans

Spring beans 是那些造成Spring應用的主幹的java對象。它們被Spring IOC 容器初始化,裝配,和管理。這些beans經過容器中配置的元數據建立。好比,以XML文件中<bean/> 的形式定義。 Spring 框架定義的beans都是單例 beans。

一個 Spring Beans的定義須要包含什麼

一個 Spring Bean 的定義包含容器必知的全部配置元數據,包括如何建立一個 bean,它的生命週期詳情及它的依賴。

你怎樣定義類的做用域

當定義一個<bean> 在Spring裏,咱們還能給這個bean聲明一個做用域。它能夠經過bean 定義中的scope屬性來定義。如,當 Spring 要在須要的時候每次生產一個新的 bean 實例,bean 的 scope 屬性被指定爲 prototype。另外一方面,一個bean每次使用的時候必須返回同一個實例,這個bean的scope 屬性必須設爲 singleton

Spring支持的幾種bean的做用域

Spring框架支持如下五種bean的做用域:

singleton : bean在每一個Spring ioc 容器中只有一個實例。

prototype:一個bean的定義能夠有多個實例。

request:每次http請求都會建立一個bean,該做用域僅在基於web的Spring ApplicationContext情形下有效。

session:在一個 HTTP Session 中,一個 bean 定義對應一個實例。該做用域僅在基於 web 的Spring ApplicationContext情形下有效。

global-session:在一個全局的 HTTP Session 中,一個 bean 定義對應一個實例。該做用域僅在基於 web 的Spring ApplicationContext情形下有效。

Spring框架中的單例bean是線程安全的嗎?

Spring框架中的單例bean不是線程安全的。

什麼是Spring的內部bean

當一個 bean 僅被用做另外一個 bean 的屬性時,它能被聲明爲一個內部 bean,爲了定義 inner bean,在Spring 的 基於XML的 配置元數據中,能夠在 <property/><constructor-arg/> 元素內使用<bean/> 元素,內部bean一般是匿名的,它們的Scope通常是prototype

在 Spring中如何注入一個java集合

Spring提供如下幾種集合的配置元素:

<list>類型用於注入一列值,容許有相同的值

<set> 類型用於注入一組值,不容許有相同的值

<props>類型用於注入一組鍵值對,鍵和值都只能爲String類型。

<map>型用於注入一組鍵值對,鍵和值均可覺得任意類型。

什麼是bean的自動裝配?

無須在Spring配置文件中描述javaBean之間的依賴關係(IOC容器會自動創建javabean之間的關聯關係。

解釋不一樣方式的自動裝配

有五種自動裝配的方式,能夠用來指導Spring容器用自動裝配方式來進行依賴注入。

1)no:默認的方式是不進行自動裝配,經過顯式設置ref 屬性來進行裝配。

2)byName:經過參數名自動裝配,Spring 容器在配置文件中發現 bean 的autowire 屬性被設置成 byname,以後容器試圖匹配、裝配和該bean的屬性具備相同名字的bean。

3)byType::經過參數類型自動裝配,Spring容器在配置文件中發現bean的autowire屬性被設置成byType,以後容器試圖匹配、裝配和該bean的屬性具備相同類型的bean。若是有多個bean符合條件,則拋出錯誤。

4)constructor:這個方式相似於 byType, 可是要提供給構造器參數,若是沒有肯定的帶參數的構造器參數類型,將會拋出異常。

5)autodetect:首先嚐試使用constructor來自動裝配,若是沒法工做,則使用byType方式。

什麼是基於Java的Spring註解配置? 給一些註解的例子

基於Java的配置,容許你在少許的Java註解的幫助下,進行你的大部分Spring配置而非經過XML文件。 以@Configuration 註解爲例,它用來標記類能夠當作一個 bean 的定義,被 Spring IOC 容器使用。另外一個例子是@Bean註解,它表示此方法將要返回一個對象,做爲一個bean註冊進Spring應用上下文。

什麼是基於註解的容器配置?

相對於XML文件,註解型的配置依賴於經過字節碼元數據裝配組件,而非尖括號的聲明。開發者經過在相應的類,方法或屬性上使用註解的方式,直接組件類中進行配置,而不是使用xml表述bean的裝配關係。

怎樣開啓註解裝配

註解裝配在默認狀況下是不開啓的,爲了使用註解裝配,咱們必須在 Spring 配置文件中配 context:annotation-config/元素

在Spring框架中如何更有效地使用JDBC?

使用 SpringJDBC 框架,資源管理和錯誤處理的代價都會被減輕。因此開發者只需寫 statements 和 queries 從數據存取數據,JDBC也能夠在Spring框架提供的模板類的幫助下更有效地被使用,這個模板叫JdbcTemplate 。 JdbcTemplate 類提供了不少便利的方法解決諸如把數據庫數據轉變爲基本數據類型或對象,執行寫好的或可調用的數據庫操做語句,提供自定義的數據錯誤處理。

使用Spring經過什麼方式訪問Hibernate?

在Spring中有兩種方式訪問Hibernate:

1)控制反轉 HibernateTemplate和 Callback。

2)繼承 HibernateDAOSupport提供一個AOP 攔截器。

Spring支持的ORM框架有哪些?

Spring支持如下ORM: Hibernate、iBatis、JPA (Java Persistence API)、TopLink、JDO (Java Data Objects)、OJB

Spring的通知是什麼?有哪幾種類型?

通知是個在方法執行前或執行後要作的動做,其實是程序執行時要經過SpringAOP框架觸發的代碼段。

Spring切面能夠應用五種類型的通知:

1.前置通知[Before advice]:在鏈接點前面執行,前置通知不會影響鏈接點的執行,除非此處拋出異常。

2.正常返回通知[After returning advice]:在鏈接點正常執行完成後執行,若是鏈接點拋出異常,則不會執行。

3.異常返回通知[After throwing advice]:在鏈接點拋出異常後執行。

4.返回通知[After (finally) advice]:在鏈接點執行完成後執行,無論是正常執行完成,仍是拋出異常,都會執行返回通知中的內容。

5.環繞通知[Around advice]:環繞通知圍繞在鏈接點先後,好比一個方法調用的先後。這是最強大的通知類型,能在方法調用先後自定義一些操做。環繞通知還須要負責決定是繼續處理join point(調用ProceedingJoinPoint的proceed方法)仍是中斷執行。

Mybatis中#和$的區別?

#至關於對數據 加上 雙引號,$至關於直接顯示數據

  1. #將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,若是傳入的值是111,那麼解析成sql時的值爲order by "111", 若是傳入的值是id,則解析成的sql爲order by "id".

  2. $將傳入的數據直接顯示生成在 sql 中。如:order by $user_id$,若是傳入的值是 111,那麼解析成 sql 時的值爲order by user_id, 若是傳入的值是id,則解析成的sql爲order by id.

  1. #方式可以很大程度防止sql注入。

  2. $方式沒法防止Sql注入。

  3. $方式通常用於傳入數據庫對象,例如傳入表名.

  4. 通常能用#的就別用$.

Mybatis的編程步驟是什麼樣的

一、建立SqlSessionFactory

二、經過SqlSessionFactory建立 SqlSession

三、經過sqlsession執行數據庫操做

四、調用session.commit()提交事務

五、調用session.close()關閉會話

JDBC編程有哪些不足之處,MyBatis是如何解決這些問題的

  • 數據庫連接建立、釋放頻繁形成系統資源浪費從而影響系統性能,若是使用數據庫連接池可解決此問題。

 

解決:在SqlMapConfig.xml中配置數據連接池,使用鏈接池管理數據庫連接。

  • Sql語句寫在代碼中形成代碼不易維護,實際應用sql變化的可能較大,sql變更須要改變java代碼。

 

解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。

 

  • 向 sql 語句傳參數麻煩,由於 sql 語句的 where 條件不必定,可能多也可能少,佔位符須要和參數一一對應。

解決: Mybatis自動將java對象映射至sql語句。

  • 對結果集解析麻煩,sql變化致使解析代碼變化,且解析前須要遍歷,若是能將數據庫記錄封裝成pojo對象解析比較方便。

 

解決:Mybatis自動將sql執行結果映射至java對象。

 

使用MyBatis的mapper接口調用時有哪些要求

  1. Mapper接口方法名和mapper.xml中定義的每一個sql的id相同

  2. Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同

  3. Mapper接口方法的輸出參數類型和mapper.xml中定義的每一個sql的resultType的類型相同

  4. Mapper.xml文件中的namespace便是mapper接口的類路徑。

Mybatis中一級緩存與二級緩存

  1. 一級緩存: 基於 PerpetualCache 的 HashMap 本地緩存,其存儲做用域爲 Session,當 Session flush 或 close 以後,該Session中的全部 Cache 就將清空。

  2. 二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap存儲,不一樣在於其存儲做用域爲 Mapper(Namespace),而且可自定義存儲源,如 Ehcache。做用域爲namespance指對該namespance對應的配置文件中全部的select操做結果都緩存,這樣不一樣線程之間就能夠共用二級緩存。啓動二級緩存:在mapper配置文件中:<cache />

MyBatis在insert插入操做時返回主鍵ID

數據庫爲MySql時:

<insert id="insert" parameterType="com.test.User" keyProperty="userId" useGeneratedKeys="true" >

「keyProperty」表示返回的id要保存到對象的那個屬性中,「useGeneratedKeys」表示主鍵id爲自增加模式。MySQL中作以上配置就OK了

簡單介紹一下Struts2

Struts2 框架是一個按照 MVC 設計模式設計的 WEB 層框架,是在 struts 1 和 WebWork 的技術基礎上進行了合併的全新的框架。其全新的 Struts 2 的體系結構與 Struts 1 的體 繫結構差異巨大。

Struts 2 以 WebWork 爲核心,採用攔截器的機制來處理用戶的請求, 這樣的設計也使得業務邏輯控制器可以與 ServletAPI 徹底脫離開。 
 咱們能夠把 struts2 理解爲一個大大的 servlet,而這個 servlet 就是ActionServlet。struts2 在處理客戶端請求時, 會先讀取 web.xml 配置文件,根據前端控制器將符合條件的請求 分給各個不一樣的 Action 處理。 在此以前,會把 ActionServlet 會把數據封裝成一個 javaBean。 
 Struts2 框架提供了許多的攔截器,在封裝數據的過程當中,咱們能夠對數據進行一些操 做,例如:數據校驗等等。

當 Action 執行完後要返回一個結果視圖,這個結果視圖能夠跟據 struts2 的配置文件中 配置,選擇轉發或者重定向。

Struts2中Action配置的注意事項有哪些

  1. name 包名稱,在 struts2 的配置文件中,包名不能重複,name 並非真正包名,只是爲了管理 Action


  1. namespace 和 <action>的 name 屬性,決定 Action 的訪問路徑 (以/開始 )

  2. extends 繼承哪一個包,一般開發中繼承 struts-default 包 (struts-default 包 在 struts-default.xml 中定義 )【能夠使用包中默認的攔截器和結果集】

攔截器和過濾器有哪些區別?

  • 攔截器是基於 java 的反射機制的,而過濾器是基於函數回調

  • 攔截器不依賴與 servlet 容器,而過濾器依賴與 servlet 容器


  • 攔截器只能對 action 請求起做用,而過濾器則能夠對幾乎全部的請求起做用

  • 攔截器能夠訪問 action 上下文、值棧裏的對象,而過濾器不能

  • 在 action 的生命週期中,攔截器能夠屢次被調用,而過濾器只能在容器初始化時被調用一 次

Struts2的封裝方式有哪些

1、屬性封裝

  1. 在action中設置成員變量,變量名與表單中的name屬性值相同

  2. 生成變量的set方法

2、模型驅動(經常使用)

  1. action實現 ModeDriven 接口

  2. 在action裏建立實體類對象

  3. 實現接口的 getModel方法並返回所建立的對象

3、表達式封裝

  1. 在 action 中聲明實體類

  2. 生成實體類的 set 和 get 方法

  3. 在表單輸入項的 name 屬性值裏面寫表達式

SpringMVC和Struts2的區別?

一、Struts2是類級別的攔截, 一個類對應一個request上下文,SpringMVC是方法級別的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應,因此說從架構自己上SpringMVC就容易實現restful url,而struts2的架構實現起來要費勁,由於 Struts2 中 Action 的一個方法能夠對應一個 url,而其類屬性卻被全部方法共享,這也就沒法用註解或其餘方式標識其所屬方法了。

二、由上邊緣由,SpringMVC的方法之間基本上獨立的,獨享request response數據,請求數據經過參數獲取,處理結果經過 ModelMap 交回給框架,方法之間不共享變量,而 Struts2 搞的就比較亂,雖然方法之間也是獨立的,但其全部 Action 變量是共享的,這不會影響程序運行,卻給咱們編碼 讀程序時帶來麻煩,每次來了請求就建立一個Action,一個Action對象對應一個request上下文。

三、因爲Struts2須要針對每一個request進行封裝,把request,session等servlet生命週期的變量封裝成一個一個Map,供給每一個Action使用,並保證線程安全,因此在原則上,是比較耗費內存的。

四、 攔截器實現機制上,Struts2有以本身的interceptor機制,SpringMVC用的是獨立的AOP方式,這樣致使Struts2的配置文件量仍是比SpringMVC大。

五、SpringMVC 的入口是servlet,而Struts2 是 filter(這裏要指出,filter 和servlet 是不一樣的。),這就致使了兩者的機制不一樣,這裏就牽涉到servlet和filter的區別了。

六、SpringMVC集成了Ajax,使用很是方便,只需一個註解@ResponseBody就能夠實現,而後直接返回響應文本便可,而Struts2攔截器集成了Ajax,在 Action中處理時通常必須安裝插件或者本身寫代碼集成進去,使用起來也相對不方便。

七、SpringMVC驗證支持JSR303,處理起來相對更加靈活方便,而Struts2驗證比較繁瑣,感受太煩亂。

八、Spring MVC 和 Spring 是無縫的。從這個項目的管理和安全上也比 Struts2 高(固然 Struts2 也能夠經過不一樣的目錄結構和相關配置作到SpringMVC同樣的效果,可是須要xml配置的地方很多)。

九、 設計思想上,Struts2更加符合OOP的編程思想, SpringMVC就比較謹慎,在servlet上擴展。

十、SpringMVC開發效率和性能高於Struts2。 十一、SpringMVC能夠認爲已經100%零配置。

Struts2中的 # 和 % 分別是作什麼的?

Struts2中有哪些經常使用結果類型

1)dispatcher :默認的請求轉發的結果類型,Action 轉發給 JSP

2) chain :Action轉發到另外一個Action (同一次請求)

3) redirect : 重定向,重定向到一個路徑信息,路徑信息沒有限制(不在一個請求中),Action重定向到 JSP

4) redirectAction :Action重定向到另外一個Action

5)stream :將原始數據做爲流傳遞迴瀏覽器端,該結果類型對下載的內容和圖片很是有用。

6)freemarker :呈現freemarker模板。 7)plaintext :返回普通文本內容。

簡述一下hibernate的開發流程

第一步:加載 hibernate 的配置文件,讀取配置文件的參數(jdbc 鏈接參數,數據 庫方言,hbm 表與對象關係映射文件) 


第二步:建立 SessionFactory 會話工廠(內部有鏈接池) 


第三步:打開 session 獲取鏈接,構造 session 對象(一次會話維持一個數據鏈接, 
也是一級緩存) 


第四步:開啓事務 


第五步:進行操做 
 第六步:提交事務 
 第七步:關閉 session(會話)將鏈接釋放 
 第八步:關閉鏈接池 


hibernate中對象的三種狀態

  • 瞬時態(臨時態、自由態):不存在持久化標識 OID,還沒有與 Hibernate Session 關聯對象, 被認爲處於瞬時態,失去引用將被 JVM 回收
  • 持久態:存在持久化標識 OID,與當前 session 有關聯,而且相關聯的 session 沒有關閉 , 而且事務未提交 

  • 脫管態(離線態、遊離態):存在持久化標識 OID,但沒有與當前 session 關聯,脫管狀態 改變 hibernate 不能檢測到


hibernate的緩存機制。

Hibernate緩存分爲兩層:Hibernate的一級緩存和Hibernate二級緩存。

1.Hibernate一級緩存(Session的緩存):

(1)Session實現了第一級Cache,屬於事務級數據緩衝。一旦事務結束,緩存隨之失效。一個Session的生命週期對應一個數據庫事務或一個程序事務。

(2)Session-Cache老是被打開而且不能被關閉的。

(3)Session-Cache保證一個Session中兩次請求同一個對象時,取得的對象是同一個Java實例,有時它能夠避免沒必要要的數據衝突。

               a.在對於同一個對象進行循環引用時,不至於產生堆棧溢出。

               b.當數據庫事務結束時,對於同一數據錶行,不會產生數據衝突。由於對於數據庫中的一行,最多有一個對象來表示它。

               c.一個事務中可能會有不少個處理單元,在每個處理單元中作的操做都會當即被其餘的數據單元得知。

2.Hibernate二級緩存(SessionFactory的緩存):

(1)二級緩存是SessionFactory範圍內的緩存,全部的 Session共享同一個二級緩存。在二級緩存中保存持久化實例的散裝形式的數據。

(2)持久化不一樣的數據須要不一樣的Cache策略,好比一些因素將影響Cache策略的選擇:數據的讀/寫比例、數據表是否能被其餘的應用程序所訪問等。

(3)設置Hibernate二級緩存須要分兩步:首先,確認使用什麼數據併發策略。而後,配置緩存過時時間並設置Cache提供器。

Hibernate的查詢方式有哪些

Hibernate的查詢方式常見的主要分爲三種: HQL, QBC(命名查詢), 以及使用原生SQL查詢(SqlQuery)

Hibernate和Mybatis的區別

二者相同點:

1)Hibernate與MyBatis均可以是經過SessionFactoryBuider由XML配置文件生成SessionFactory,而後由SessionFactory 生成 Session,最後由 Session 來開啓執行事務和 SQL 語句。其中 SessionFactoryBuider,SessionFactory,Session的生命週期都是差很少的。

2)Hibernate和MyBatis都支持JDBC和JTA事務處理。

Mybatis優點:

1)MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。

2)MyBatis容易掌握,而Hibernate門檻較高。

Hibernate優點:

1)Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射。

2)Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。

3)Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。

4)Hibernate有更好的二級緩存機制,能夠使用第三方緩存。MyBatis自己提供的緩存機制不佳。

Hibernate和JDBC優缺點對比

相同點:

1)二者都是java數據庫操做的中間件

2)二者對數據庫進行直接操做的對象都是線程不安全的,都須要及時關閉。

3)二者均可對數據庫的更新操做進行顯式的事務處理。

不一樣點:

JDBC是SUN公司提供一套操做數據庫的規範,使用java代碼操做數據庫。Hibernate是一個基於jdbc的主流持久化框架,對JDBC訪問數據庫的代碼作了封裝。

使用的SQL語言不一樣:JDBC使用的是基於關係型數據庫的標準SQL語言,Hibernate使用的是HQL(Hibernate query language)語言。

操做的對象不一樣:JDBC 操做的是數據,將數據經過 SQL 語句直接傳送到數據庫中執行,Hibernate 操做的是持久化對象,由底層持久化對象的數據更新到數據庫中。

數據狀態不一樣:JDBC操做的數據是「瞬時」的,變量的值沒法與數據庫中的值保持一致,而Hibernate操做的數據是可持久的,即持久化對象的數據屬性的值是能夠跟數據庫中的值保持一致的。

關於Hibernate的orm思想你瞭解多少?

ORM 指的是對象關係型映射(Object RelationShip Mapping ),指的就是咱們經過建立實體類對象和數據庫中的表關係進行一 一對應,來實現經過操做實體類對象來更改數據庫裏邊的數據信息。這裏邊起到關鍵做用的是經過Hibernate的映射文件+Hibernate的核心配置文件

如何進行Hibernate的優化

(1)數據庫設計調整。

(2)HQL優化。

(3)API的正確使用(如根據不一樣的業務類型選用不一樣的集合及查詢API)。

(4)主配置參數(日誌,查詢緩存,fetch_size, batch_size等)。

(5)映射文件優化(ID生成策略,二級緩存,延遲加載,關聯優化)。

(6)一級緩存的管理。

(7)針對二級緩存,還有許多特有的策略。

(8)事務控制策略

什麼是 Hibernate 延遲加載?

          延遲加載機制是爲了不一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正須要 數據的時候,才真正執行數據加載操做。在Hibernate中提供了對實體對象的延遲加載以及 對集合的延遲加載,另外在Hibernate3中還提供了對屬性的延遲加載。 延遲加載的過程:經過代理(Proxy)機制來實現延遲加載。Hibernate從數據庫獲取某一個對象數據時、獲取某一個對象的集合屬性值時,或獲取某一個對象所關聯的另外一個對象時,因爲沒有使用該對象的數據(除標識符外),Hibernate 並不從數據庫加載真正的數據,而只是爲該對象建立一個代理對象來表明這個對象,這個對象上的全部屬性都爲默認值;只有在真正須要使用該對象的數據時才建立這個真正的對象,真正從數據庫中加載它的數據。

hibernate中get和load的區別?

(1)get是當即加載,load是延時加載。

(2)get 會先查一級緩存,再查二級緩存,而後查數據庫;load 會先查一級緩存,若是沒有找到,就建立代理對象,等須要的時候去查詢二級緩存和數據庫。(這裏就體現load的延遲加載的特性。)

(3)get若是沒有找到會返回null,load若是沒有找到會拋出異常。

(4)當咱們使用 session.load()方法來加載一個對象時,此時並不會發出 sql 語句,當前獲得的這個對象實際上是一個代理對象,這個代理對象只保存了實體對象的id值,只有當咱們要使用這個對象,獲得其它屬性時,這個時候纔會發出 sql 語句,從數據庫中去查詢咱們的對象;相對於 load 的延遲加載方式,get 就直接的多,當咱們使用session.get()方法來獲得一個對象時,無論咱們使不使用這個對象,此時都會發出sql語句去從數據庫中查詢出來。

比較Hibernate三種檢索策略的優缺點

一、當即檢索

優勢:對應用程序徹底透明,無論對象處於持久化狀態,仍是遊離狀態,應用程序均可以方便的從一個對象導航到與它關聯的對象;

缺點:   

  • select語句太多;
  • 可能會加載應用程序不須要訪問的對象白白浪費許多內存空間;

二、延遲檢索

優勢:由應用程序決定須要加載哪些對象,能夠避免可執行多餘的 select 語句,以及避免加載應用程序不須要訪問的對象。所以能提升檢索性能,而且能節省內存空間;

缺點:應用程序若是但願訪問遊離狀態代理類實例,必須保證他在持久化狀態時已經被初始化;

三、 迫切左外鏈接檢索

優勢:

  • 對應用程序徹底透明,無論對象處於持久化狀態,仍是遊離狀態,應用程序均可以方便地衝一個對象導航到與它關聯的對象。
  • 使用了外鏈接,select語句數目少; 缺點:一、可能會加載應用程序不須要訪問的對象,白白浪費許多內存空間;
  • 複雜的數據庫錶鏈接也會影響檢索性能;
相關文章
相關標籤/搜索