天天看點

預備春招面試複習第一篇-----SSM架構

前言

為什麼要先準備架構内容的複習呢?

個人是因為履歷平平,隻有倆項目還看得過去,新年的首發面試就涼在項目上,上來便是轟炸項目和架構.後來檢討了下,架構知識也是一塊很重要的内容.面試首發一般都是針對履歷的項目開始考察.

後來看了一些别人的面經,很多都是上來就扯項目,你說要是連第一關架構都入不了面試官的眼,那還指望其他加分嗎? 尤其當我知道别人二面全怼項目的時候,才意識到架構其實是面試的大頭.那些隻考算法,網絡,作業系統的隻是bat等大廠而已.

對于絕大多數普通人(履曆平平)來說,面試内容中項目和架構占了大半,不容忽視.

Spring篇:

Spring複習中最重要的兩塊:

1. IOC(控制反轉)和DI(依賴注入)
2. AOP(面向切面程式設計)           

控制反轉(IoC): 一種反轉流、依賴和接口的方式(DIP的具體實作方式)。

依賴注入(DI): IoC的一種實作方式,用來反轉依賴(IoC的具體實作方式)。

IoC容器: 依賴注入的架構,用來映射依賴,管理對象建立和生存周期(DI架構)。

三者之間關系看這篇:

http://blog.jobbole.com/101666/

IOC是什麼?

這一篇講的不錯:

http://www.cnblogs.com/DebugLZQ/archive/2013/06/05/3107957.html

IOC更具體的 ,如初始化等:

https://segmentfault.com/a/1190000017348726

個人了解:

IOC是一種思想,而DI則是它的實作方式(還有另一種方式:服務定位)
IOC容器作為第三方,将各個對象粘合在一起.
在Spring中由Spring容器借助bean配置來控制
Spring IOC容器是DI注入的架構,負責建立對象,管理對象,整合對象,配置對象以及管理這些對象的生命周期.
通過配置檔案管理對象的生命周期,依賴關系,不用重新修改并編譯具體的代碼,進而實作元件之間的解耦.           

沒有IOC的情況時,對象A依賴對象B時,需要對象手動建立B,這個時候控制權在A手中,此時耦合度高,會出現牽一發而動全身的問題.

出現IOC後,選擇控制權從調用類中移除,所有對象的控制權都上交到IOC容器中,這時候它就起到了"粘合劑"的作用

控制反轉的由來是因為:對象A獲得依賴對象B的過程由主動行為變成了被動行為,控制權颠倒過來.

可以了解為:獲得依賴對象的過程被反轉了,即獲得依賴對象的過程由自身管理變成了由IOC容器主動注入

依賴注入:

由IOC容器在運作期間,動态地将某種依賴關系注入到對象之中

依賴注入(DI)和控制反轉(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關系注入的方式,實作對象之間的解耦

與new對象的差別?

正轉與反轉,傳統應用程式是由我們将自己在對象中主動控制去直接擷取依賴對象,也就是正轉;而反轉則是由容器來幫助建立及注入依賴對象。

IoC優缺點

優點:實作元件之間的解耦,提供程式的靈活性和可維護性
缺點:對象生成因為是使用反射程式設計,在效率上有損耗
           

那在spring中如何放入一個對象管理呢?(以XML配置方式解釋)

  1. 準備配置檔案:配置檔案中聲明 Bean 定義也就是 Bean 配置中繼資料。
  2. 通過應用上下文将配置加載到IOC容器
  3. 由 IoC 容器進行解析中繼資料:IoC 容器的 Bean Reader 讀取并解析配置檔案,根據定義生成 BeanDefintion 配置中繼資料對象,IoC 容器根據 BeanDefintion 進行執行個體化、配置及組裝 Bean。
  4. 執行個體化 IoC 容器:由用戶端執行個體化容器,擷取需要的 Bean。

什麼是應用上下文?

應用上下文其實就是IOC容器在Spring中的代碼實作,在Spring中IOC容器大緻分為兩種:

  1. BeanFactory
  2. 內建BeanFactory後派生而來的應用上下文,如其抽象接口為ApplicationContext

具體參考:

https://www.cnblogs.com/chenbenbuyi/p/8166304.html

Spring XML配置Bean注入的三種常見方式:

  1. 屬性注入(set 注入):可以有選擇地通過 Setter 方法完成調用類所需依賴的注入。
  2. 構造函數注入:通過調用類的構造函數,将接口實作類通過構造函數變量傳入。
  3. 工廠方法注入

    參考:

https://blog.csdn.net/a909301740/article/details/78379720

AOP(面向切面程式設計):

是對OOP的補充和完善,OOP是縱向有層次的結構,而AOP是橫向的,注重的是解決許多問題的方法中的共同點,就比如 我們開發的軟體中有很多業務方法,但是我們要對這個方法的執行進行監控,需要加入日志記錄,這個時候日志代碼寫在哪裡?顯然不能寫在業務代碼裡,這樣不僅污染了業務代碼,而且因為不同業務方法都需要這個日志代碼,重複性很高,是以我們要單獨領出來寫成一個通用的代碼塊,這個時候AOP面向切面的程式設計就呼之欲出了.

總結:

AOP就是在目标類的基礎上增加切面邏輯,生成增強的類(切面邏輯在目标函數執行之前,或者之後,或者抛出異常時執行)

AOP将應用系統分為兩部分,一部分是核心業務邏輯,一部分是橫向的通用邏輯,通過反射機制調用目标類的代碼,動态将橫切邏輯和業務邏輯編織在一起.

AOP中的核心功能的底層實作機制:動态代理的實作原理,AOP中的攔截功能是由java的動态代理實作的.

重頭戲來了:jdk動态代理和CGLIB動态代理.(當初考我兩者差別,我隻知道CGLIB快)

jdk:

1.由java内部的反射機制實作,通過實作 InvocationHandler 接口建立自己的調用處理器;

  1. 代理的目标類必須基于統一的接口,有一定的局限性,在生成類的過程中比較高效
  2. 代理機制是委托機制,不需要以來第三方的庫,隻要要JDK環境就可以進行代理,動态實作接口類,在動态生成的實作類裡面委托為hanlder去調用原始實作類方法;

CGLIB:

  1. CGLIB既可以對接口的類生成代理,也可以針對類生成代理。以在運作期擴充Java類與實作Java接口。
  2. 底層借助asm實作,對代理對象類的class檔案加載進來,通過修改其位元組碼生成子類來處理。
  3. 在生成類之後的相關執行過程中比較高效(可以通過将asm生成的類進行緩存,解決生成類過程低效的問題)
  4. CGLib的類庫,使用的是繼承機制,是被代理類和代理類繼承的關系,是以代理類是可以指派給被代理類的,如果被代理類有接口,那麼代理類也可以指派給接口。
  5. CGLIB是針對類實作代理,主要是對指定的類生成一個子類,覆寫其中的方法因為是繼承,是以該類或方法最好不要聲明成final

具體應用:

如果目标對象實作了接口,預設情況下是采用JDK動态實作AOP

如果目标對象沒有實作接口,必須采用CGLIB庫.

如何強制使用CGLIB實作AOP?

1. 添加CGLIB庫,SPRING_HOME/cglib/*.jar 

2. 在spring配置檔案中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
           

過濾器和攔截器:

Filter配置在web.xml

賴于servlet容器。在實作上,基于函數回調,它可以對幾乎所有請求進行過濾,但是缺點是一個過濾器執行個體隻能在容器初始化時調用一次。使用過濾器的目的,是用來做一些過濾操作,擷取我們想要擷取的資料,比如:在Javaweb中,對傳入的request、response提前過濾掉一些資訊,或者提前設定一些參數,然後再傳入servlet或者Controller進行業務邏輯操作。通常用的場景是:在過濾器中修改字元編碼(CharacterEncodingFilter)、在過濾器中修改HttpServletRequest的一些參數(XSSFilter(自定義過濾器)),如:過濾低俗文字、危險字元等。

攔截器的配置一般在SpringMVC的配置檔案中

在實作上,基于Java的反射機制,屬于面向切面程式設計(AOP)的一種運用,就是在service或者一個方法前,調用一個方法,或者在方法後,調用一個方法,比如動态代理就是攔截器的簡單實作,在調用方法前列印出字元串(或者做其它業務邏輯的操作),也可以在調用方法後列印出字元串,甚至在抛出異常的時候做業務邏輯的操作。由于攔截器是基于web架構的調用,是以可以使用Spring的依賴注入(DI)進行一些業務操作,同時一個攔截器執行個體在一個controller生命周期之内可以多次調用。但是缺點是隻能對controller請求進行攔截,對其他的一些比如直接通路靜态資源的請求則沒辦法進行攔截處理

https://blog.csdn.net/zxd1435513775/article/details/80556034 https://blog.csdn.net/xiaodanjava/article/details/32125687

Bean和Spring容器之間的關系:

https://www.cnblogs.com/wuchanming/p/5426746.html

servlet和jsp本質是一樣的嗎?

答:一樣

https://www.zhihu.com/question/37962386

servlet,過濾器,監聽器,攔截器的差別:

https://www.cnblogs.com/jinb/p/6915351.html

Spring架構的啟動入口?

Spring的入口配置在web.xml中。以監聽器的形式來實作。

即ContextLoaderListener

它實作了接口ServletContextListener,也就是說他必須實作contextDestroyed, contextInitialized這兩個方法

Spring架構由此啟動, contextInitialized也就是監聽器類的main入口函數

所有實作都隐藏在ContextLoader類裡

參考:

https://blog.csdn.net/xiaolyuh123/article/details/60132518

web.xml 檔案中一般包括什麼?

servlet, filter, listenr的配置

servlet:是伺服器端的程式,用來處理和響應請求,web.xml配置目的是攔截指定的url位址,傳遞給SpringMVC的DispatcherServlet處理

filter:如編碼過濾器,解決亂碼問題,啟動一次

listenr:監聽器,一般配置Spring監聽器

web.xml的加載過程是context-param >> listener >> fileter >> servlet

初始化過程:
1. 在啟動Web項目時,容器(比如Tomcat)會讀web.xml配置檔案中的兩個節點<listener>和<contex-param>。
2. 接着容器會建立一個ServletContext(上下文),應用範圍内即整個WEB項目都能使用這個上下文。
3. 接着容器會将讀取到<context-param>轉化為鍵值對,并交給ServletContext。
4. 容器建立<listener></listener>中的類執行個體,即建立監聽(備注:listener定義的類可以是自定義的類但必須需要繼承ServletContextListener),一般配置contextLoaderListener extends ContextLoader implements ServletContextListener
5. Spring啟動主要的邏輯在父類ContextLoader的方法initWebApplicationContext實作。ContextLoaderListener的作用就是啟動web容器時自動裝配ApplicationContext的配置資訊。更細化一點講,Spring的啟動過程其實就是Spring IOC容器的啟動過程。
6. 在 web 容 器 啟 動 時 , 會 觸 發 容 器 初 始 化 事 件 , 此 時在 web 容 器 啟 動 時 , 會 觸 發 容 器 初 始 化 事 件 , 此 時
contextLoaderListener 會監聽到這個事件,其 contextInitialized )初始化方法會被調用,在這個方法中可以通過event.getServletContext().getInitParameter("contextConfigLocation") 來得到context-param 設定的值,spring 會初始
化一個啟動上下文,這個上下文被稱為根上下文,即 WebApplicationContext,這是一個接口類,确切的說,其實
際的實作類是 XmlWebApplicationContext。這個就是 spring 的 IoC 容器,其對應的 Bean 定義的配置由 web.xml 中
的 context-param 标簽指定。在這個類中還必須有一個contextDestroyed(ServletContextEvent event) 銷毀方法.用于關閉應用前釋放資源,比如說資料庫連接配接的關閉。
7. 在Spring IOC 容器啟動初始化完畢之後,會将其儲存到ServletContext中
8. 以上都是在WEB項目還沒有完全啟動起來的時候就已經完成了的工作。如果系統中有Servlet,則Servlet是在第一次發起請求的時候被執行個體化的,而且一般不會被容器銷毀,它可以服務于多個使用者的請求。是以,Servlet的初始化都要比上面提到的那幾個要遲。           
https://www.cnblogs.com/yaoyiyao/p/7198076.html https://blog.csdn.net/lieyanhaipo/article/details/58605545

Spring如何實作Bean注入?

預備春招面試複習第一篇-----SSM架構

Spring啟動的時候讀取應用程式提供的Bean配置資訊,并且在Spring容器中生成一份相應的Bean配置系統資料庫,然後根據這個張系統資料庫執行個體化Bean,裝配好Bean之間的依賴關系,為上層應用提供準備就緒的運作環境.

簡單過程:

  1. BeanDefinitionReader讀取Resource所指向的配置檔案資源,然後解析配置檔案。配置檔案中每一個

    <bean>

    解析成一個

    BeanDefinition

    對象,并儲存到

    BeanDefinitionRegistry

    中;
  2. 容器掃描BeanDefinitionRegistry中的BeanDefinition;調用InstantiationStrategy進行Bean執行個體化的工作;使用BeanWrapper完成Bean屬性的設定工作;
  3. 利用容器中注冊的 Bean 後處理器(實作 BeanPostProcessor 接口的 Bean)對已經完成屬性設定工作的 Bean 進行後續加工,直接裝配出一個準備就緒的 Bean。

單例Bean緩存池:Spring 在DefaultSingletonBeanRegistry類中提供了一個用于緩存單執行個體 Bean 的緩存器,它是一個用HashMap實作的緩存器,單執行個體的Bean以beanName為鍵儲存在這個HashMap中。

classpath與classpath*差別?

Spring 中哪些地方用到了 ThreadLocal,起到了什麼作用?

ThreadLocal與像synchronized這樣的鎖機制是不同的。首先,它們的應用場景與實作思路就不一樣,鎖更強調的是如何同步多個線程去正确地共享一個變量,ThreadLocal則是為了解決同一個變量如何不被多個線程共享。從性能開銷的角度上來講,如果鎖機制是用時間換空間的話,那麼ThreadLocal就是用空間換時間。

使用模闆類通路底層資料,根據持久化技術的不同,模闆類需要綁定資料連接配接或會話的資源。但這些資源本身是非線程安全的,也就是說它們不能在同一時刻被多個線程共享。雖然模闆類通過資源池擷取資料連接配接或會話,但資源池本身解決的是資料連接配接或會話的緩存問題,并非資料連接配接或會話的線程安全問題。

ThreadLocal 可以儲存線程本地化對象的容器。當運作在多線程環境的某個對象使用 ThreadLocal 維護變量時,ThreadLocal 為每個使用該變量的線程配置設定一個獨立的變量副本。是以每個線程都可以獨立地改變自己的副本,而不會影響其他線程所對應的副本。

舉例:

我們知道在一般情況下,隻有無狀态的Bean才可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder)中非線程安全的“狀态性對象”采用ThreadLocal進行封裝,讓它們也成為線程安全的“狀态性對象”,因為有狀态的Bean就能夠以singleton方式在多線程中正常工作了。

還有 事務也有.

解釋 Spring 支援的幾種 bean 的作用域

  1. singleton : bean 在每個 Spring ioc 容器中隻有一個執行個體。
  2. prototype:一個 bean 的定義可以有多個執行個體。
  3. request:每次 http 請求都會建立一個 bean,該作用域僅在基于 web 的 Spring ApplicationContext 情形下有

    效。

  4. session : 在 一 個 HTTP Session 中 , 一 個 bean 定 義 對 應 一 個 實 例 。 該 作 用 域 僅 在 基 于 web 的 Spring

    ApplicationContext 情形下有效。

  5. global-session:在一個全局的 HTTP Session 中,一個 bean 定義對應一個執行個體。該作用域僅在基于 web 的 Spring ApplicationContext 情形下有效。

預設的 Spring bean 的作用域是 Singleton.

Spring中的 Bean的生命周期:

https://www.jianshu.com/p/3944792a5fff

String AOP 和 MVC 攔截器差別?

String AOP 和 MVC 攔截器都是 AOP思想的具體實作

Filter過濾器:攔截web通路url位址。

Interceptor攔截器:攔截以 .action結尾的url,攔截Action的通路。

Spring AOP攔截器:隻能攔截Spring管理Bean的通路(業務層Service)

https://blog.csdn.net/heyeqingquan/article/details/71600676 https://blog.csdn.net/u010061060/article/details/80327348

Spring事務:有7種傳播行為,5種隔離方式

Spring事務管理分為 1. 程式設計式事務管理 2. 聲明式事務管理兩種

聲明式事務和程式設計式事務差別:

Spring 的聲明式事務管理在底層是建立在 AOP 的基礎之上的。其本質是對方法前後進行攔截,然後在目标方法開始之前建立或者加入一個事務,在執行完目标方法之後根據執行情況送出或者復原事務。聲明式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯代碼中摻雜事務管理的代碼,隻需在配置檔案中做相關的事務規則聲明(或通過等價的基于标注的方式),便可以将事務規則應用到業務邏輯中。Spring 強大的聲明式事務管理功能,這主要得益于 Spring 依賴注入容器和 Spring AOP 的支援。依賴注入容器為聲明式事務管理提供了基礎設施,使得 Bean 對于 Spring 架構而言是可管理的;而 Spring AOP 則是聲明式事務管理的直接實作者。和程式設計式事務相比,聲明式事務唯一不足地方是,後者的最細粒度隻能作用到方法級别,無法做到像程式設計式事務那樣可以作用到代碼塊級别。

事務不會滾原因?

https://www.cnblogs.com/zeng1994/p/8257763.html

.Spring 注解中@Resource 和@Autowired 的差別

1@Autowired 與@Resource 都可以用來裝配 bean. 都可以寫在字段上,或寫在 setter 方法上。

2@Autowired 預設按類型裝配(這個注解是屬于 spring 的),預設情況下必須要求依賴對象必須存在,如

果要允許 null 值,可以設定它的 required 屬性為 false,如:@Autowired(required=false) ,如果我們想使用名

稱裝配可以結合@Qualifier 注解進行使用

3@Resource(這個注解屬于 J2EE 的),預設按照名稱進行裝配,名稱可以通過 name 屬性進行指定,如果沒

有指定 name 屬性,當注解寫在字段上時,預設取字段名進行按照名稱查找,如果注解寫在 setter 方法上預設取屬性名進行裝配。 當找不到與名稱比對的 bean 時才按照類型進行裝配。但是需要注意的是,如果 name 屬性一旦指定,就隻會按照名稱進行裝配。

Spring中多線程 線程安全問題?

IOC中的Bean大多都是service,dao等,都是無狀态的,即自身沒有狀态,沒有共享變量,隻有一些操作,

資料庫Connection都作為函數的局部變量(局部變量是在使用者棧中的,而且使用者棧本身就是線程私有的記憶體區域,是以不存線上程安全問題),用完即關(或交還給連接配接池)。

http://www.importnew.com/27440.html

Spring 的 controller 是單例嗎,如何保證線程安全?

Spring controller 預設是單例的。是以是非線程安全的。

解決辦法:

1 在控制器中不使用執行個體變量
2 将控制器的作用域從單例改為原型,即在 spring 配置檔案 Controller 中聲明 scope="prototype",每
次都建立新的 controller。
3 在 Controller 中使用 ThreadLocal 變量。           

Spring中用到了哪些設計模式?

  1. 簡單工廠模式:由一個工廠根據傳入的參數,動态确定應該建立哪一個産品類.Spring中的BeanFactory就是簡單工廠的展現,根據傳入一個唯一的表示來擷取Bean對象.
  2. 工廠方法模式:工廠父類定義産品的接口,工廠子類負責建立具體的産品,把産品的執行個體化延遲到子類工廠中,由子類工廠決定具體執行個體化哪個對象.可以了解為:有了很多個工廠方法,自己需要哪一個産品,就調用目前産品的工廠方法,擷取相應的具體執行個體。Spring将應用程式的工廠對象交給Spring管理,這樣Spring管理的就不是普通的Bean,而是工廠Bean
  3. 單例模式:保證一個類僅有一個執行個體.Spring中的Bean預設是單例模式.

    下面對單件模式的懶漢式與餓漢式進行簡單介紹:

1、餓漢式:在程式啟動或單件模式類被加載的時候,單件模式執行個體就已經被建立。

2、懶漢式:當程式第一次通路單件模式執行個體時才進行建立。

如何選擇:如果單件模式執行個體在系統中經常會被用到,餓漢式是一個不錯的選擇。

反之如果單件模式在系統中會很少用到或者幾乎不會用到,那麼懶漢式是一個不錯的選擇。

  1. 代理模式:在Spring AOP 使用的JDK動态代理或者CGLib動态代理,對類進行方法級别的切面增強,實作面向切面程式設計.
  2. 觀察者模式:定義對象之間的一種一對多的依賴關系,當一個對象的狀态發生改變時,所有依賴于他的對象都得到通知并被自動更新,最常用的就是監聽器 (listener)
  3. 模闆方法模式:定義一個操作中的算法的骨架,而将一些步驟延遲到子類中。模闆方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。Spring 中的 JdbcTemplate 使用了模闆方法模式。

Spring MVC篇:

Spring MVC入口:

前端控制器DispatcherServlet

在web.xml的servlet中配置

. springmvc原理

SpringMVC的攔截器不同于Spring的攔截器,SpringMVC具有統一的入口DispatcherServlet,所有的請求都通過DispatcherServlet,所有的操作都是通過該servlet進行的順序操作,DispatcherServlet也沒有代理,同時SpringMVC管理的Controller也沒有代理。哪不難想到我們在執行controller之前做某些動作,執行完畢做某些動作,render完成做某些動作,都是servlet在開始便策劃好的。SpringMVC的攔截器對應提供了三個preHandle,postHandle,afterCompletion方法。
           

Spring MVC 流程:

預備春招面試複習第一篇-----SSM架構

再談一次攔截器:

一個攔截器執行個體在一個controller生命周期之内可以多次調用。但是缺點是隻能對controller請求進行攔截,對其他的一些比如直接通路靜态資源的請求則沒辦法進行攔截處理

攔截器在MVC中的流程圖:

預備春招面試複習第一篇-----SSM架構
https://blog.csdn.net/leisure_life/article/details/72793738

Spring MVC 中控制器Controller傳回值有哪些?

  1. void
  2. ModelAndView
  3. 字元串(真實路徑,重定向,轉發)
https://www.cnblogs.com/1102whw/p/8777586.html

3、資料源和連接配接池的差別

連接配接池是由容器(比如 Tomcat)提供的,用來管理池中的連接配接對象。

連接配接池自動配置設定連接配接對象并對閑置的連接配接進行回收。

連接配接池中的連接配接對象是由資料源(DataSource)建立的。

連接配接池(Connection Pool)用來管理連接配接(Connection)對象。

資料源(DataSource)用來連接配接資料庫,建立連接配接(Connection)對象。

java.sql.DataSource 接口負責建立與資料庫的連接配接,由 Tomcat 提供,将連接配接儲存在連接配接池中。

Mybatis緩存:

預設開啟一級緩存,一級緩存相對于一個SqlSession而言,各個SqlSession是互相隔離的,是以在參數和SQL完全一樣的情況下,我們使用同一個SqlSession對象調用同一個Mapper的方法,隻執行一次sql.

二級緩存是根據mapper的namespace劃分的,相同namespace的mapper查詢資料放在同一個區域,也就是根據命名空間來劃分,如果兩個mapper檔案的命名空間一樣,那麼他們共享一個mapper緩存.

#{}和${}的差別是什麼?

${}是 Properties 檔案中的變量占位符,它可以用于标簽屬性值和 sql 内部,屬于靜态文本替換,比如${driver}會被靜态替換為 com.mysql.jdbc.Driver。#{}是 sql 的參數占位符,Mybatis 會将 sql 中的#{}替換為?号,在 sql 執行前會使用 PreparedStatement 的參數設定方法,按序給 sql 的?号占位符設定參數值,比如 ps.setInt(0, parameterValue),#{item.name} 的 取 值 方 式 為 使 用 反 射 從 參 數 對 象 中 獲 取 item 對 象 的 name 屬 性 值 , 相 當 于param.getItem().getName()。

通常一個XML映射檔案都會寫一個Dao接口與之對應,這個Dao接口的工作原理是什麼?Dao接口裡的方法,參數不一樣,方法能重載嗎?

Dao接口,就是Mapper接口,接口的全限名,就是映射檔案的namespace的值,接口的方法名就是映射檔案中MappedStatement的id值,接口方法内的采納數就是傳遞給sql的參數,Mapper接口是沒有實作類的,當調用接口方法時,接口全限名+方法名憑借字元串作為key值,可唯一定位一個MapperStatement.dao接口的工作原理是jdk動态代理.Mybatis運作時使用jdk動态代理為Dao接口生成代理proxy對象,攔截接口方法,轉而執行MapperStatement所代表的sql,然後将sql執行結果傳回.

Dao接口中的方法,是不能重載的,因為全限名+方法名的儲存和尋找政策.

Mybatis 是如何進行分頁的?分頁插件的原理是什麼?

Mybatis 使用 RowBounds 對象進行分頁,它是針對 ResultSet 結果集執行的記憶體分頁,而非實體分頁,可以在 sql内直接書寫帶有實體分頁的參數來完成實體分頁功能,也可以使用分頁插件來完成實體分頁。

分頁插件的基本原理是使用 Mybatis 提供的插件接口,實作自定義插件,在插件的攔截方法内攔截待執行的 sql,然後重寫 sql,根據 dialect 方言,添加對應的實體分頁語句和實體分頁參數。

Mybatis 是否支援延遲加載?如果支援,它的實作原理是什麼?

Mybatis 僅支援 association 關聯對象和 collection 關聯集合對象的延遲加載, association 指的就是一對一, collection指的就是一對多查詢。在 Mybatis 配置檔案中,可以配置是否啟用延遲加載 lazyLoadingEnabled=true|false。原理是,使用 CGLIB 建立目标對象的代理對象,當調用目标方法時,進入攔截器方法,比如調用 a.getB().getName(),攔截器 invoke()方法發現 a.getB()是 null 值,那麼就會單獨發送事先儲存好的查詢關聯 B 對象的 sql,把 B 查詢上來,然後調用 a.setB(b),于是 a 的對象 b 屬性就有值了,接着完成 a.getB().getName()方法的調用。

未完待續