JAVA 面試題(有部分答案)
面試題(有答案):
1. String類為什麼是final的。
答:主要是為了“效率” 和 “安全性” 的緣故。若 String允許被繼承, 由於它的高度被使用率, 可能會降低程式的效能,所以String被定義成final。
2. HashMap的原始碼,實現原理,底層結構。
3. 說說你知道的幾個Java集合類:list、set、queue、map實現類咯。。。
4. 描述一下ArrayList和LinkedList各自實現和區別
5. Java中的佇列都有哪些,有什麼區別。
6. 反射中,Class.forName和classloader的區別
答:共同點
1. 兩者都會將使用者指定的類載入到記憶體中,供使用者使用
不同點:
Class.forName方法有要不要初始static變數的引數,而ClassLoader.loadClass()沒有;Class.forName的過載方法是靜態的,而ClassLoader.loadClass不是。
7. Java7、Java8的新特性(baidu問的,好BT)
8. Java陣列和連結串列兩種結構的操作效率,在哪些情況下(從開頭開始,從結尾開始,從中間開始),哪些操作(插入,查詢,刪除)的效率高
答:陣列在隨機訪問資料、隨機增加資料、隨機刪除資料的執行效率上比連結串列的效率高,資料量越小,兩者之間效率的差距越小,資料量越大差距越大。
9. Java記憶體洩露的問題調查定位:jmap,jstack的使用等等
10. string、stringbuilder、stringbuffer區別
11. hashtable和hashmap的區別
13 .異常的結構,執行時異常和非執行時異常,各舉個例子
14. String a= “abc” String b = “abc” String c = new String(“abc”) String d = “ab” + “c” .他們之間用 == 比較的結果
15. String 類的常用方法
16. Java 的引用型別有哪幾種
17. 抽象類和介面的區別
18. java的基礎型別和位元組大小。
19. Hashtable,HashMap,ConcurrentHashMap 底層實現原理與執行緒安全問題(建議熟悉 jdk 原始碼,才能從容應答)
20. 如果不讓你用Java Jdk提供的工具,你自己實現一個Map,你怎麼做。說了好久,說了HashMap原始碼,如果我做,就會借鑑HashMap的原理,說了一通HashMap實現
21. Hash衝突怎麼辦?哪些解決雜湊衝突的方法?
22. HashMap衝突很厲害,最差效能,你會怎麼解決?從O(n)提升到log(n)咯,用二叉排序樹的思路說了一通
23. rehash
24. hashCode() 與 equals() 生成演算法、方法怎麼重寫
25. 講講IO裡面的常見類,位元組流、字元流、介面、實現類、方法阻塞。
26. 講講NIO。
27. String 編碼UTF-8 和GBK的區別?
28. 什麼時候使用位元組流、什麼時候使用字元流?
29. 遞迴讀取資料夾下的檔案,程式碼怎麼實現
30. session和cookie的區別和聯絡,session的生命週期,多個服務部署時session管理。
cookie 和session 的區別:1、cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上。2、cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙考慮到安全應當使用session。3、session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能考慮到減輕伺服器效能方面,應當使用COOKIE。4、單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。cookie 和session 的聯絡:session是通過cookie來工作的session和cookie之間是通過COOKIE[′PHPSESSID′]來聯系的,通過_COOKIE[‘PHPSESSID’]可以知道session的id,從而獲取到其他的資訊。在購物網站中通常將使用者加入購物車的商品聯通session_id記錄到資料庫中,當用戶再次訪問是,通過sessionid就可以查詢到使用者上次加入購物車的商品。因為sessionid是唯一的,記錄到資料庫中就可以根據這個查找了。
生命週期:
Session儲存在伺服器端,一般為了防止在伺服器的記憶體中(為了高速存取),Sessinon在使用者訪問第一次訪問伺服器時建立,需要注意只有訪問JSP、Servlet等程式時才會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session,可呼叫request.getSession(true)強制生成Session。
Session什麼時候失效?
1. 伺服器會把長時間沒有活動的Session從伺服器記憶體中清除,此時Session便失效。Tomcat中Session的預設失效時間為20分鐘。
2. 呼叫Session的invalidate方法。
多個服務部署時session管理
三種方式:1. Session複製,Web伺服器之間同步session資訊。2. 負載均衡支援會話親和,相同的會話請求傳送給同一個Web伺服器。3. Session不存在Web伺服器本地,而是放在快取伺服器如Redis上。
31. servlet的一些相關問題
32. webservice相關問題
33. jdbc連線,forname方式的步驟,怎麼宣告使用一個事務。舉例並具體程式碼
34. 無框架下配置web.xml的主要配置內容
35. jsp和servlet的區別
36. Java的記憶體模型以及GC演算法
JVM記憶體模型中分兩大塊,一塊是 NEW Generation, 另一塊是Old Generation. 在New Generation中,有一個叫Eden的空間,主要是用來存放新生的物件,還有兩個Survivor Spaces(from,to), 它們用來存放每次垃圾回收後存活下來的物件。在Old Generation中,主要存放應用程式中生命週期長的記憶體物件,還有個Permanent Generation,主要用來放JVM自己的反射物件,比如類物件和方法物件等。
在New Generation塊中,垃圾回收一般用Copying的演算法,速度快。每次GC的時候,存活下來的物件首先由Eden拷貝到某個Survivor Space, 當Survivor Space空間滿了後, 剩下的live物件就被直接拷貝到Old Generation中去。因此,每次GC後,Eden記憶體塊會被清空。在Old Generation塊中,垃圾回收一般用mark-compact的演算法,速度慢些,但減少記憶體要求.垃圾回收分多級,0級為全部(Full)的垃圾回收,會回收OLD段中的垃圾;1級或以上為部分垃圾回收,只會回收NEW中的垃圾,記憶體溢位通常發生於OLD段或Perm段垃圾回收後,仍然無記憶體空間容納新的Java物件的情況。
1,out of memory 只發生在jvm對old和perm generation 回收後還不能獲足夠記憶體的情況.
當一個URL被訪問時,記憶體申請過程如下:A. JVM會試圖為相關Java物件在Eden中初始化一塊記憶體區域B. 當Eden空間足夠時,記憶體申請結束。否則到下一步C. JVM試圖釋放在Eden中所有不活躍的物件(這屬於1或更高階的垃圾回收), 釋放後若Eden空間仍然不足以放入新物件,則試圖將部分Eden中活躍物件放入Survivor區D. Survivor區被用來作為Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的物件會被移到Old區,否則會被保留在Survivor區E. 當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)F. 完全垃圾收集後,若Survivor及OLD區仍然無法存放從Eden複製過來的部分物件,導致JVM無法在Eden區為新物件建立記憶體區域,則出現”out of memory錯誤”
造成full gc的原因:
new了很多物件,沒有即時在主動釋放掉->Eden記憶體不夠用->不斷把物件往old遷移->old滿了->full gc
full gc 如何預防,:
1,使用了快取
訪問有兩種,第一種是快取命中率不高的訪問,第二種種是快取命中率很高的訪問.對於第一種情況,就沒必要快取了,快取反而效果不好,浪費記憶體,沒有提升程式效率還浪費空間,特別是如果這種訪問量級別很大的時候還會導致full gc.第二種情況,不得不快取很多物件,不快取的話就要呼叫資料庫或者其它是要發生io的,所以這時候要不就是想辦法減少快取物件的大小,例如不快取沒必要快取的資料,或者合併一些資料減少記憶體的使用.如果還是不行那就加機器,加記憶體.
總結:在不影響功能的情況下,快取物件越小越要,命中率越高越好.低命中率的快取物件還不如不快取.
2,沒使用快取的情況,貌似不會出現full gc的情況,除非記憶體太小,或者設定不對,程式有漏洞.
37. jvm效能調優都做了什麼
38. 介紹JVM中7個區域,然後把每個區域可能造成記憶體的溢位的情況說明
39. 介紹GC 和GC Root不正常引用。
40. 自己從classload 載入方式,載入機制說開去,從程式執行時資料區,講到記憶體分配,講到String常量池,講到JVM垃圾回收機制,演算法,hotspot。反正就是各種擴充套件
41. jvm 如何分配直接記憶體, new 物件如何不分配在堆而是棧上,常量池解析
42. 陣列多大放在 JVM 老年代(不只是設定 PretenureSizeThreshold ,問通常多大,沒做過一問便知)
43. 老年代中陣列的訪問方式
44. GC 演算法,永久代物件如何 GC , GC 有環怎麼處理
45. 誰會被 GC ,什麼時候 GC
46. 如果想不被 GC 怎麼辦
47. 如果想在 GC 中生存 1 次怎麼辦
49. 講講mybatis的連線池。
50. spring框架中需要引用哪些jar包,以及這些jar包的用途
org.springframework.aop-3.0.6.RELEASE | Spring的面向切面程式設計,提供AOP(面向切面程式設計)實現 |
org.springframework.asm- 3.0.6.RELEASE | Spring獨立的asm程式,Spring2.5.6的時候需要asmJar 包3.0.6開始提供他自己獨立的asmJar |
org.springframework.aspects- 3.0.6.RELEASE | Spring提供對AspectJ框架的整合 |
org.springframework.beans-3.0.6.RELEASE | SpringIoC(依賴注入)的基礎實現 |
org.springframework.context.support-3.0.6.RELEASE | Spring-context的擴充套件支援,用於MVC方面 |
org.springframework.context-3.0.6.RELEASE | Spring提供在基礎IoC功能上的擴充套件服務,此外還提供許多企業級服務的支援,如郵件服務、任務排程、JNDI定位、EJB整合、遠端訪問、快取以及各種檢視層框架的封裝等 |
org.springframework.core-3.0.6.RELEASE | Spring3.0.6的核心工具包 |
org.springframework.expression-3.0.6.RELEASE | Spring表示式語言 |
org.springframework.instrument.tomcat-3.0.6.RELEASE | Spring3.0.6對Tomcat的連線池的整合 |
org.springframework.instrument-3.0.6.RELEASE | Spring3.0.6對伺服器的代理介面 |
org.springframework.jdbc-3.0.6.RELEASE | 對JDBC的簡單封裝 |
org.springframework.jms-3.0.6.RELEASE | 為簡化JMS API的使用而作的簡單封裝 |
org.springframework.orm-3.0.6.RELEASE | 整合第三方的ORM框架,如hibernate,ibatis,jdo,以及 spring的JPA實現 |
org.springframework.oxm-3.0.6.RELEASE | Spring 對Object/XMl的對映支援,可以讓Java與XML之間來回切換 |
org.springframework.test-3.0.6.RELEASE | 對Junit等測試框架的簡單封裝 |
org.springframework.transaction-3.0.6.RELEASE | 為JDBC、Hibernate、JDO、JPA等提供的一致的宣告式和程式設計式事務管理 |
org.springframework.web.portlet-3.0.6.RELEASE | 基於protlet的MVC實現 |
org.springframework.web.servlet-3.0.6.RELEASE | 基於servlet的MVC實現 |
org.springframework.web.struts-3.0.6.RELEASE | 整合Struts的時候的支援 |
org.springframework.web-3.0.6.RELEASE | SpringWeb下的工具包 |
做Spring還必須依賴第三方包:
① Spring 工程依賴的公共包commons-logging-1[1].0.4.jar(只要是做Spring都需要這個包,否則工程起不來)
51. springMVC的原理
答:1. 客戶端請求提交到DispatcherServlet
2. 由DispatcherServlet控制器查詢一個或多個HandlerMapping,找到處理請求的Controller
3. DispatcherServlet將請求提交到Controller
4. Controller呼叫業務邏輯處理後,返回ModelAndView
5. DispatcherServlet查詢一個或多個ViewResoler檢視解析器,找到ModelAndView指定的檢視
6. 檢視負責將結果顯示到客戶端
52. springMVC註解的意思
答:@Controller
@Controller 負責註冊一個bean 到spring 上下文中,bean 的ID 預設為
類名稱開頭字母小寫,你也可以自己指定,如下
方法一:
@Controller
public class TestController {}
方法二:
@Controller(“tmpController”)
public class TestController {}
@RequestMapping
[email protected]用來定義訪問的URL,你可以為整個類定義一個
@RequestMapping,或者為每個方法指定一個。
把@RequestMapping放在類級別上,這可令它與方法級別上的
@RequestMapping註解協同工作,取得縮小選擇範圍的效果。
例如:
@RequestMapping(“/test”)
public class TestController {}
則,該類下的所有訪問路徑都在/test之下。
2.將@RequestMapping用於整個類不是必須的,如果沒有配置,所有的方法
的訪問路徑配置將是完全獨立的,沒有任何關聯。
3.完整的引數項為:@RequestMapping(value=”“,method =
{“”,”“},headers={},params={“”,”“}),各引數說明如下:
value :String[] 設定訪問地址
method: RequestMethod[]設定訪問方式,字元陣列,檢視RequestMethod
類,包括GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE,常用
RequestMethod.GET,RequestMethod.POST
headers:String[] headers一般結合method = RequestMethod.POST使用
params: String[] 訪問引數設定,字元陣列 例如:userId=id
4.value的配置還可以採用模版變數的形式 ,例如:@RequestMapping
(value=”/owners/{ownerId}”, method=RequestMethod.GET),這點將在介
紹@PathVariable中詳細說明。
[email protected] params的補充說明,你可以通過設定引數條件來限制
訪問地址,例如params=”myParam=myValue”表示式,訪問地址中引數只有
包含了該規定的值”myParam=myValue”才能匹配得上,類似”myParam”之類
的表示式也是支援的,表示當前請求的地址必須有該引數(引數的值可以是
任意),”!myParam”之類的表示式表明當前請求的地址不能包含具體指定的
引數”myParam”。
6.有一點需要注意的,如果為類定義了訪問地址為*.do,*.html之類的,則
在方法級的@RequestMapping,不能再定義value值,否則會報錯,例如
Java程式碼
@RequestMapping(“/bbs.do”)
public class BbsController {
@RequestMapping(params = “method=getList”)
public String getList() {
return “list”;
}
@RequestMapping(value= “/spList”)
public String getSpecialList() {
return “splist”;
}
}
如上例:/bbs.do?method=getList 可以訪問到方法getList() ;而訪
問/bbs.do/spList則會報錯.
@PathVariable
[email protected]用於方法中的引數,表示方法引數繫結到地址URL的模板
變數。
例如:
Java程式碼
@RequestMapping(value=”/owners/{ownerId}”,
method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model
model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute(“owner”, owner);
return “displayOwner”;
}
[email protected]用於位址列使用{xxx}模版變數時使用。
如果@RequestMapping沒有定義類似”/{ownerId}” ,這種變數,則使用在
方法中@PathVariable會報錯。
@ModelAttribute
1.應用於方法引數,引數可以在頁面直接獲取,相當於
request.setAttribute(,)
2.應用於方法,將任何一個擁有返回值的方法標註上 @ModelAttribute,使
其返回值將會進入到模型物件的屬性列表中.
3.應用於方法引數時@ModelAttribute(“xx”),須關聯到Object的資料型別
,基本資料型別 如:int,String不起作用
例如:
Java程式碼
@ModelAttribute(“items”)//<——①向模型物件中新增一個名為items的
屬性
public List<String> populateItems() {
List<String> lists = new ArrayList<String>();
lists.add(“item1”);
lists.add(“item2”);
return lists;
}
@RequestMapping(params = “method=listAllBoard”)
public String listAllBoard(@ModelAttribute(“currUser”)User user,
ModelMap model) {
bbtForumService.getAllBoard();
//<——②在此訪問模型中的items屬性
System.out.println(“model.items:” + ((List<String>)
model.get(“items”)).size());
return “listBoard”;
}
在 ① 處,通過使用 @ModelAttribute 註解,populateItem() 方法將在
任何請求處理方法執行前呼叫,Spring MVC 會將該方法返回值以“items
”為名放入到隱含的模型物件屬性列表中。
所以在 ② 處,我們就可以通過 ModelMap 入參訪問到 items 屬性,當執
行 listAllBoard() 請求處理方法時,② 處將在控制檯列印
出“model.items:2”的資訊。當然我們也可以在請求的檢視中訪問到模型
物件中的 items 屬性。
@ResponseBody
這個註解可以直接放在方法上,表示返回型別將會直接作為HTTP響應位元組
流輸出(不被放置在Model,也不被攔截為檢視頁面名稱)。可以用於ajax。
@RequestParam
@RequestParam是一個可選引數,例如:@RequestParam(“id”) 註解,所以
它將和URL所帶引數 id進行繫結
如果入參是基本資料型別(如 int、long、float 等),URL 請求引數中
一定要有對應的引數,否則將丟擲
org.springframework.web.util.NestedServletException 異常,提示無
法將 null 轉換為基本資料型別.
@RequestParam包含3個配置 @RequestParam(required = ,value=”“,
defaultValue = “”)
required :引數是否必須,boolean型別,可選項,預設為true
value: 傳遞的引數名稱,String型別,可選項,如果有值,對應到設定方
法的引數
defaultValue:String型別,引數沒有傳遞時為引數預設指定的值
@SessionAttributes session管理
Spring 允許我們有選擇地指定 ModelMap 中的哪些屬性需要轉存到
session 中,以便下一個請求屬對應的 ModelMap 的屬性列表中還能訪問
到這些屬性。這一功能是通過類定義處標註 @SessionAttributes 註解來
實現的。@SessionAttributes 只能宣告在類上,而不能宣告在方法上。
例如
@SessionAttributes(“currUser”) // 將ModelMap 中屬性名為currUser 的屬性
@SessionAttributes({“attr1”,”attr2”})
@SessionAttributes(types = User.class)
@SessionAttributes(types = {User.class,Dept.class})
@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,”attr2”})
@CookieValue 獲取cookie資訊
@RequestHeader 獲取請求的頭部資訊
53. spring中beanFactory和ApplicationContext的聯絡和區別
答:1. BeanFactory負責讀取bean配置文件,管理bean的載入,例項化,維護bean之間的依賴關係,負責bean的宣告週期。2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,還提供了更完整的框架功能:a. 國際化支援b. 資源訪問:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”c. 事件傳遞:通過實現ApplicationContextAware介面
54. spring注入的幾種方式(迴圈注入)
答:1. 介面注入(不推薦)
2. getter,setter方式注入(比較常用)
3. 構造器注入(死的應用)
55. spring如何實現事物管理的
答:Spring+Hibernate的實質:就是把Hibernate用到的資料來源Datasource,Hibernate的SessionFactory例項,事務管理器HibernateTransactionManager,都交給Spring管理。那麼再沒整合之前Hibernate是如何實現事務管理的呢?通過ServletFilter實現資料庫事務的管理,這樣就避免了在資料庫操作中每次都要進行資料庫事務處理。一.事務的4個特性: 原子性:一個事務中所有對資料庫的操作是一個不可分割的操作序列,要麼全做,要麼全部做。 一致性:資料不會因為事務的執行而遭到破壞。 隔離性:一個事務的執行,不受其他事務(程序)的干擾。既併發執行的個事務之間互不干擾。 永續性:一個事務一旦提交,它對資料庫的改變將是永久的。二.事務的實現方式:實現方式共有兩種:編碼方式;宣告式事務管理方式。基於AOP技術實現的宣告式事務管理,實質就是:在方法執行前後進行攔截,然後在目標方法開始之前建立並加入事務,執行完目標方法後根據執行情況提交或回滾事務。宣告式事務管理又有兩種方式:基於XML配置檔案的方式;另一個是在業務方法上進行@Transactional註解,將事務規則應用到業務邏輯中。三.建立事務的時機:是否需要建立事務,是由事務傳播行為控制的。讀資料不需要或只為其指定只讀事務,而資料的插入,修改,刪除就需要事務管理了。一種常見的事務管理配置:事務攔截器TransactionInterceptor和事務自動代理BeanNameAutoProxyCreator相結合的方式<!–定義Hibernate的事務管理器HibernateTransactionManager –> <bean id=”transactionManager” class=”org.springframework.orm.hibernate3.HibernateTransactionManager”> <!– 依賴注入上面定義的sessionFactory –> <property name=”sessionFactory” ref=”sessionFactory”/> </bean><!–定義Spring的事務攔截器TransactionInterceptor –> <bean id=”transactionInterceptor” class=”org.springframework.transaction.interceptor.TransactionInterceptor”> <!– 依賴注入上面定義的事務管理器transactionManager –> <property name=”transactionManager” ref=”transactionManager”/><!– 定義需要進行事務攔截的方法及所採用的事務控制型別 –> <property name=”transactionAttributes”> <props> <!– 以browse、list、load、get及is開頭的所有方法採用只讀型事務控制型別 –> <prop key=”browse*”>PROPAGATION_REQUIRED,readOnly</prop> <prop key=”list*”>PROPAGATION_REQUIRED,readOnly</prop> <prop key=”load*”>PROPAGATION_REQUIRED,readOnly</prop> <prop key=”get*”>PROPAGATION_REQUIRED,readOnly</prop> <prop key=”is*”>PROPAGATION_REQUIRED,readOnly</prop> <!– 所有方法均進行事務控制,如果當前沒有事務,則新建一個事務 –><prop key=”*”>PROPAGATION_REQUIRED</prop> </props> </property></bean><!– 定義BeanNameAutoProxyCreatorf進行Spring的事務處理–> <bean class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”> <!– 針對指定的bean自動生成業務代理 –> <property name=”beanNames”> <list> <value>adminService</value> <value>columnsService</value> <value>newsService</value> <value>crawlService</value> <value>memberLevelService</value> <value>memberService</value> <value>categoryService</value> <value>merService</value> <value>cartService</value> <value>ordersService</value> <value>trafficService</value> </list> </property> <!– 這個屬性為true時,表示被代理的是目標類本身而不是目標類的介面 –> <property name=”proxyTargetClass”><value>true</value> </property> <!– 依賴注入上面定義的事務攔截器transactionInterceptor –> <property name=”interceptorNames”> <list> <value>transactionInterceptor</value> </list> </property> </bean>尤其注意:如下***********************************************************************************************************【以上的事務攔截器和事務自動代理方式實現原理:像Struts2一樣,都是憑藉強大的攔截器功能對業務邏輯方法的呼叫進行攔截,然後又BeanNameAutoProxyCreator自動生成事務代理,最後送事務管理器,統一管理】***********************************************************************************************************
56. springIOC
57. spring AOP的原理
答:下面為spring的主要原理:
IoC(Inversion of Control):IoC就是應用本身不依賴物件的建立和維護而是交給外部容器(這裡為spring),這要就把應用和物件之間解耦,控制權交給了外部容器。即Don’t call me ,I’ll call you!所以IoC也稱DI(依賴注入)物件的建立和維護依賴於外部容器.
class UserService{
private UserDao userDao = new UserDaoImpl(); //讓業務層與資料訪問層耦合在一起,不利用以後模組的替換.
private UserDao userDao_IoC = null;
public void SetUserDao(UserDao userDao){
this.userDao_IoC = userDao
}
public void save(User user){
userDao.save(user);
}
}
AOP(Aspect Oriented Programming):面向切面程式設計。就是把一些貫穿在各個模組之間相同的功能抽象出來,然後封裝成一個面。
AOP一般都是通過代理來實現,利用代理就有目標物件是什麼,攔截哪些點(方法),攔截後要做什麼。
JoinPoint(連線點):被攔截到的點. Advice(通知):攔截JoinPoint之前與之後要做的事。
PointCut(切入點):對joinPoint進行攔截的定義。Target(目標物件):代理的目標物件。
對於異常處理,日誌功能,許可權的檢查,事務等都是貫穿到各個模組之中,因此進行AOP.
代理技術有面向介面和生成子類.
public Object getProxy(final Object targetObj) {
Obejct obj = Proxy.newProxyInstance(
targetObj.getClass().getClassLoader(), //被代理類的類載入器
targetObj.getClass().getInterfaces(), //被代理類介面的位元組碼
new InvocationHandler() { //類似於一個回撥函式 代理功能就在裡面實現
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
try{
beforeAdvice(); //前置通知
method.invoke(targetObj, args); //攔截的點
afterAdvice(); //後置通知
}catch (Exception e) {
exceptionAdvice(); //異常通知
}finally{
finalAdvice(); //必須執行通知
}
return obj;
}
});
}
還一個用子類實現的同理 要採用CGlib庫來實現 JDK6之前未提供,估計JDK以後會提供。
這就是spring的2大原理,自如怎麼配置,那就要花點時間去學,原理思想掌握了哪些配置方法隨便學下就明白了。
58. hibernate中的1級和2級快取的使用方式以及區別原理
(Lazy-Load的理解)
答:快取是介於應用程式和物理資料來源之間,其作用是為了降低應用程式對物理資料來源訪問的頻次,從而提高了應用的執行效能。快取內的資料是對物理資料來源中的資料的複製,應用程式在執行時從快取讀寫資料,在特定的時刻或事件會同步快取和物理資料來源的資料。
快取的介質一般是記憶體,所以讀寫速度很快。但如果快取中存放的資料量非常大時,也會用硬碟作為快取介質。快取的實現不僅僅要考慮儲存的介質,還要考慮到管理快取的併發訪問和快取資料的生命週期。
Hibernate的快取包括Session的快取和SessionFactory的快取,其中SessionFactory的快取又可以分為兩類:內建快取和外接快取。Session的快取是內建的,不能被解除安裝,也被稱為Hibernate的第一級快取。SessionFactory的內建快取和Session的快取在實現方式上比較相似,前者是SessionFactory物件的一些集合屬性包含的資料,後者是指Session的一些集合屬性包含的資料。SessionFactory的內建快取中存放了對映元資料和預定義SQL語句,對映元資料是對映檔案中資料的拷貝,而預定義SQL語句是在Hibernate初始化階段根據對映元資料推匯出來,SessionFactory的內建快取是隻讀的,應用程式不能修改快取中的對映元資料和預定義SQL語句,因此SessionFactory不需要進行內建快取與對映檔案的同步。SessionFactory的外接快取是一個可配置的外掛。在預設情況下,SessionFactory不會啟用這個外掛。外接快取的資料是資料庫資料的拷貝,外接快取的介質可以是記憶體或者硬碟。SessionFactory的外接快取也被稱為Hibernate的第二級快取。
Hibernate的這兩級快取都位於持久化層,存放的都是資料庫資料的拷貝,那麼它們之間的區別是什麼呢?為了理解二者的區別,需要深入理解持久化層的快取的兩個特性:快取的範圍和快取的併發訪問策略。
持久化層的快取的範圍
快取的範圍決定了快取的生命週期以及可以被誰訪問。快取的範圍分為三類。
1 事務範圍:快取只能被當前事務訪問。快取的生命週期依賴於事務的生命週期,當事務結束時,快取也就結束生命週期。在此範圍下,快取的介質是記憶體。事務可以是資料庫事務或者應用事務,每個事務都有獨自的快取,快取內的資料通常採用相互關聯的的物件形式。
2 程序範圍:快取被程序內的所有事務共享。這些事務有可能是併發訪問快取,因此必須對快取採取必要的事務隔離機制。快取的生命週期依賴於程序的生命週期,程序結束時,快取也就結束了生命週期。程序範圍的快取可能會存放大量的資料,所以存放的介質可以是記憶體或硬碟。快取內的資料既可以是相互關聯的物件形式也可以是物件的鬆散資料形式。鬆散的物件資料形式有點類似於物件的序列化資料,但是物件分解為鬆散的演算法比物件序列化的演算法要求更快。
3 叢集範圍:在叢集環境中,快取被一個機器或者多個機器的程序共享。快取中的資料被複制到叢集環境中的每個程序節點,程序間通過遠端通訊來保證快取中的資料的一致性,快取中的資料通常採用物件的鬆散資料形式。
對大多數應用來說,應該慎重地考慮是否需要使用叢集範圍的快取,因為訪問的速度不一定會比直接訪問資料庫資料的速度快多少。
持久化層可以提供多種範圍的快取。如果在事務範圍的快取中沒有查到相應的資料,還可以到程序範圍或叢集範圍的快取內查詢,如果還是沒有查到,那麼只有到資料庫中查詢。事務範圍的快取是持久化層的第一級快取,通常它是必需的;程序範圍或叢集範圍的快取是持久化層的第二級快取,通常是可選的。
持久化層的快取的併發訪問策略
當多個併發的事務同時訪問持久化層的快取的相同資料時,會引起併發問題,必須採用必要的事務隔離措施。
在程序範圍或叢集範圍的快取,即第二級快取,會出現併發問題。因此可以設定以下四種類型的併發訪問策略,每一種策略對應一種事務隔離級別。
事務型:僅僅在受管理環境中適用。它提供了Repeatable Read事務隔離級別。對於經常被讀但很少修改的資料,可以採用這種隔離型別,因為它可以防止髒讀和不可重複讀這類的併發問題。
讀寫型:提供了Read Committed事務隔離級別。僅僅在非叢集的環境中適用。對於經常被讀但很少修改的資料,可以採用這種隔離型別,因為它可以防止髒讀這類的併發問題。
非嚴格讀寫型:不保證快取與資料庫中資料的一致性。如果存在兩個事務同時訪問快取中相同資料的可能,必須為該資料配置一個很短的資料過期時間,從而儘量避免髒讀。對於極少被修改,並且允許偶爾髒讀的資料,可以採用這種併發訪問策略。 只讀型:對於從來不會修改的資料,如參考資料,可以使用這種併發訪問策略。
事務型併發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,併發效能就越低。
什麼樣的資料適合存放到第二級快取中?
1、很少被修改的資料
2、不是很重要的資料,允許出現偶爾併發的資料
3、不會被併發訪問的資料
4、參考資料
不適合存放到第二級快取的資料?
1、經常被修改的資料
2、財務資料,絕對不允許出現併發
3、與其他應用共享的資料。
Hibernate的二級快取
如前所述,Hibernate提供了兩級快取,第一級是Session的快取。由於Session物件的生命週期通常對應一個數據庫事務或者一個應用事務,因此它的快取是事務範圍的快取。第一級快取是必需的,不允許而且事實上也無法比卸除。在第一級快取中,持久化類的每個例項都具有唯一的OID。
第二級快取是一個可插拔的的快取外掛,它是由SessionFactory負責管理。由於SessionFactory物件的生命週期和應用程式的整個過程對應,因此第二級快取是程序範圍或者叢集範圍的快取。這個快取中存放的物件的鬆散資料。第二級物件有可能出現併發問題,因此需要採用適當的併發訪問策略,該策略為被快取的資料提供了事務隔離級別。快取介面卡用於把具體的快取實現軟體與Hibernate整合。第二級快取是可選的,可以在每個類或每個集合的粒度上配置第二級快取。
Hibernate的二級快取策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有欄位)這樣的SQL語句查詢資料庫,一次獲得所有的資料物件。
2) 把獲得的所有資料物件根據ID放入到第二級快取中。
3) 當Hibernate根據ID訪問資料物件的時候,首先從Session一級快取中查;查不到,如果配置了二級快取,那麼從二級快取中查;查不到,再查詢資料庫,把結果按照ID放入到快取。
4) 刪除、更新、增加資料的時候,同時更新快取。
Hibernate的二級快取策略,是針對於ID查詢的快取策略,對於條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query快取。
Hibernate的Query快取策略的過程如下:
1) Hibernate首先根據這些資訊組成一個Query Key,Query Key包括條件查詢的請求一般資訊:SQL, SQL需要的引數,記錄範圍(起始位置rowStart,最大記錄個數maxRows),等。
2) Hibernate根據這個Query Key到Query快取中查詢對應的結果列表。如果存在,那麼返回這個結果列表;如果不存在,查詢資料庫,獲取結果列表,把整個結果列表根據Query Key放入到Query快取中。
3) Query Key中的SQL涉及到一些表名,如果這些表的任何資料發生修改、刪除、增加等操作,這些相關的Query Key都要從快取中清空。
59. Hibernate的原理體系架構,五大核心介面,Hibernate物件的三種狀態轉換,事務管理。
60. Java建立執行緒之後,直接呼叫start()方法和run()的區別
61. 常用的執行緒池模式以及不同執行緒池的使用場景
62. newFixedThreadPool此種執行緒池如果執行緒數達到最大值後會怎麼辦,底層原理。
63. 多執行緒之間通訊的同步問題,synchronized鎖的是物件,衍伸出和synchronized相關很多的具體問題,例如同一個類不同方法都有synchronized鎖,一個物件是否可以同時訪問。或者一個類的static構造方法加上synchronized之後的鎖的影響。
64. 瞭解可重入鎖的含義,以及ReentrantLock 和synchronized的區別
65. 同步的資料結構,例如concurrentHashMap的原始碼理解以及內部實現原理,為什麼他是同步的且效率高
66. atomicinteger和Volatile等執行緒安全操作的關鍵字的理解和使用
67. 執行緒間通訊,wait和notify
68. 定時執行緒的使用
69. 場景:在一個主執行緒中,要求有大量(很多很多)子執行緒執行完之後,主執行緒才執行完成。多種方式,考慮效率。
70. 程序和執行緒的區別
71. 什麼叫執行緒安全?舉例說明
72. 執行緒的幾種狀態
73. 併發、同步的介面或方法
74. HashMap 是否執行緒安全,為何不安全。 ConcurrentHashMap,執行緒安全,為何安全。底層實現是怎麼樣的。
75. J.U.C下的常見類的使用。 ThreadPool的深入考察; BlockingQueue的使用。(take,poll的區別,put,offer的區別);原子類的實現。
76. 簡單介紹下多執行緒的情況,從建立一個執行緒開始。然後怎麼控制同步過程,多執行緒常用的方法和結構
77. volatile的理解
78. 實現多執行緒有幾種方式,多執行緒同步怎麼做,說說幾個執行緒裡常用的方法
79. http是無狀態通訊,http的請求方式有哪些,可以自己定義新的請求方式麼。
答:HTTP/1.1規定的 HTTP 請求方法有8種CONNECT 、OPTIONS、PUT、DELETE、TRACE、
GET、
HEAD、
POST:包含了Content-Type 和訊息主體編碼方式兩部分
application/x-www-form-urlencoded
最常見的 POST 提交資料的方式了。瀏覽器的原生 form 表單,如果不設定 enctype 屬性,那麼最終就會以 application/x-www-form-
urlencoded 方式提交資料
multipart/form-data
使用表單上傳檔案時,必須讓 form 的 enctyped 等於這個值
自己定義新的資料提交方式:
application/json
現在越來越多的人把它作為請求頭,用來告訴服務端訊息主體是序列化後的 JSON 字串。由於 JSON 規範的流行,除了低版本 IE 之外的
各大瀏覽器都原生支援 JSON.stringify,服務端語言也都有處理 JSON 的函式,使用 JSON 不會遇上什麼麻煩。
http中,Get和Post的區別
GET 被強制伺服器支援
瀏覽器對URL的長度有限制,所以GET請求不能代替POST請求傳送大量資料
GET請求傳送資料更小
GET請求是安全的, 這裡的安全指的是在規範的定義下,Get操作不會修改伺服器的資料
GET請求是冪等的
POST請求不能被快取
POST請求相對GET請求是「安全」的,這裡所有的「安全」是相對的,因為GET請求有時候會直接反應在瀏覽器的位址列,而現在的瀏覽器大多會記住曾經輸入過的URL
80. socket通訊,以及長連線,分包,連線異常斷開的處理。
81. socket通訊模型的使用,AIO和NIO。
82. socket框架netty的使用,以及NIO的實現原理,為什麼是非同步非阻塞。
83. 同步和非同步,阻塞和非阻塞。
84. OSI七層模型,包括TCP,IP的一些基本知識
85. http中,get post的區別
86. 說說http,tcp,udp之間關係和區別。
87. 說說瀏覽器訪問www.taobao.com,經歷了怎樣的過程。
88. HTTP協議、 HTTPS協議,SSL協議及完整互動過程;
89. tcp的擁塞,快回傳,ip的報文丟棄
90. https處理的一個過程,對稱加密和非對稱加密
91. head各個特點和區別
92. 說說瀏覽器訪問www.taobao.com,經歷了怎樣的過程。
93. MySQL的儲存引擎的不同
答:這個是考慮效能的問題,還有事務的支援,吧 百度一下你就知道 MyISAM、InnoDB、Heap(Memory)、NDB 貌似一般都是使用 InnoDB的, mysql的儲存引擎包括:MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDBCluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等,其中InnoDB和BDB提供事務安全表,其他儲存引擎都是非事務安全表。 最常使用的2種儲存引擎: 1.Myisam是Mysql的預設儲存引擎,當create建立新表時,未指定新表的儲存引擎時,預設使用Myisam。每個MyISAM在磁碟上儲存成三個檔案。檔名都和表名相同,副檔名分別是.frm(儲存表定義)、.MYD(MYData,儲存資料)、.MYI(MYIndex,儲存索引)。資料檔案和索引檔案可以放置在不同的目錄,平均分佈io,獲得更快的速度。 2.InnoDB儲存引擎提供了具有提交、回滾和崩潰恢復能力的事務安全。但是對比Myisam的儲存引擎,InnoDB寫的處理效率差一些並且會佔用更多的磁碟空間以保留資料和索引。
94. 單個索引、聯合索引、主鍵索引
答:Mysql索引概念:說說Mysql索引,看到一個很少比如:索引就好比一本書的目錄,它會讓你更快的找到內容,顯然目錄(索引)並不是越多越好,假如這本書1000頁,有500也是目錄,它當然效率低,目錄是要佔紙張的,而索引是要佔磁碟空間的。Mysql索引主要有兩種結構:B+樹和hash.
hash:hsah索引在mysql比較少用,他以把資料的索引以hash形式組織起來,因此當查詢某一條記錄的時候,速度非常快.當時因為是hash結構,每個鍵只對應一個值,而且是雜湊的方式分佈.所以他並不支援範圍查詢和排序等功能.B+樹:b+tree是mysql使用最頻繁的一個索引資料結構,資料結構以平衡樹的形式來組織,因為是樹型結構,所以更適合用來處理排序,範圍查詢等功能.相對hash索引,B+樹在查詢單條記錄的速度雖然比不上hash索引,但是因為更適合排序等操作,所以他更受使用者的歡迎.畢竟不可能只對資料庫進行單條記錄的操作. Mysql常見索引有:主鍵索引、唯一索引、普通索引、全文索引、組合索引
PRIMARY KEY(主鍵索引) ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) UNIQUE(唯一索引) ALTER TABLE `table_name` ADD UNIQUE (`column`)INDEX(普通索引) ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) FULLTEXT(全文索引) ALTER TABLE `table_name` ADD FULLTEXT ( `column` )組合索引 ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
Mysql各種索引區別:普通索引:最基本的索引,沒有任何限制唯一索引:與”普通索引”類似,不同的就是:索引列的值必須唯一,但允許有空值。主鍵索引:它 是一種特殊的唯一索引,不允許有空值。 全文索引:僅可用於 MyISAM 表,針對較大的資料,生成全文索引很耗時好空間。組合索引:為了更多的提高mysql效率可建立組合索引,遵循”最左字首“原則。
95. Mysql怎麼分表,以及分表後如果想按條件分頁查詢怎麼辦(如果不是按分表字段來查詢的話,幾乎效率低下,無解)
答:當一張的資料達到幾百萬時,你查詢一次所花的時間會變多,如果有聯合查詢的話,我想有可能會死在那兒了。分表的目的就在於此,減小資料庫的負擔,縮短查詢時間。
根據個人經驗,mysql執行一個sql的過程如下:1,接收到sql;2,把sql放到排隊佇列中 ;3,執行sql;4,返回執行結果。在這個執行過程中最花時間在什麼地方呢?第一,是排隊等待的時間,第二,sql的執行時間。其實這二個是一回事,等待的同時,肯定有sql在執行。所以我們要縮短sql的執行時間。
mysql中有一種機制是表鎖定和行鎖定,為什麼要出現這種機制,是為了保證資料的完整性,我舉個例子來說吧,如果有二個sql都要修改同一張表的同一條 資料,這個時候怎麼辦呢,是不是二個sql都可以同時修改這條資料呢?很顯然mysql對這種情況的處理是,一種是表鎖定(myisam儲存引擎),一個 是行鎖定(innodb儲存引擎)。表鎖定表示你們都不能對這張表進行操作,必須等我對錶操作完才行。行鎖定也一樣,別的sql必須等我對這條資料操作完 了,才能對這條資料進行操作。如果資料太多,一次執行的時間太長,等待的時間就越長,這也是我們為什麼要分表的原因。
二,分表
1,做mysql叢集,例如:利用mysql cluster ,mysql proxy,mysql replication,drdb等等
有人會問mysql叢集,根分表有什麼關係嗎?雖然它不是實際意義上的分表,但是它啟到了分表的作用,做叢集的意義是什麼呢?為一個數據庫減輕負擔,說白 了就是減少sql排隊佇列中的sql的數量,舉個例子:有10個sql請求,如果放在一個數據庫伺服器的排隊佇列中,他要等很長時間,如果把這10個 sql請求,分配到5個數據庫伺服器的排隊佇列中,一個數據庫伺服器的佇列中只有2個,這樣等待時間是不是大大的縮短了呢?這已經很明顯了。所以我把它列 到了分表的範圍以內,我做過一些mysql的叢集:
linux mysql proxy 的安裝,配置,以及讀寫分離
mysql replication 互為主從的安裝及配置,以及資料同步
優點:擴充套件性好,沒有多個分表後的複雜操作(PHP程式碼)
缺點:單個表的資料量還是沒有變,一次操作所花的時間還是那麼多,硬體開銷大。
2,預先估計會出現大資料量並且訪問頻繁的表,將其分為若干個表
這種預估大差不差的,論壇裡面發表帖子的表,時間長了這張表肯定很大,幾十萬,幾百萬都有可能。 聊天室裡面資訊表,幾十個人在一起一聊一個晚上,時間長了,這張表的資料肯定很大。像這樣的情況很多。所以這種能預估出來的大資料量表,我們就事先分出個N個表,這個N是多少,根據實際情況而定。以聊天資訊表為例:
我事先建100個這樣的表,message_00,message_01,message_02……….message_98,message_99.然 後根據使用者的ID來判斷這個使用者的聊天資訊放到哪張表裡面,你可以用hash的方式來獲得,可以用求餘的方式來獲得,方法很多,各人想各人的吧。下面用 hash的方法來獲得表名:
1. <?php
2. function get_hash_table(table,userid) {
3. str = crc32(userid);
4. if($str<0){
5. hash = "0".substr(abs(str), 0, 1);
6. }else{
7. hash = substr(str, 0, 2);
8. }
9.
10. return table."′′.hash;
11. }
12.
13. echo get_hash_table(‘message’,’user18991’); //結果為message_10
14. echo get_hash_table(‘message’,’user34523’); //結果為message_13
15. ?>
說明一下,上面的這個方法,告訴我們user18991這個使用者的訊息都記錄在message_10這張表裡,user34523這個使用者的訊息都記錄在message_13這張表裡,讀取的時候,只要從各自的表中讀取就行了。
優點:避免一張表出現幾百萬條資料,縮短了一條sql的執行時間
缺點:當一種規則確定時,打破這條規則會很麻煩,上面的例子中我用的hash演算法是crc32,如果我現在不想用這個演算法了,改用md5後,會使同一個使用者的訊息被儲存到不同的表中,這樣資料亂套了。擴充套件性很差。
3,利用merge儲存引擎來實現分表
我覺得這種方法比較適合,那些