最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java面試題沖刺第八天--Spring框架2

 更新時(shí)間:2021年07月13日 16:42:38   作者:_陳哈哈  
這篇文章主要為大家分享了最有價(jià)值的三道Spring框架面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下

面試題1:聊一下你對AOP的理解吧?

AOP(Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一(兩外兩個(gè):IOC-控制反轉(zhuǎn)、DI-依賴注入)。AOP主要應(yīng)用于處理一些具有橫切性質(zhì)的系統(tǒng)級服務(wù),如日志收集、事務(wù)管理安全檢查(權(quán)限校驗(yàn))、緩存、對象池管理等。

那么AOP是干啥的?在我們的程序中,經(jīng)常存在一些系統(tǒng)性的需求,比如權(quán)限校驗(yàn)、記錄日志等,這些代碼會(huì)散落穿插在各個(gè)業(yè)務(wù)邏輯中,非常冗余且不利于維護(hù)。例如下面這個(gè)示意圖:

在這里插入圖片描述

有多少業(yè)務(wù)操作,就要寫多少重復(fù)的校驗(yàn)和日志記錄代碼,這顯然是無法接受的。當(dāng)然,用面向?qū)ο蟮乃枷?,我們可以把這些重復(fù)的代碼抽離出來,寫成公共方法,就是下面這樣:

在這里插入圖片描述

這樣,代碼冗余和可維護(hù)性的問題得到了解決,但每個(gè)業(yè)務(wù)方法中依然要依次手動(dòng)調(diào)用這些公共方法,也是略顯繁瑣。有沒有更好的方式呢?有的,那就是AOP,AOP將權(quán)限校驗(yàn)、日志記錄等非業(yè)務(wù)代碼完全提取出來,與業(yè)務(wù)代碼分離,并尋找節(jié)點(diǎn)切入業(yè)務(wù)代碼中:

在這里插入圖片描述

使用AOP的好處主要是降低模塊的耦合度、使系統(tǒng)容易擴(kuò)展、提高代碼復(fù)用性。

簡單地去理解,其實(shí)AOP要做三類事:

  • 在哪里切入,也就是權(quán)限校驗(yàn)等非業(yè)務(wù)操作在哪些業(yè)務(wù)代碼中執(zhí)行。
  • 在什么時(shí)候切入,是業(yè)務(wù)代碼執(zhí)行前還是執(zhí)行后。
  • 切入后做什么事,比如做權(quán)限校驗(yàn)、日志記錄等。

因此,AOP的體系可以梳理為下圖:

在這里插入圖片描述

AOP的一些概念:

  • 切入點(diǎn)(Pointcut):決定處理如權(quán)限校驗(yàn)、日志記錄等在何處切入業(yè)務(wù)代碼中(即織入切面)。切點(diǎn)分為execution方式和annotation方式。前者可以用路徑表達(dá)式指定哪些類織入切面,后者可以指定被哪些注解修飾的代碼織入切面。
  • 通知(Advice):我們也叫它處理(即“切面”對于某個(gè)“連接點(diǎn)”所產(chǎn)生的動(dòng)作),包括處理時(shí)機(jī)和處理內(nèi)容。處理內(nèi)容就是要做什么事,比如校驗(yàn)權(quán)限和記錄日志。處理時(shí)機(jī)就是在什么時(shí)機(jī)執(zhí)行處理內(nèi)容,分為前置處理(即業(yè)務(wù)代碼執(zhí)行前)、后置處理(業(yè)務(wù)代碼執(zhí)行后)等。
  • 切面(Aspect):即Pointcut和Advice。
  • 連接點(diǎn)(Joint point):是程序執(zhí)行的一個(gè)點(diǎn)。例如,一個(gè)方法的執(zhí)行或者一個(gè)異常的處理。在 Spring AOP 中,一個(gè)連接點(diǎn)總是代表一個(gè)方法執(zhí)行。
  • 織入(Weaving):就是通過動(dòng)態(tài)代理,在目標(biāo)對象方法中執(zhí)行處理內(nèi)容的過程。
  • 目標(biāo)對象(Target Object) :被一個(gè)或者多個(gè)切面所通知的對象。
  • AOP代理(AOP Proxy) 在Spring AOP中有兩種代理方式,JDK動(dòng)態(tài)代理和CGLIB代理。

追問1:Advice通知的類型有哪幾種?

在AOP術(shù)語中,切面的工作被稱為通知,實(shí)際上是程序執(zhí)行時(shí)要通過SpringAOP框架觸發(fā)的代碼段。

Spring切面可以應(yīng)用5種類型的通知:

  • 前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;
  • 后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時(shí)不會(huì)關(guān)心方法的輸出是什么;
  • 返回通知(After-returning ):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;
  • 異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知;
  • 環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為。

追問2:在同一個(gè)切面(Aspect)中,不同Advice的執(zhí)行順序

無異常情況下:

/*************不同Advice的執(zhí)行順序*****************/
1. around before advice
2. before advice
3. target method (執(zhí)行代碼段)
4. around after advice
5. after advice
/*******************前五個(gè)都一樣*******************/
6. afterReturning
/*************************************************/

有異常情況下:

/*************不同Advice的執(zhí)行順序*****************/
1. around before advice
2. before advice
3. target method (執(zhí)行代碼段)
4. around after advice
5. after advice
/*******************前五個(gè)都一樣*******************/
6. afterThrowing:異常發(fā)生
7. java.lang.RuntimeException: 異常發(fā)生
/*************************************************/

面試題2:AspectJ AOP 和 Spring AOP 有什么區(qū)別?

AOP實(shí)現(xiàn)的關(guān)鍵在于代理模式,AOP代理主要分為靜態(tài)代理動(dòng)態(tài)代理。

  • 靜態(tài)代理的代表為AspectJ;
  • 動(dòng)態(tài)代理則以Spring AOP為代表;

Spring AOP和AspectJ有不同的目標(biāo)。

  • Spring AOP旨在通過Spring IoC提供一個(gè)簡單的AOP實(shí)現(xiàn),以解決編碼人員面臨的最常出現(xiàn)的問題。這并不是完整的AOP解決方案,它只能用于Spring容器管理的beans
  • 另一方面,AspectJ是最原始的AOP實(shí)現(xiàn)技術(shù),提供了玩這個(gè)的AOP解決方案。AspectJ更為健壯,相對于Spring AOP也顯得更為復(fù)雜。值得注意的是,AspectJ能夠被應(yīng)用于所有的領(lǐng)域?qū)ο蟆?/li>

從原理上看:

Spring AOP

  • 基于動(dòng)態(tài)代理來實(shí)現(xiàn),默認(rèn)如果使用接口的,用JDK提供的動(dòng)態(tài)代理實(shí)現(xiàn),如果是方法則使用CGLIB實(shí)現(xiàn)
  • Spring AOP需要依賴IOC容器來管理,并且只能作用于Spring容器,使用純Java代碼實(shí)現(xiàn)
  • 在性能上,由于Spring AOP是基于動(dòng)態(tài)代理來實(shí)現(xiàn)的,在容器啟動(dòng)時(shí)需要生成代理實(shí)例,在方法調(diào)用上也會(huì)增加棧的深度,使得Spring AOP的性能不如AspectJ的那么好

AspectJ

AspectJ屬于靜態(tài)代理(織入),通過修改代碼來實(shí)現(xiàn),有如下幾個(gè)織入的時(shí)機(jī):

  1. 編譯期織入(Compile-time weaving): 如類 A 使用 AspectJ 添加了一個(gè)屬性,類 B 引用了它,這個(gè)場景就需要編譯期的時(shí)候就進(jìn)行織入,否則沒法編譯類 B。
  2. 編譯后織入(Post-compile weaving): 也就是已經(jīng)生成了 .class 文件,或已經(jīng)打成 jar 包了,這種情況我們需要增強(qiáng)處理的話,就要用到編譯后織入。
  3. 類加載后織入(Load-time weaving): 指的是在加載類的時(shí)候進(jìn)行織入,要實(shí)現(xiàn)這個(gè)時(shí)期的織入,有幾種常見的方法。1、自定義類加載器來干這個(gè),這個(gè)應(yīng)該是最容易想到的辦法,在被織入類加載到 JVM 前去對它進(jìn)行加載,這樣就可以在加載的時(shí)候定義行為了。2、在 JVM 啟動(dòng)的時(shí)候指定 AspectJ 提供的 agent:-javaagent:xxx/xxx/aspectjweaver.jar。

AspectJ可以做Spring AOP干不了的事情,它是AOP編程的完全解決方案,Spring AOP則致力于解決企業(yè)級開發(fā)中最普遍的AOP(方法織入)。而不是成為像AspectJ一樣的AOP方案。

因?yàn)锳spectJ在實(shí)際運(yùn)行之前就完成了織入,所以說它生成的類是沒有額外運(yùn)行時(shí)開銷的

指標(biāo)項(xiàng) Spring AOP AspectJ
使用語言 在純 Java 中實(shí)現(xiàn) 使用 Java 編程語言的擴(kuò)展實(shí)現(xiàn)
是否需要編譯 不需要單獨(dú)的編譯過程 除非設(shè)置 LTW,否則需要 AspectJ 編譯器 (ajc)
織入方式 只能使用運(yùn)行時(shí)織入 運(yùn)行時(shí)織入不可用。支持編譯時(shí)、編譯后和加載時(shí)織入
織入能力 功能不強(qiáng)-僅支持方法級編織 更強(qiáng)大 – 可以編織字段、方法、構(gòu)造函數(shù)、靜態(tài)初始值設(shè)定項(xiàng)、最終類/方法等……。
適用范圍 只能在由 Spring 容器管理的 bean 上實(shí)現(xiàn) 可以在所有域?qū)ο笊蠈?shí)現(xiàn)
切入點(diǎn)要求 僅支持方法執(zhí)行切入點(diǎn) 支持所有切入點(diǎn)
代理局限 代理是由目標(biāo)對象創(chuàng)建的, 并且切面應(yīng)用在這些代理上 在執(zhí)行應(yīng)用程序之前 (在運(yùn)行時(shí)) 前, 各方面直接在代碼中進(jìn)行織入
性能 比 AspectJ 慢很多 更好的性能
復(fù)雜度 易于學(xué)習(xí)和應(yīng)用 相對于 Spring AOP 來說更復(fù)雜

追問1:了解JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理的原理么?他倆有哪些區(qū)別?

Spring AOP中的動(dòng)態(tài)代理主要有兩種方式,JDK動(dòng)態(tài)代理CGLIB動(dòng)態(tài)代理

JDK動(dòng)態(tài)代理:是利用反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類,在調(diào)用具體方法前調(diào)用 InvokeHandler 來處理,他有一個(gè)限制,就是它只能為接口創(chuàng)建代理實(shí)例,那么對于沒有通過接口定義業(yè)務(wù)方法的類,就要用CGLIB動(dòng)態(tài)代理了。 CGLIB(Code Generation Library)動(dòng)態(tài)代理:是一個(gè)基于ASM的字節(jié)碼生成庫,它允許我們在運(yùn)行時(shí)對字節(jié)碼進(jìn)行修改和動(dòng)態(tài)生成。CGLIB通過繼承方式實(shí)現(xiàn)代理,在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用并順勢織入橫切邏輯。

JDK動(dòng)態(tài)代理具體實(shí)現(xiàn)原理:

  • 通過實(shí)現(xiàn)InvocationHandler接口創(chuàng)建自己的調(diào)用處理器;
  • 通過為Proxy類指定ClassLoader對象和一組interface來創(chuàng)建動(dòng)態(tài)代理;
  • 通過反射機(jī)制獲取動(dòng)態(tài)代理類的構(gòu)造函數(shù),其唯一參數(shù)類型就是調(diào)用處理器接口類型;
  • 通過構(gòu)造函數(shù)創(chuàng)建動(dòng)態(tài)代理類實(shí)例,構(gòu)造時(shí)調(diào)用處理器對象作為參數(shù)參入;

JDK動(dòng)態(tài)代理是面向接口的代理模式,如果被代理目標(biāo)沒有接口那么Spring也無能為力,Spring通過Java的反射機(jī)制生產(chǎn)被代理接口的新的匿名實(shí)現(xiàn)類,重寫了其中AOP的增強(qiáng)方法。

CGLib動(dòng)態(tài)代理:

利用ASM開源包,對代理對象類的class文件加載進(jìn)來,通過修改其字節(jié)碼生成子類來處理。

如果目標(biāo)對象實(shí)現(xiàn)了接口,默認(rèn)情況下會(huì)采用JDK的動(dòng)態(tài)代理實(shí)現(xiàn)AOP;

如果目標(biāo)對象實(shí)現(xiàn)了接口,可以強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP;

如果目標(biāo)對象沒有實(shí)現(xiàn)了接口,必須采用CGLIB庫,spring會(huì)自動(dòng)在JDK動(dòng)態(tài)代理和CGLIB之間轉(zhuǎn)換;

3、兩者對比:

  • JDK動(dòng)態(tài)代理是面向接口的。
  • CGLib動(dòng)態(tài)代理是通過字節(jié)碼底層繼承要代理類來實(shí)現(xiàn)(對指定的類生成一個(gè)子類,覆蓋其中的方法),因此如果被代理類被final關(guān)鍵字所修飾,會(huì)失敗。

面試題3:什么是基于Java的Spring注解配置? 給一些注解的例子

基于Java的配置,允許你在少量的Java注解的幫助下進(jìn)行大部分Spring配置,而非通過XML文件。當(dāng)然,也不不建議啥都用注解配置,畢竟如果修改就要?jiǎng)觕lass文件很麻煩。因此建議:不會(huì)修改、極少修改的用注解,會(huì)修改的用xml配置,如AOP的配置我就用XML,因?yàn)檫@個(gè)需要改的場景比較多。

@Configuration 注解為例,它用來標(biāo)記類可以當(dāng)做一個(gè)bean的定義,被Spring IOC容器使用。另一個(gè)是通過@Bean注解,它表示此方法將要返回一個(gè)對象,作為一個(gè)bean注冊進(jìn)Spring應(yīng)用上下文。

@Configuration
public class StudentConfig {
    @Bean
    public StudentBean myStudent() {
        return new StudentBean();
    }

怎樣開啟注解裝配呢?

注解裝配在默認(rèn)情況下是不開啟的,為了使用注解裝配,我們必須在Spring配置文件中配置 <context:annotation-config/>元素。

一些常見的注解:

1、@Component:

這將 java 類標(biāo)記為 bean。它是任何 Spring 管理組件的通用構(gòu)造型。spring 的組件掃描機(jī)制現(xiàn)在可以將其拾取并將其拉入應(yīng)用程序環(huán)境中。

2、@Controller:

這將一個(gè)類標(biāo)記為 Spring Web MVC 控制器。標(biāo)有它的 Bean 會(huì)自動(dòng)導(dǎo)入到 IoC 容器中。

3、@Service:

此注解是組件注解的特化。它不會(huì)對 @Component 注解提供任何其他行為。我們可以在服務(wù)層類中使用 @Service 而不是 @Component,因?yàn)樗愿玫姆绞街付艘鈭D。

4、@Repository:

這個(gè)注解是具有類似用途和功能的 @Component 注解的特化。它為 DAO 提供了額外的好處。它將 DAO 導(dǎo)入 IoC 容器,并使未經(jīng)檢查的異常有資格轉(zhuǎn)換為 Spring DataAccessException。

5、@Required :

這個(gè)注解表明bean的屬性必須在配置的時(shí)候設(shè)置,通過一個(gè)bean定義的顯式的屬性值或通過自動(dòng)裝配,若@Required注解的bean屬性未被設(shè)置,容器將拋出BeanInitializationException。

示例:

public class Employee {
    private String name;
    @Required
    public void setName(String name){
        this.name=name;
    }
    public string getName(){
        return name;
    }
}

6、@Autowired :

@Autowired默認(rèn)是按照類型裝配注入的,默認(rèn)情況下它要求依賴對象必須存在(可以設(shè)置它required屬性為false)。@Autowired 注解提供了更細(xì)粒度的控制,包括在何處以及如何完成自動(dòng)裝配。它的用法和@Required一樣,修飾setter方法、構(gòu)造器、屬性或者具有任意名稱和/或多個(gè)參數(shù)的PN方法。

public class Employee {
    private String name;
    @Autowired
    public void setName(String name) {
        this.name=name;
    }
    public string getName(){
        return name;
    }

@Autowired和@Resource的區(qū)別

@Autowired可用于:構(gòu)造函數(shù)、成員變量、Setter方法

@Autowired和@Resource之間的區(qū)別

@Autowired:默認(rèn)是按照類型裝配注入的,默認(rèn)情況下它要求依賴對象必須存在(可以設(shè)置它required屬性為false)。

@Resource:默認(rèn)是按照名稱來裝配注入的,只有當(dāng)找不到與名稱匹配的bean才會(huì)按照類型來裝配注入。

7、@Qualifier :

當(dāng)創(chuàng)建多個(gè)相同類型的 bean 并希望僅使用屬性裝配其中一個(gè) bean 時(shí),可以使用@Qualifier 注解和 @Autowired 通過指定應(yīng)該裝配哪個(gè)確切的 bean 來消除歧義。

8、@RequestMapping :

@RequestMapping 注解用于將特定 HTTP 請求方法映射到將處理相應(yīng)請求的控制器中的特定類/方法。此注釋可應(yīng)用于兩個(gè)級別:

  • 類級別:映射請求的URL
  • 方法級別:映射 URL 以及 HTTP 請求方法

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更對內(nèi)容!

相關(guān)文章

最新評論

荆门市| 嘉义市| 涟水县| 西丰县| 区。| 顺昌县| 马龙县| 灵宝市| 铜山县| 上思县| 额尔古纳市| 中卫市| 客服| 肇东市| 雷波县| 得荣县| 慈利县| 宿松县| 湖南省| 秭归县| 汉川市| 巴中市| 汶上县| 青铜峡市| 沧州市| 平江县| 齐齐哈尔市| 滨海县| 富裕县| 澜沧| 长丰县| 原阳县| 绥中县| 甘德县| 道孚县| 平塘县| 定州市| 白朗县| 金川县| 舞钢市| 丰镇市|