欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring的13個經(jīng)典面試題

 更新時間:2021年06月16日 15:44:20   作者:興趣使然的草帽路飛  
Spring框架是一個開放源代碼的J2EE應用程序框架,是針對bean的生命周期進行管理的輕量級容Spring解決了開發(fā)者在J2EE開發(fā)中遇到的許多常見的問題,我們這篇文章就來了解一下spring的面試題

1、JDK 動態(tài)代理和 CGLIB 代理有什么區(qū)別?

  • JDK 動態(tài)代理主要是針對類實現(xiàn)了某個接口,AOP 則會使用 JDK 動態(tài)代理。他基于反射的機制實現(xiàn),生成一個實現(xiàn)同樣接口的一個代理類,然后通過重寫方法的方式,實現(xiàn)對代碼的增強。
  • 而如果某個類沒有實現(xiàn)接口,AOP 則會使用 CGLIB 代理。他的底層原理是基于 ASM 第三方框架,通過修改字節(jié)碼生成一個子類,然后重寫父類的方法,實現(xiàn)對代碼的增強。

詳細分析參考:【Java萌新】面試常問設計模式——代理模式

2、FactoryBean、BeanFactory、ApplicationContext 有什么區(qū)別?

  • BeanFactory:是一個 Bean 工廠,使用簡單工廠模式,是 Spring IoC 容器頂級接口,是用于管理 Bean 的工廠,最核心的功能是通過 getBean() 方法加載 Bean 對象,通常我們不會直接使用該接口,而是使用其子接口 ApplicationContext
  • FactoryBean:是一個工廠 Bean,使用了工廠方法模式,實現(xiàn)該接口的類可以自己定義要創(chuàng)建的 Bean 實例,只需要實現(xiàn)它的 getObject() 方法即可。
  • ApplicationConext:是 BeanFactory 的子接口,擴展了 BeanFactory 的功能(高級 IOC 容器)。

3、說一說Spring Bean 的生命周期?

Spring Bean 生命周期簡單概括為 5 個階段:

  1. Bean 的實例化階段:創(chuàng)建一個 Bean 對象。
  2. Bean 實例的屬性填充階段:為 Bean 實例的屬性賦值。
  3. Bean 實例的初始化階段:對 Bean 實例進行初始化。
  4. Bean 實例的正常使用階段。
  5. Bean 實例的銷毀階段:容器關閉后,將 Bean 實例銷毀。

4、依賴注入的實現(xiàn)方法,以及相關注解?

構造方法注入、Setter 方法注入、接口注入 三種。

依賴注入的相關注解

  • @Autowired:自動按類型注入,如果有多個匹配則按照指定 Bean 的 id 查找,查找不到會報錯。
  • @Qualifier:在自動按照類型注入的基礎上再按照 Bean 的 id 注入,給變量注入時必須搭配@Autowired,給方法注入時可單獨使用。
  • @Resource :直接按照 Bean 的 id 注入,只能注入 Bean 類型。
  • @Value :用于注入基本數(shù)據(jù)類型和 String 類型。

5、什么是 Spring IOC ?

IOC 即控制反轉,簡單來說就是把原來代碼里需要實現(xiàn)的對象創(chuàng)建、依賴反轉給容器來幫忙實現(xiàn),Spring 中管理對象及其依賴關系都是通過 Spring 的 IOC 容器實現(xiàn)的。

IOC 的實現(xiàn)方式有依賴注入和依賴查找,由于依賴查找使用的很少,因此 IOC 也叫做依賴注入。

我們之前在創(chuàng)建一個對象的時候都是直接 new 一個對象實例,而有了 IOC ,對象實例的創(chuàng)建都交給容器去實現(xiàn)即可。

6、Spring IOC 容器的構建流程(初始化過程)

我們以 XML 方式的容器初始化為例:

通過 ClassPathXmlApplicationContext,去創(chuàng)建 ApplicationContext 容器對象:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

ClassPathXmlApplicationContext創(chuàng)建容器對象時,構造方法做了如下兩件事:

  • ① 調(diào)用父容器的構造方法為容器先設置好 Bean 資源加載器。
  • ② 調(diào)用父類的 setConfigLocations() 方法設置 Bean 配置信息的定位路徑
  • ③ 調(diào)用父類 AbstractApplicationContext 的 refresh() 方法啟動整個 IOC 容器對 Bean 的載入,在創(chuàng)建 IOC 容器前如果已有容器存在,需要把已有的容器銷毀,保證在 refresh() 方法后使用的是新創(chuàng)建的 IOC 容器。
  • 容器創(chuàng)建完成后,通過 loadBeanDefinitions() 方法加載 Bean 配置資源,該方法在加載資源時,首先解析配置文件路徑,讀取配置文件的內(nèi)容,然后通過 XML 解析器將 Bean 的配置信息轉換成文檔對象,之后按照 Spring Bean 的定義規(guī)則將文檔對象解析為 BeanDefinition 對象。
  • 接下來,將解析得到的 BeanDefinition 對象存入本地緩存(一個 HashMap 集合,key 是字符串,值是 BeanDefinition)中。
  • 最后,實例化所有的 Bean 實例(非懶加載):包括實例的創(chuàng)建,實例的屬性填充,實例的初始化。

7、依賴注入的過程(Bean 的加載流程)?

源碼分析可以參考我的文章:Spring源碼分析——Bean的加載

先來看下面幾行代碼:

public class BeanFactoryTest {
	public static void main(String[] args) {
		// 加載與解析XML配置文件,獲得BeanFactory:
		BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-bf.xml"));
		// 從BeanFactory中加載Bean對象
		Object a = beanFactory.getBean("componentA");
		Object b = beanFactory.getBean("componentB");
		System.out.println(a);// com.myspring.test.xmltest.ComponentA@1c93084c
		System.out.println(b);// com.myspring.test.xmltest.ComponentB@6ef888f6
	}
}
  • 首先通過 BeanFactory/ApplicationContext 調(diào)用getBean() 方法,來獲取 Bean 實例,該方法中,真正獲取 Bean 實例的是其內(nèi)層方法 doGetBean() 方法(真正實現(xiàn)從 IOC 容器獲取 Bean ,也是觸發(fā)依賴注入的地方)。
  • doGetBean() 方法中,主要做了以下幾件事:
    • beanName 的轉換方法 transformedBeanName(name),該方法的作用是,根據(jù)傳入的 name 參數(shù),獲取真正的 Bean 對應的 beanName。該方法的 name 參數(shù),有可能是一個別名(alias 屬性設置的別名),也有可能是一個&開頭的 name (工廠 Bean 對象)。
    • ② 嘗試從緩存中加載 Bean 的單實例,根據(jù)上面transformedBeanName方法轉換 name 后得到的真實 beanName,getSingleton(beanName)方法直接嘗試從緩存中獲取 Bean 的共享單實例,這時候獲取的是初始狀態(tài),尚未實例化。(從緩存中加載的流程就是,根據(jù) beanName 依次從一級緩存、二級緩存、三級緩存中嘗試獲取,通過三級緩存機制也可以有效避免循環(huán)依賴)
    • Bean 的實例化,getSingleton(beanName)方法執(zhí)行后,從緩存中得到了 Bean 的原始狀態(tài),接下來需要對該 Bean 進行實例化。
    • Bean 的初始化:尋找依賴(循環(huán)依賴檢查、依賴注入),因為 Bean 的初始化過程中很可能會用到某些屬性,而某些屬性很可能是動態(tài)配置的,并且配置的成依賴于其他的 Bean,那么此時應該先加載依賴的 Bean。所以在流程中,Spring初始化一個 Bean,會先初始化其依賴的所有的其他 Bean。
    • 根據(jù)不同的 scope 作用域創(chuàng)建 Bean,調(diào)用doCreateBean() 方法創(chuàng)建 Bean。
    • 類型轉換,根據(jù) scope 創(chuàng)建完 Bean 成功后,一般可以直接返回即可。但當傳入 doGetBean 方法中的 requireType 參數(shù)不為空時,意味著我們對最后返回的 Bean 有著類型上的要求。Spring 通過 類型轉換器 將第 ⑤ 步創(chuàng)建完成的 Bean 轉換為 requireType 指定的類型。

8、Bean 的作用范圍?

通過 scope 屬性指定 Bean 的作用范圍,包括:

  • singleton:單例模式,是默認作用域,不管收到多少 Bean 請求每個容器中只有一個唯一的 Bean 實例。
  • prototype:原型模式,和 singleton 相反,每次 Bean 請求都會創(chuàng)建一個新的實例。
  • request:每次 HTTP 請求都會創(chuàng)建一個新的 Bean 并把它放到 request 域中,在請求完成后 Bean 會失效并被垃圾收集器回收。
  • session:和 request 類似,確保每個 session 中有一個 Bean 實例,session 過期后 bean 會隨之失效。
  • global session:當應用部署在 Portlet 容器時,如果想讓所有 Portlet 共用全局存儲變量,那么該變量需要存儲在 global session 中。

9、Spring事務傳播機制有哪些?

  • REQUIRED:Spring 默認的事務傳播級別,如果上下文中已經(jīng)存在事務,那么就加入到事務中執(zhí)行,如果當前上下文中不存在事務,則新建事務執(zhí)行。
  • REQUIRES_NEW:每次都會新建一個事務,如果上下文中有事務,則將上下文的事務掛起,當新建事務執(zhí)行完成以后,上下文事務再恢復執(zhí)行。
  • SUPPORTS:如果上下文存在事務,則加入到事務執(zhí)行,如果沒有事務,則使用非事務的方式執(zhí)行。
  • MANDATORY:上下文中必須要存在事務,否則就會拋出異常。
  • NOT_SUPPORTED :如果上下文中存在事務,則掛起事務,執(zhí)行當前邏輯,結束后恢復上下文的事務。
  • NEVER:上下文中不能存在事務,否則就會拋出異常。
  • ESTED:嵌套事務。如果上下文中存在事務,則嵌套事務執(zhí)行,如果不存在事務,則新建事務。

10、Spring 的事務隔離級別有哪些?

Spring 的事務隔離級別底層其實是基于數(shù)據(jù)庫的,Spring 并沒有自己的一套隔離級別。

  • DEFAULT:使用數(shù)據(jù)庫的默認隔離級別。
  • READ_UNCOMMITTED:讀未提交,最低的隔離級別,會讀取到其他事務還未提交的內(nèi)容,存在臟讀。
  • READ_COMMITTED:讀已提交,讀取到的內(nèi)容都是已經(jīng)提交的,可以解決臟讀,但是存在不可重復讀。
  • REPEATABLE_READ:可重復讀,在一個事務中多次讀取時看到相同的內(nèi)容,可以解決不可重復讀,但是存在幻讀。
  • SERIALIZABLE:串行化,最高的隔離級別,對于同一行記錄,寫會加寫鎖,讀會加讀鎖。在這種情況下,只有讀讀能并發(fā)執(zhí)行,其他并行的讀寫、寫讀、寫寫操作都是沖突的,需要串行執(zhí)行??梢苑乐古K讀、不可重復度、幻讀,沒有并發(fā)事務問題。

11、AOP 是什么?AOP有哪些應用場景?

AOP 概念: 即面向切面編程,使用動態(tài)代理技術,在不修改源碼的基礎上對目標方法進行增強。

Spring 中的 AOP 目前支持 JDK 動態(tài)代理和 Cglib 代理。如果被代理對象實現(xiàn)了接口,則使用 JDK 動態(tài)代理,否則使用 Cglib 代理。另外,也可以通過指定 proxyTargetClass=true 來實現(xiàn)強制走 Cglib 代理。

應用場景:

  • 權限認證
  • 日志打印
  • 事務

12、AOP 的相關注解有哪些?

  • @Aspect:切面,聲明被注解標注的類是一個切面 Bean。
@Aspect
@Component
public class LogAspect {
    ...
}
  • @Pointcut:切入點,可以通過 @Pointcut("execution(* top.csp1999.service.impl.*.*(..))") 去指定要切入的目標對象,并對其符合表達式要求的方法進行增強。
@Pointcut("execution(* top.csp1999.service.impl.*.*(..))")
public void operationLog(){}
  • @Before:前置通知,指在某個連接點之前執(zhí)行的通知。
@Before("operationLog()")
public void doBeforeAdvice(JoinPoint joinPoint){
    System.out.println("進入方法前執(zhí)行.....");
}
  • @After:后置通知,指某個連接點退出時執(zhí)行的通知(不論正常返回還是異常退出)。
@After("operationLog()")
public void after(JoinPoint jp){
    System.out.println("方法最后執(zhí)行.....");
}
  • @AfterReturning:后置返回通知,指某連接點正常完成之后執(zhí)行的通知,返回值可以在返回后通知方法里接收。
@AfterReturning(returning = "ret", pointcut = "operationLog()")
public void doAfterReturning(Object ret) {
    System.out.println("方法的返回值 : " + ret);
}
  • @AfterThrowing:后置異常通知,指方法拋出異常導致退出時執(zhí)行的通知,和@AfterReturning只會有一個執(zhí)行,異常使用 throwing 屬性接收。
@AfterThrowing(throwing = "jp", pointcut = "operationLog()")
public void throwss(JoinPoint jp){
    System.out.println("方法異常時執(zhí)行.....");
}
  • @Around:環(huán)繞通知,可以用來在調(diào)用一個具體方法前和調(diào)用后來完成一些具體的任務。
@Around("operationLog()")
public Object run2(ProceedingJoinPoint joinPoint) throws Throwable {
    // 獲取方法參數(shù)值數(shù)組
    Object[] args = joinPoint.getArgs();
    // 得到其方法簽名
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    // 獲取方法參數(shù)類型數(shù)組
    Class[] paramTypeArray = methodSignature.getParameterTypes();
    if (EntityManager.class.isAssignableFrom(paramTypeArray[paramTypeArray.length - 1])) {
         // 如果方法的參數(shù)列表最后一個參數(shù)是entityManager類型,則給其賦值
         args[args.length - 1] = entityManager;
	}
     logger.info("請求參數(shù)為{}",args);
     // 動態(tài)修改其參數(shù)
     // 注意,如果調(diào)用joinPoint.proceed()方法,則修改的參數(shù)值不會生效,必須調(diào)用joinPoint.proceed(Object[] args)
     Object result = joinPoint.proceed(args);
     logger.info("響應結果為{}",result);
     // 如果這里不返回result,則目標對象實際返回值會被置為null
     return result;
}

13、AOP 的相關術語有什么?

Aspect:切面,一個關注點的模塊化,這個關注點可能會橫切多個對象。

Joinpoint:連接點,程序執(zhí)行過程中的某一行為,即業(yè)務層中的所有方法。。

Advice:通知,指切面對于某個連接點所產(chǎn)生的動作,包括前置通知、后置通知、返回后通知、異常通知和環(huán)繞通知。

Pointcut:切入點,指被攔截的連接點,切入點一定是連接點,但連接點不一定是切入點。

Proxy:代理,Spring AOP 中有 JDK 動態(tài)代理和 CGLib 代理,目標對象實現(xiàn)了接口時采用 JDK 動態(tài)代理,反之采用 CGLib 代理。

Target:代理的目標對象,指一個或多個切面所通知的對象。

Weaving :織入,指把增強應用到目標對象來創(chuàng)建代理對象的過程。

14、總結

文章會不定時更新,有時候一天多更新幾篇,還請三連支持一下,后續(xù)會億點點的更新!也希望大家可以關注腳本之家其他文章!

相關文章

  • SpringBoot中的RestTemplate使用方法詳解

    SpringBoot中的RestTemplate使用方法詳解

    這篇文章主要介紹了SpringBoot中的RestTemplate使用方法詳解,為了方便使用,這里我封裝成一個工具類來靜態(tài)調(diào)用RestTemplate,基于SpringBoot2.4.2版本,需要的朋友可以參考下
    2024-01-01
  • Java工具包之Lombok使用

    Java工具包之Lombok使用

    這篇文章主要介紹了Java工具包之Lombok使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • 淺談多線程中的鎖的幾種用法總結(必看)

    淺談多線程中的鎖的幾種用法總結(必看)

    下面小編就為大家?guī)硪黄獪\談多線程中的鎖的幾種用法總結(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • IDEA-SpringBoot項目Debug啟動不了(卡住不動)的原因分析

    IDEA-SpringBoot項目Debug啟動不了(卡住不動)的原因分析

    這篇文章主要介紹了IDEA-SpringBoot項目Debug啟動不了(卡住不動)的原因分析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • IDEA個性化設置注釋模板詳細講解版

    IDEA個性化設置注釋模板詳細講解版

    IDEA自帶的注釋模板不是太好用,我本人到網(wǎng)上搜集了很多資料系統(tǒng)的整理了一下制作了一份比較完整的模板來分享給大家,下面這篇文章主要給大家介紹了IDEA個性化設置注釋模板的相關資料,需要的朋友可以參考下
    2024-01-01
  • 在controller中如何設置接收參數(shù)的默認值

    在controller中如何設置接收參數(shù)的默認值

    這篇文章主要介紹了在controller中如何設置接收參數(shù)的默認值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java中使用Jedis操作Redis的示例代碼

    Java中使用Jedis操作Redis的示例代碼

    本篇文章主要介紹了Java中使用Jedis操作Redis的示例代碼,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12
  • Java面試題沖刺第二十七天--JVM2

    Java面試題沖刺第二十七天--JVM2

    這篇文章主要為大家分享了最有價值的三道關于JVM的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結構和算法相關的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java異常繼承結構解析_動力節(jié)點Java學院整理

    Java異常繼承結構解析_動力節(jié)點Java學院整理

    這篇文章主要介紹了Java異常繼承結構解析的相關知識,需要的朋友可以參考下
    2017-04-04
  • Java中System.currentTimeMillis()計算方式與時間單位轉換講解

    Java中System.currentTimeMillis()計算方式與時間單位轉換講解

    本文詳細講解了Java中System.currentTimeMillis()計算方式與時間單位轉換,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12

最新評論