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

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)、記錄日志等,這些代碼會散落穿插在各個(gè)業(yè)務(wù)邏輯中,非常冗余且不利于維護(hù)。例如下面這個(gè)示意圖:

在這里插入圖片描述

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

在這里插入圖片描述

這樣,代碼冗余和可維護(hù)性的問題得到了解決,但每個(gè)業(yè)務(wù)方法中依然要依次手動調(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)生的動作),包括處理時(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):就是通過動態(tài)代理,在目標(biāo)對象方法中執(zhí)行處理內(nèi)容的過程。
  • 目標(biāo)對象(Target Object) :被一個(gè)或者多個(gè)切面所通知的對象。
  • AOP代理(AOP Proxy) 在Spring AOP中有兩種代理方式,JDK動態(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í)不會關(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)代理動態(tài)代理

  • 靜態(tài)代理的代表為AspectJ;
  • 動態(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

  • 基于動態(tài)代理來實(shí)現(xiàn),默認(rèn)如果使用接口的,用JDK提供的動態(tài)代理實(shí)現(xiàn),如果是方法則使用CGLIB實(shí)現(xiàn)
  • Spring AOP需要依賴IOC容器來管理,并且只能作用于Spring容器,使用純Java代碼實(shí)現(xiàn)
  • 在性能上,由于Spring AOP是基于動態(tài)代理來實(shí)現(xiàn)的,在容器啟動時(shí)需要生成代理實(shí)例,在方法調(diào)用上也會增加棧的深度,使得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 啟動的時(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動態(tài)代理和CGLIB動態(tài)代理的原理么?他倆有哪些區(qū)別?

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

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

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

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

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

CGLib動態(tài)代理:

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

如果目標(biāo)對象實(shí)現(xiàn)了接口,默認(rèn)情況下會采用JDK的動態(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會自動在JDK動態(tài)代理和CGLIB之間轉(zhuǎn)換;

3、兩者對比:

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

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

基于Java的配置,允許你在少量的Java注解的幫助下進(jìn)行大部分Spring配置,而非通過XML文件。當(dāng)然,也不不建議啥都用注解配置,畢竟如果修改就要動class文件很麻煩。因此建議:不會修改、極少修改的用注解,會修改的用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 會自動導(dǎo)入到 IoC 容器中。

3、@Service:

此注解是組件注解的特化。它不會對 @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定義的顯式的屬性值或通過自動裝配,若@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ì)粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@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才會按照類型來裝配注入。

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)文章

  • idea配置gradle全過程

    idea配置gradle全過程

    安裝Gradle首先需要解壓安裝包到指定目錄,隨后配置環(huán)境變量GRDLE_HOME和GRADLE_USER_HOME,這里的GRADLE_USER_HOME是指文件下載的路徑,安裝后,通過命令行輸入gradle -v來測試是否安裝成功,對于Idea的配置,需要通過File->Setting->Gradle進(jìn)行
    2024-10-10
  • 詳解spring自動掃描包

    詳解spring自動掃描包

    這篇文章主要介紹了spring自動掃描包的相關(guān)知識,本文通過實(shí)例相結(jié)合的形式給大家介紹的非常詳細(xì),感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-06-06
  • Java日期工具類時(shí)間校驗(yàn)實(shí)現(xiàn)

    Java日期工具類時(shí)間校驗(yàn)實(shí)現(xiàn)

    一般項(xiàng)目中需要對入?yún)⑦M(jìn)行校驗(yàn),比如必須是一個(gè)合法的日期,本文就來介紹一下Java日期工具類時(shí)間校驗(yàn)實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • 淺談Java中BIO、NIO和AIO的區(qū)別和應(yīng)用場景

    淺談Java中BIO、NIO和AIO的區(qū)別和應(yīng)用場景

    這篇文章主要介紹了Java中BIO、NIO和AIO的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • MyBatis配置文件元素示例詳解

    MyBatis配置文件元素示例詳解

    在MyBatis框架的核心配置文件中,<configuration>元素是配置文件的根元素,其他元素都要在<contiguration>元素內(nèi)配置,這篇文章主要介紹了MyBatis配置文件元素,需要的朋友可以參考下
    2023-06-06
  • Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作示例

    Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作示例

    這篇文章主要介紹了Java基于分治算法實(shí)現(xiàn)的線性時(shí)間選擇操作,涉及java排序、比較、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • Java Web會話技術(shù)Session的簡單使用

    Java Web會話技術(shù)Session的簡單使用

    在請求需要傳遞的信息比較多,使用Cookie技術(shù)就會增大請求的難度。而Session可以存儲對象、數(shù)組等信息,并且Session是存儲到服務(wù)器端的,在客戶端請求時(shí)只需要將session id一并攜帶給服務(wù)器端。本文將簡單的介紹如何使用Session
    2021-05-05
  • JVM的垃圾回收算法工作原理詳解

    JVM的垃圾回收算法工作原理詳解

    這篇文章主要介紹了JVM的垃圾回收算如何判斷對象是否可以被回收,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下
    2019-06-06
  • java構(gòu)造方法的作用總結(jié)

    java構(gòu)造方法的作用總結(jié)

    在本篇文章里小編給大家整理了關(guān)于java構(gòu)造方法的相關(guān)知識點(diǎn)以及實(shí)例代碼,有需要的朋友們可以學(xué)習(xí)下。
    2019-07-07
  • SpringCloud配置服務(wù)端的ConfigServer設(shè)置安全認(rèn)證

    SpringCloud配置服務(wù)端的ConfigServer設(shè)置安全認(rèn)證

    這篇文章主要為大家介紹了SpringCloud配置服務(wù)端的ConfigServer設(shè)置安全認(rèn)證,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08

最新評論