电竞比分网-中国电竞赛事及体育赛事平台

分享

2021最新 Spring面試題精選(附刷題小程序)

 頭號碼甲 2021-05-09

目錄

1. Spring基礎(chǔ)

1.1 什么是 spring?

Spring是一個輕量級Java開發(fā)框架,最早有Rod Johnson創(chuàng)建,目的是為了解決企業(yè)級應(yīng)用開發(fā)的業(yè)務(wù)邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack(一站式)輕量級開源框架,為開發(fā)Java應(yīng)用程序提供全面的基礎(chǔ)架構(gòu)支持。Spring負(fù)責(zé)基礎(chǔ)架構(gòu),因此Java開發(fā)者可以專注于應(yīng)用程序的開發(fā)。

Spring最根本的使命是解決企業(yè)級應(yīng)用開發(fā)的復(fù)雜性,即簡化Java開發(fā)。

Spring可以做很多事情,它為企業(yè)級開發(fā)提供給了豐富的功能,但是這些功能的底層都依賴于它的兩個核心特性,也就是依賴注入(dependency injection,DI)和面向切面編程(aspect-oriented programming,AOP)。

為了降低Java開發(fā)的復(fù)雜性,Spring采取了以下4種關(guān)鍵策略

  • 基于POJO的輕量級和最小侵入性編程;

  • 通過依賴注入和面向接口實現(xiàn)松耦合;

  • 基于切面和慣例進行聲明式編程;

  • 通過切面和模板減少樣板式代碼。

1.2 Spring框架的設(shè)計目標(biāo),設(shè)計理念,和核心是什么?

  • Spring設(shè)計目標(biāo)
    Spring為開發(fā)者提供一個一站式輕量級應(yīng)用開發(fā)平臺;

  • Spring設(shè)計理念
    在JavaEE開發(fā)中,支持POJO和JavaBean開發(fā)方式,使應(yīng)用面向接口開發(fā),充分支持OO(面向?qū)ο螅┰O(shè)計方法;Spring通過IoC容器實現(xiàn)對象耦合關(guān)系的管理,并實現(xiàn)依賴反轉(zhuǎn),將對象之間的依賴關(guān)系交給IoC容器,實現(xiàn)解耦;

  • Spring框架的核心
    IoC容器和AOP模塊。通過IoC容器管理POJO對象以及他們之間的耦合關(guān)系;通過AOP以動態(tài)非侵入的方式增強服務(wù)。

IoC讓相互協(xié)作的組件保持松散的耦合,而AOP編程允許你把遍布于應(yīng)用各層的功能分離出來形成可重用的功能組件。

1.3 Spring 框架中都用到了哪些設(shè)計模式?

  1. 工廠模式:BeanFactory就是簡單工廠模式的體現(xiàn),用來創(chuàng)建對象的實例;

  2. 單例模式:Bean默認(rèn)為單例模式。

  3. 代理模式:Spring的AOP功能用到了JDK的動態(tài)代理和CGLIB字節(jié)碼生成技術(shù);

  4. 模板方法:用來解決代碼重復(fù)的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。

  5. 觀察者模式:定義對象鍵一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中l(wèi)istener的實現(xiàn)–ApplicationListener。

1.4 Spring Framework 中有多少個模塊,它們分別是什么?

Spring 總共大約有 20 個模塊, 由 1300 多個不同的文件構(gòu)成。 而這些組件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和設(shè)備支持(Instrmentation)數(shù)據(jù)訪問與集成(Data Access/Integeration) 、 Web、 消息(Messaging)Test等 幾 個模塊中。 以下是 Spring 5 的模塊結(jié)構(gòu)圖:

  • Spring 核心容器
    提供了框架的基本組成部分,包括控制反轉(zhuǎn)(Inversion of Control,IOC)和依賴注入(Dependency Injection,DI)功能。 它包含以下模塊:

    • Spring Core

    • Spring Bean

    • SpEL (Spring Expression Language)

    • Spring Context

  • AOP
    該層支持面向切面編程

  • 數(shù)據(jù)訪問/集成
    該層提供與數(shù)據(jù)庫交互的支持。它包含以下模塊:

    • JDBC (Java DataBase Connectivity)

    • ORM (Object Relational Mapping)

    • OXM (Object XML Mappers)

    • JMS (Java Messaging Service)

    • Transaction

  • Web
    該層提供了創(chuàng)建 Web 應(yīng)用程序的支持 。 它包含以下模塊:

    • Web

    • Servlet

    • WSocket

    • Portlet

  • Instrumentation
    該層為類檢測和類加載器實現(xiàn)提供支持。

  • Test
    該層為使用 JUnit 和 TestNG 進行測試提供支持。

  • 其他模塊

    • Messaging
      該模塊為 STOMP 提供支持 。 它還支持注解編程模型,該模型用于從

    • WebSocket
      客戶端路由和處理 STOMP 消息。

    • Aspects
      該模塊為與AspectJ的集成提供支持 。

1.5 spring context應(yīng)用上下文有什么作用?

這是基本的Spring模塊,提供spring 框架的基礎(chǔ)功能,BeanFactory 是 任何以spring為基礎(chǔ)的應(yīng)用的核心。Spring 框架建立在此模塊之上,它使Spring成為一個容器。

Bean 工廠是工廠模式的一個實現(xiàn),提供了控制反轉(zhuǎn)功能,用來把應(yīng)用的配置和依賴從真正的應(yīng)用代碼中分離。最常用的就是org.springframework.beans.factory.xml.XmlBeanFactory ,它根據(jù)XML文件中的定義加載beans。該容器從XML 文件讀取配置元數(shù)據(jù)并用它去創(chuàng)建一個完全配置的系統(tǒng)或應(yīng)用。

1.6 Spring 應(yīng)用程序有哪些不同組件?

Spring 應(yīng)用一般有以下組件:

  • 接口
    定義功能。

  • Bean 類
    它包含屬性,setter 和 getter 方法,函數(shù)等。

  • Spring 面向切面編程(AOP)
    提供面向切面編程的功能。

  • Bean 配置文件
    包含類的信息以及如何配置它們。

  • 用戶程序
    它使用接口

1.7 使用 Spring 有哪些方式?

  • 作為一個成熟的 Spring Web 應(yīng)用程序。

  • 作為第三方 Web 框架,使用 Spring Frameworks 中間層。

  • 用于遠(yuǎn)程使用。

  • 作為企業(yè)級 Java Bean,它可以包裝現(xiàn)有的 POJO(Plain Old Java Objects)。

1.8 Spring的優(yōu)缺點是什么?

  • 優(yōu)點

    • 方便解耦,簡化開發(fā)
      Spring就是一個大工廠,可以將所有對象的創(chuàng)建和依賴關(guān)系的維護,交給Spring管理。

    • AOP編程的支持
      Spring提供面向切面編程,可以方便的實現(xiàn)對程序進行權(quán)限攔截、運行監(jiān)控等功能。

    • 聲明式事務(wù)的支持
      只需要通過配置就可以完成對事務(wù)的管理,而無需手動編程。

    • 方便程序的測試
      Spring對Junit4支持,可以通過注解方便的測試Spring程序。

    • 方便集成各種優(yōu)秀框架
      Spring不排斥各種優(yōu)秀的開源框架,其內(nèi)部提供了對各種優(yōu)秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。

    • 降低JavaEE API的使用難度
      Spring對JavaEE開發(fā)中非常難用的一些API(JDBC、JavaMail、遠(yuǎn)程調(diào)用等),都提供了封裝,使這些API應(yīng)用難度大大降低。

  • 缺點

    • Spring明明一個很輕量級的框架,卻給人感覺大而全

    • Spring依賴反射,反射影響性能

    • 使用門檻升高,入門Spring需要較長時間

1.9 Spring框架中有哪些不同類型的事件?

Spring 提供了以下5種標(biāo)準(zhǔn)的事件:

  1. 上下文更新事件(ContextRefreshedEvent):
    在調(diào)用ConfigurableApplicationContext 接口中的refresh()方法時被觸發(fā)。

  2. 上下文開始事件(ContextStartedEvent):
    當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開始/重新開始容器時觸發(fā)該事件。

  3. 上下文停止事件(ContextStoppedEvent):
    當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時觸發(fā)該事件。

  4. 上下文關(guān)閉事件(ContextClosedEvent):
    當(dāng)ApplicationContext被關(guān)閉時觸發(fā)該事件。容器被關(guān)閉時,其管理的所有單例Bean都被銷毀。

  5. 請求處理事件(RequestHandledEvent):
    在Web應(yīng)用中,當(dāng)一個http請求(request)結(jié)束觸發(fā)該事件。如果一個bean實現(xiàn)了ApplicationListener接口,當(dāng)一個ApplicationEvent 被發(fā)布以后,bean會自動被通知。

2. Spring IoC

2.1 什么是 Spring IOC 容器?

控制反轉(zhuǎn)即IoC (Inversion of Control),它把傳統(tǒng)上由程序代碼直接操控的對象的調(diào)用權(quán)交給容器,通過容器來實現(xiàn)對象組件的裝配和管理。所謂的“控制反轉(zhuǎn)”概念就是對組件對象控制權(quán)的轉(zhuǎn)移,從程序代碼本身轉(zhuǎn)移到了外部容器。

Spring IOC 負(fù)責(zé)創(chuàng)建對象,管理對象(通過依賴注入(DI),裝配對象,配置對象,并且管理這些對象的整個生命周期

2.2 控制反轉(zhuǎn)(IoC)有什么作用?

  • 管理對象的創(chuàng)建和依賴關(guān)系的維護。對象的創(chuàng)建并不是一件簡單的事,在對象關(guān)系比較復(fù)雜時,如果依賴關(guān)系需要程序猿來維護的話,那是相當(dāng)頭疼的

  • 解耦,由容器去維護具體的對象

  • 托管了類的產(chǎn)生過程,比如我們需要在類的產(chǎn)生過程中做一些處理,最直接的例子就是代理,如果有容器程序可以把這部分處理交給容器,應(yīng)用程序則無需去關(guān)心類是如何完成代理的

2.3 可以通過多少種方式完成依賴注入?

通常,依賴注入可以通過三種方式完成,即:

  • 構(gòu)造函數(shù)注入

  • setter 注入

  • 接口注入(由于在靈活性和易用性比較差,現(xiàn)在從Spring4開始已被廢棄)

2.4 Spring 如何設(shè)計容器的,BeanFactory和ApplicationContext的關(guān)系詳解?

Spring 作者 Rod Johnson 設(shè)計了兩個接口用以表示容器。

  • BeanFactory

  • ApplicationContext

BeanFactory 簡單粗暴,可以理解為就是個 HashMap,Key 是 BeanName,Value 是 Bean 實例。通常只提供注冊(put),獲?。╣et)這兩個功能。我們可以稱之為 “低級容器”。

ApplicationContext 可以稱之為 “高級容器”。因為他比 BeanFactory 多了更多的功能。他繼承了多個接口。因此具備了更多的功能。例如資源的獲取,支持多種消息(例如 JSP tag 的支持),對 BeanFactory 多了工具級別的支持等待。所以你看他的名字,已經(jīng)不是 BeanFactory 之類的工廠了,而是 “應(yīng)用上下文”, 代表著整個大容器的所有功能。該接口定義了一個 refresh 方法,此方法是所有閱讀 Spring 源碼的人的最熟悉的方法,用于刷新整個容器,即重新加載/刷新所有的 bean。

當(dāng)然,除了這兩個大接口,還有其他的輔助接口,這里就不介紹他們了。

BeanFactory和ApplicationContext的關(guān)系

為了更直觀的展示 “低級容器” 和 “高級容器” 的關(guān)系,這里通過常用的 ClassPathXmlApplicationContext 類來展示整個容器的層級 UML 關(guān)系。

最上面的是 BeanFactory,下面的 3 個綠色的,都是功能擴展接口,這里就不展開講。

看下面的隸屬 ApplicationContext 粉紅色的 “高級容器”,依賴著 “低級容器”,這里說的是依賴,不是繼承哦。他依賴著 “低級容器” 的 getBean 功能。而高級容器有更多的功能:支持不同的信息源頭,可以訪問文件資源,支持應(yīng)用事件(Observer 模式)。

通常用戶看到的就是 “高級容器”。 但 BeanFactory 也非常夠用啦!

左邊灰色區(qū)域的是 “低級容器”, 只負(fù)載加載 Bean,獲取 Bean。容器其他的高級功能是沒有的。例如上圖畫的 refresh 刷新 Bean 工廠所有配置,生命周期事件回調(diào)等。

小結(jié)

說了這么多,不知道你有沒有理解Spring IoC? 這里小結(jié)一下:IoC 在 Spring 里,只需要低級容器就可以實現(xiàn),2 個步驟:

  1. 加載配置文件,解析成 BeanDefinition 放在 Map 里。

  2. 調(diào)用 getBean 的時候,從 BeanDefinition 所屬的 Map 里,拿出 Class 對象進行實例化,同時,如果有依賴關(guān)系,將遞歸調(diào)用 getBean 方法 —— 完成依賴注入。

上面就是 Spring 低級容器(BeanFactory)的 IoC。

至于高級容器 ApplicationContext,他包含了低級容器的功能,當(dāng)他執(zhí)行 refresh 模板方法的時候,將刷新整個容器的 Bean。同時其作為高級容器,包含了太多的功能。一句話,他不僅僅是 IoC。他支持不同信息源頭,支持 BeanFactory 工具類,支持層級容器,支持訪問文件資源,支持事件發(fā)布通知,支持接口回調(diào)等等。

2.5 IoC 的好處有哪些?

  1. 它將最小化應(yīng)用程序中的代碼量。

  2. 它將使您的應(yīng)用程序易于測試,因為它不需要單元測試用例中的任何單例

  3. 或JNDI 查找機制。

  4. 它以最小的影響和最少的侵入機制促進松耦合。

  5. 它支持即時的實例化和延遲加載服務(wù)。

2.6 Spring IoC 的實現(xiàn)機制

Spring 中的IoC 的實現(xiàn)原理就是工廠模式加反射機制 。
示例:

interface Fruit {
  public abstract void eat();
}

class Apple implements Fruit {
  public void eat(){
    System.out.println("Apple");
  }
}
class Orange implements Fruit {
  public void eat(){
    System.out.println("Orange");
  }
}
class Factory {
  public static Fruit getInstance(String ClassName) { 
    Fruit f=null;
    try {
      f=(Fruit)Class.forName(ClassName).newInstance(); } catch (Exception e) {
    e.printStackTrace();
    }
    return f;
  }
}

class Client {
  public static void main(String[] a) {
    Fruit f=Factory.getInstance("com.xxx.xxx.Apple");
    if(f!=null){
      f.eat();
    } 
  }
}

2.7 Spring 的 IoC支持哪些功能?

Spring 的 IoC 設(shè)計支持以下功能:

  • 依賴注入

  • 依賴檢查

  • 自動裝配

  • 支持集合

  • 指定初始化方法和銷毀方法

  • 支持回調(diào)某些方法(但是需要實現(xiàn) Spring 接口,略有侵入)

其中,最重要的就是依賴注入,從 XML 的配置上說,即 ref 標(biāo)簽。對應(yīng) Spring RuntimeBeanReference 對象。

對于 IoC 來說,最重要的就是容器。容器管理著 Bean 的生命周期,控制著 Bean 的依賴注入。

2.8 BeanFactory 和 ApplicationContext有什么區(qū)別?

BeanFactory和ApplicationContext是Spring的兩大核心接口,都可以當(dāng)做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

  • 依賴關(guān)系
    BeanFactory:是Spring里面最底層的接口,包含了各種Bean的定義,讀取bean配置文檔,管理bean的加載、實例化,控制bean的生命周期,維護bean之間的依賴關(guān)系。
    ApplicationContext接口作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:

    • 繼承MessageSource,因此支持國際化。

    • 統(tǒng)一的資源文件訪問方式。

    • 提供在監(jiān)聽器中注冊bean的事件。

    • 同時加載多個配置文件。

    • 載入多個(有繼承關(guān)系)上下文 ,使得每一個上下文都專注于一個特定的層次,比如應(yīng)用的web層。

  • 加載方式
    BeanFactroy采用的是延遲加載形式來注入Bean的,即只有在使用到某個Bean時(調(diào)用getBean()),才對該Bean進行加載實例化。這樣,我們就不能發(fā)現(xiàn)一些存在的Spring的配置問題。如果Bean的某一個屬性沒有注入,BeanFacotry加載后,直至第一次使用調(diào)用getBean方法才會拋出異常。
    ApplicationContext,它是在容器啟動時,一次性創(chuàng)建了所有的Bean。這樣,在容器啟動時,我們就可以發(fā)現(xiàn)Spring中存在的配置錯誤,這樣有利于檢查所依賴屬性是否注入。 ApplicationContext啟動后預(yù)載入所有的單實例Bean,通過預(yù)載入單實例bean ,確保當(dāng)你需要的時候,你就不用等待,因為它們已經(jīng)創(chuàng)建好了。
    相對于基本的BeanFactory,ApplicationContext 唯一的不足是占用內(nèi)存空間。當(dāng)應(yīng)用程序配置Bean較多時,程序啟動較慢。

  • 創(chuàng)建方式
    BeanFactory通常以編程的方式被創(chuàng)建,ApplicationContext還能以聲明的方式創(chuàng)建,如使用ContextLoader。

  • 注冊方式
    BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區(qū)別是:BeanFactory需要手動注冊,而ApplicationContext則是自動注冊。

2.9 ApplicationContext通常的實現(xiàn)是什么?

  • FileSystemXmlApplicationContext
    此容器從一個XML文件中加載beans的定義,XML Bean 配置文件的全路徑名必須提供給它的構(gòu)造函數(shù)。

  • ClassPathXmlApplicationContext
    此容器也從一個XML文件中加載beans的定義,這里,你需要正確設(shè)置classpath因為這個容器將在classpath里找bean配置。

  • WebXmlApplicationContext
    此容器加載一個XML文件,此文件定義了一個WEB應(yīng)用的所有bean。

2.10 什么是Spring的依賴注入?

控制反轉(zhuǎn)IoC是一個很大的概念,可以用不同的方式來實現(xiàn)。其主要實現(xiàn)方式有兩種:依賴注入依賴查找

依賴注入:相對于IoC而言,依賴注入(DI)更加準(zhǔn)確地描述了IoC的設(shè)計理念。所謂依賴注入(Dependency Injection),即組件之間的依賴關(guān)系由容器在應(yīng)用系統(tǒng)運行期來決定,也就是由容器動態(tài)地將某種依賴關(guān)系的目標(biāo)對象實例注入到應(yīng)用系統(tǒng)中的各個關(guān)聯(lián)的組件之中。組件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關(guān)系。

2.11 依賴注入的基本原則是什么?

依賴注入的基本原則是:應(yīng)用組件不應(yīng)該負(fù)責(zé)查找資源或者其他依賴的協(xié)作對象。配置對象的工作應(yīng)該由IoC容器負(fù)責(zé),“查找資源”的邏輯應(yīng)該從應(yīng)用組件的代碼中抽取出來,交給IoC容器負(fù)責(zé)。容器全權(quán)負(fù)責(zé)組件的裝配,它會把符合依賴關(guān)系的對象通過屬性(JavaBean中的setter)或者是構(gòu)造器傳遞給需要的對象。

2.12 依賴注入有什么優(yōu)勢?

依賴注入之所以更流行是因為它是一種更可取的方式:讓容器全權(quán)負(fù)責(zé)依賴查詢,受管組件只需要暴露JavaBean的setter方法或者帶參數(shù)的構(gòu)造器或者接口,使容器可以在初始化時組裝對象的依賴關(guān)系。其與依賴查找方式相比,主要優(yōu)勢為:

  • 查找定位操作與應(yīng)用代碼完全無關(guān)。

  • 不依賴于容器的API,可以很容易地在任何容器以外使用應(yīng)用對象。

  • 不需要特殊的接口,絕大多數(shù)對象可以做到完全不必依賴容器。

2.13 構(gòu)造器依賴注入和 Setter方法注入有什么區(qū)別?

構(gòu)造函數(shù)注入setter 注入
沒有部分注入有部分注入
不會覆蓋 setter 屬性會覆蓋 setter 屬性
任意修改都會創(chuàng)建一個新實例任意修改不會創(chuàng)建一個新實例
適用于設(shè)置很多屬性適用于設(shè)置少量屬性

兩種依賴方式都可以使用,構(gòu)造器注入和Setter方法注入。最好的解決方案是用構(gòu)造器參數(shù)實現(xiàn)強制依賴,setter方法實現(xiàn)可選依賴。

3. Spring Beans

3.1 什么是 spring bean?

  1. 它們是構(gòu)成用戶應(yīng)用程序主干的對象。

  2. Bean 由 Spring IoC 容器管理。

  3. 它們由 Spring IoC 容器實例化,配置,裝配和管理。

  4. Bean 是基于用戶提供給容器的配置元數(shù)據(jù)創(chuàng)建。

3.2 spring 提供了哪些配置方式?

  • 基于xml配置
    bean 所需的依賴項和服務(wù)在 XML 格式的配置文件中指定 。 這些配置文件通常包含許多 bean 定義和特定于應(yīng)用程序的配置選項。 它們通常以 bean 標(biāo)簽開頭。例如:

    <bean id="studentbean" class="org.edureka.firstSpring.StudentBean"> 
      <property name="name" value="Edureka"></property>
    </bean>
  • 基于注解配置
    您可以通過在相關(guān)的類,方法或字段聲明上使用注解,將 bean 配置為組件類本身,而不是使用 XML 來描述 bean 裝配。 默認(rèn)情況下, Spring 容器中未打開注解裝配。 因此,您需要在使用它之前在 Spring 配置文件中啟用它。 例如:

    <beans>
    <context:annotation-config/>
    <!-- bean definitions go here -->
    </beans>
  • 基于Java API 配置
    Spring的Java配置是通過使用@Bean和@Configuration來實現(xiàn) 。

    例如:

    @Configuration
    public class StudentConfig {
      @Bean
      public StudentBean myStudent() {
        return new StudentBean();
      }
    }
    • @Bean
      注解扮演與

      元素相同的角色 。
    • @Configuration 類
      允許通過簡單地調(diào)用同一個類中的其他@Bean方法來定義bean間依賴關(guān)系。

3.3 spring 支持幾種 bean scope?

Spring bean 支持5種scope:

  • Singleton
    每個 Spring IoC 容器僅有一個單實例 。

  • Prototype
    每次請求都會產(chǎn)生一個新的實例。

  • Request
    每一次 HTTP 請求都會產(chǎn)生一個新的實例,并且該 bean 僅在當(dāng)前 HTTP 請求內(nèi)有效。

  • Session
    每一次 HTTP 請求都會產(chǎn)生一個新的 bean,同時該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效。

  • Global-session
    類似于標(biāo)準(zhǔn)的 HTTP Session 作用域,不過它僅僅在基于 portlet 的 web 應(yīng)用中才有意義 。 Portlet 規(guī)范定義了全局 Session 的概念,它被所有構(gòu)成某個 portlet web 應(yīng)用的各種不同的 portlet 所共享。 在 global session 作用域中定義的 bean 被限定于全局 portlet Session 的生命周期范圍內(nèi)。 如果你在 web 中使用 global session 作用域來標(biāo)識 bean,那么 web 會自動當(dāng)成 session 類型來使用。

僅當(dāng)用戶使用支持Web的ApplicationContext時,最后三個才可用 。

3.4 spring bean 容器的生命周期是什么樣的?

spring bean 容器的生命周期流程如下:

1、Spring 容器根據(jù)配置中的 bean 定義中實例化 bean。
2、Spring 使用依賴注入填充所有屬性,如 bean 中所定義的配置。
3、如果 bean 實現(xiàn) BeanNameAware 接口,則工廠通過傳遞 bean 的 ID 來調(diào)用setBeanName()。
4、如果 bean 實現(xiàn) BeanFactoryAware 接口,工廠通過傳遞自身的實例來調(diào)用 setBeanFactory()。
5、如果存在與 bean 關(guān)聯(lián)的任何BeanPostProcessors,則調(diào)用 preProcessBeforeInitialization() 方法 。
6、如果為 bean 指定了 init 方法(的 init-method 屬性),那么將調(diào)用它。
7、最后,如果存在與 bean 關(guān)聯(lián)的任何 BeanPostProcessors,則將調(diào)用 postProcessAfterInitialization() 方法。
8、如果 bean 實現(xiàn) DisposableBean 接口,當(dāng) spring 容器關(guān)閉時,會調(diào)用 destory()。
9、如果為 bean 指定了 destroy 方法(的 destroy-method 屬性),那么將調(diào)用它。

3.5 什么是 spring 的內(nèi)部 bean?

只有將 bean 用作另一個 bean 的屬性時,才能將 bean 聲明為內(nèi)部 bean。為了定義 bean, Spring 的基于 XML 的配置元數(shù)據(jù)在或 中提供了元素的使用 。 內(nèi)部 bean 總是匿名的,它們總是作為原型。

例如,假設(shè)我們有一個 Student 類,其中引用了 Person 類。 這里我們將只創(chuàng)建一個 Person 類實例并在 Student 中使用它。

Student.java

public class Student {
  private Person person;
  //Setters and Getters
}

Person.java

public class Person {
  private String name;
  private String address;
  //Setters and Getters
}

bean.xml

<bean id=“StudentBean" class="com.lupf.Student"> 
  <property name="person">
    <!--This is inner bean -->
    <bean class="com.lupf.Person">
      <property name="name" value=“Scott"></property> <property name="address" value="Bangalore"></property>
    </bean>
  </property>
</bean>

3.6 什么是bean裝配?什么是bean的自動裝配?

裝配,或bean裝配是指在Spring容器中把bean組裝到一起,前提是容器需要知道bean的依賴關(guān)系,如何通過依賴注入來把它們裝配到一起。

在Spring框架中,在配置文件中設(shè)定bean的依賴關(guān)系是一個很好的機制,Spring 容器能夠自動裝配相互合作的bean,這意味著容器不需要和配置,能通過Bean工廠自動處理bean之間的協(xié)作。這意味著 Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關(guān)系。自動裝配可以設(shè)置在每個bean上,也可以設(shè)定在特定的bean上。

3.7 自動裝配有哪些方式?

Spring容器能夠自動裝配bean。也就是說,可以通過檢查BeanFactory的內(nèi)容讓Spring自動解析bean的協(xié)作者。

自動裝配的不同模式:

  • no
    這是默認(rèn)設(shè)置,表示沒有自動裝配 。 應(yīng)使用顯式 bean 引用進行裝配 。

  • byName
    它根據(jù) bean 的名稱注入對象依賴項 。 它匹配并裝配其屬性與 XML 文件中由相同名稱定義的 bean。

  • byType
    它根據(jù)類型注入對象依賴項。如 果屬性的類型與 XML 文件中的一個 bean 名稱匹配,則匹配并裝配屬性。

  • 構(gòu)造函數(shù)
    它通過調(diào)用類的構(gòu)造函數(shù)來注入依賴項 。它有大量的參數(shù) 。

  • autodetect
    首先容器嘗試通過構(gòu)造函數(shù)使用 autowire 裝配,如果不能,則嘗試通過 byType 自動裝配。

3.8 自動裝配有什么局限?

  • 覆蓋的可能性
    您始終可以使用

    和設(shè)置指定依賴項,這將覆蓋自動裝配。
  • 基本元數(shù)據(jù)類型
    簡單屬性(如原數(shù)據(jù)類型,字符串和類)無法自動裝配。

  • 模糊特性
    自動裝配不如顯式裝配精確,如果有可能,建議使用顯式裝配。

3.9 使用@Autowired注解自動裝配的過程是怎樣的?

使用@Autowired注解來自動裝配指定的bean。在使用@Autowired注解之前需要在Spring配置文件進行配置,<context:annotation-config />。

在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor后置處理器,當(dāng)容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,并裝配給該對象的屬性。在使用@Autowired時,首先在容器中查詢對應(yīng)類型的bean:

  • 如果查詢結(jié)果剛好為一個,就將該bean裝配給@Autowired指定的數(shù)據(jù);

  • 如果查詢的結(jié)果不止一個,那么@Autowired會根據(jù)名稱來查找;

  • 如果上述查找的結(jié)果為空,那么會拋出異常。解決方法時,使用required=false。

3.10 Spring配置文件包含了哪些信息?

Spring配置文件是個XML 文件,這個文件包含了類信息,描述了如何配置它們,以及如何相互調(diào)用。

3.11 Spring基于xml注入bean的幾種方式

  1. Set方法注入;

  2. 構(gòu)造器注入:

    • 通過index設(shè)置參數(shù)的位置;

    • 通過type設(shè)置參數(shù)類型;

  3. 靜態(tài)工廠注入;

  4. 實例工廠;

3.12 Spring框架中的單例bean是線程安全的嗎?

不是,Spring框架中的單例bean不是線程安全的。

spring 中的 bean 默認(rèn)是單例模式,spring 框架并沒有對單例 bean 進行多線程的封裝處理。

實際上大部分時候 spring bean 無狀態(tài)的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態(tài)的話(比如 view model 對象),那就要開發(fā)者自己去保證線程安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當(dāng)于 new Bean()了,所以就可以保證線程安全了。

  • 有狀態(tài)就是有數(shù)據(jù)存儲功能。

  • 無狀態(tài)就是不會保存數(shù)據(jù)。

3.13 Spring如何處理線程并發(fā)問題?

在一般情況下,只有無狀態(tài)的Bean才可以在多線程環(huán)境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域,因為Spring對一些Bean中非線程安全狀態(tài)采用ThreadLocal進行處理,解決線程安全問題。

ThreadLocal和線程同步機制都是為了解決多線程中相同變量的訪問沖突問題。同步機制采用了“時間換空間”的方式,僅提供一份變量,不同的線程在訪問前需要獲取鎖,沒獲得鎖的線程則需要排隊。而ThreadLocal采用了“空間換時間”的方式。

ThreadLocal會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數(shù)據(jù)的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

3.14 bean生命周期方法有哪些? 你能重載它們嗎?

有兩個重要的bean 生命周期方法:

  • 第一個是setup :
    它是在容器加載bean的時候被調(diào)用。

  • 第二個方法是 teardown :
    它是在容器卸載類的時候被調(diào)用。

bean 標(biāo)簽有兩個重要的屬性(init-methoddestroy-method)。用它們你可以自己定制初始化和注銷方法。它們也有相應(yīng)的注解(@PostConstruct@PreDestroy)。

3.15 在 Spring中如何注入一個java集合?

Spring提供以下幾種集合的配置元素:

  1. 類型用于注入一列值,允許有相同的值。

  2. 類型用于注入一組值,不允許有相同的值。

  3. 類型用于注入一組鍵值對,鍵和值都可以為任意類型。

  4. 類型用于注入一組鍵值對,鍵和值都只能為String類型。

3.16 你可以在Spring中注入一個null 和一個空字符串嗎?

可以。

4. Spring注解

4.1 什么是基于Java的Spring注解配置?

基于Java的配置,允許你在少量的Java注解的幫助下,進行你的大部分Spring配置而非通過XML文件。

以@Configuration 注解為例,它用來標(biāo)記類可以當(dāng)做一個bean的定義,被Spring IOC容器使用。

另一個例子是@Bean注解,它表示此方法將要返回一個對象,作為一個bean注冊進Spring應(yīng)用上下文。

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

4.2 怎樣開啟注解裝配?

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

4.3 @Component, @Controller, @Repository, @Service 有何區(qū)別?

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

  • @Controller:
    這將一個類標(biāo)記為 Spring Web MVC 控制器。標(biāo)有它的 Bean 會自動導(dǎo)入到 IoC 容器中。

  • @Service:
    此注解是組件注解的特化。它不會對 @Component 注解提供任何其他行為。您可以在服務(wù)層類中使用 @Service 而不是 @Component,因為它以更好的方式指定了意圖。

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

4.4 @Required 注解有什么作用?

這個注解表明bean的屬性必須在配置的時候設(shè)置,通過一個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;
    }
}

4.5 @Autowired 注解有什么作用?

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

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

4.6 @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才會按照類型來裝配注入。

4.7 @Qualifier注解有什么作用?

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

4.8 @RequestMapping注解有什么用?

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

  • 類級別:
    映射請求的 URL

  • 方法級別:

    • 映射 URL

    • HTTP 請求方法

5. Spring數(shù)據(jù)訪問

5.1 解釋對象/關(guān)系映射集成模塊

Spring 通過提供ORM模塊,支持我們在直接JDBC之上使用一個對象/關(guān)系映射映射(ORM)工具,Spring 支持集成主流的ORM框架,如Hiberate,JDO和 iBATIS,JPA,TopLink,JDO,OJB 。Spring的事務(wù)管理同樣支持以上所有ORM框架及JDBC。

5.2 在Spring框架中如何更有效地使用JDBC?

使用Spring JDBC 框架,資源管理和錯誤處理的代價都會被減輕。所以開發(fā)者只需寫statements 和 queries從數(shù)據(jù)存取數(shù)據(jù),JDBC也可以在Spring框架提供的模板類的幫助下更有效地被使用,這個模板叫JdbcTemplate

5.3 解釋JDBC抽象和DAO模塊的作用是什么?

通過使用JDBC抽象和DAO模塊,保證數(shù)據(jù)庫代碼的簡潔,并能避免數(shù)據(jù)庫資源錯誤關(guān)閉導(dǎo)致的問題,它在各種不同的數(shù)據(jù)庫的錯誤信息之上,提供了一個統(tǒng)一的異常訪問層。它還利用Spring的AOP 模塊給Spring應(yīng)用中的對象提供事務(wù)管理服務(wù)。

5.4 Spring DAO 有什么用?

Spring DAO(數(shù)據(jù)訪問對象) 使得 JDBC,Hibernate 或 JDO 這樣的數(shù)據(jù)訪問技術(shù)更容易以一種統(tǒng)一的方式工作。這使得用戶容易在持久性技術(shù)之間切換。它還允許您在編寫代碼時,無需考慮捕獲每種技術(shù)不同的異常。

5.5 Spring JDBC API 中存在哪些類?

  1. JdbcTemplate

  2. SimpleJdbcTemplate

  3. NamedParameterJdbcTemplate

  4. SimpleJdbcInsert

  5. SimpleJdbcCall

5.6 JdbcTemplate是什么?

JdbcTemplate 類提供了很多便利的方法解決諸如把數(shù)據(jù)庫數(shù)據(jù)轉(zhuǎn)變成基本數(shù)據(jù)類型或?qū)ο?,?zhí)行寫好的或可調(diào)用的數(shù)據(jù)庫操作語句,提供自定義的數(shù)據(jù)錯誤處理。

5.7 Spring通過什么方式訪問Hibernate?

在Spring中有兩種方式訪問Hibernate:

  • 使用 Hibernate 模板和回調(diào)進行控制反轉(zhuǎn)

  • 擴展 HibernateDAOSupport 并應(yīng)用 AOP 攔截器節(jié)點

5.8 如何通過HibernateDaoSupport將Spring和Hibernate結(jié)合起來?

用Spring的 SessionFactory 調(diào)用 LocalSessionFactory。集成過程分三步:

  • 配置the Hibernate SessionFactory

  • 繼承HibernateDaoSupport實現(xiàn)一個DAO

  • 在AOP支持的事務(wù)中裝配

5.9 Spring支持的事務(wù)管理類型是什么?spring 事務(wù)實現(xiàn)方式有哪些?

Spring支持兩種類型的事務(wù)管理:

  • 編程式事務(wù)管理
    這意味你通過編程的方式管理事務(wù),給你帶來極大的靈活性,但是難維護。

  • 聲明式事務(wù)管理
    這意味著你可以將業(yè)務(wù)代碼和事務(wù)管理分離,你只需用注解和XML配置來管理事務(wù)。

5.10 Spring事務(wù)的實現(xiàn)方式和實現(xiàn)原理是什么?

Spring事務(wù)的本質(zhì)其實就是數(shù)據(jù)庫對事務(wù)的支持,沒有數(shù)據(jù)庫的事務(wù)支持,spring是無法提供事務(wù)功能的。真正的數(shù)據(jù)庫層的事務(wù)提交和回滾是通過binlog或者redo log實現(xiàn)的。

5.11 Spring的事務(wù)傳播行為有那些?

Spring事務(wù)的傳播行為說的是,當(dāng)多個事務(wù)同時存在的時候,spring如何處理這些事務(wù)的行為。

  1. PROPAGATION_REQUIRED:
    如果當(dāng)前沒有事務(wù),就創(chuàng)建一個新事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),該設(shè)置是最常用的設(shè)置。

  2. PROPAGATION_SUPPORTS:
    支持當(dāng)前事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),如果當(dāng)前不存在事務(wù),就以非事務(wù)執(zhí)行。

  3. PROPAGATION_MANDATORY:
    支持當(dāng)前事務(wù),如果當(dāng)前存在事務(wù),就加入該事務(wù),如果當(dāng)前不存在事務(wù),就拋出異常。

  4. PROPAGATION_REQUIRES_NEW:
    創(chuàng)建新事務(wù),無論當(dāng)前存不存在事務(wù),都創(chuàng)建新事務(wù)。

  5. PROPAGATION_NOT_SUPPORTED:
    以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。

  6. PROPAGATION_NEVER:
    以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。

  7. PROPAGATION_NESTED:
    如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則按REQUIRED屬性執(zhí)行。

5.12 說一下 Spring 的事務(wù)隔離?

spring 有五大隔離級別,默認(rèn)值為 ISOLATION_DEFAULT(使用數(shù)據(jù)庫的設(shè)置),其他四個隔離級別和數(shù)據(jù)庫的隔離級別一致:

  1. ISOLATION_DEFAULT:用底層數(shù)據(jù)庫的設(shè)置隔離級別,數(shù)據(jù)庫設(shè)置的是什么我就用什么;

  2. ISOLATION_READ_UNCOMMITTED:未提交讀,最低隔離級別、事務(wù)未提交前,就可被其他事務(wù)讀?。〞霈F(xiàn)幻讀、臟讀、不可重復(fù)讀);

  3. ISOLATION_READ_COMMITTED:提交讀,一個事務(wù)提交后才能被其他事務(wù)讀取到(會造成幻讀、不可重復(fù)讀),SQL server 的默認(rèn)級別;

  4. ISOLATION_REPEATABLE_READ:可重復(fù)讀,保證多次讀取同一個數(shù)據(jù)時,其值都和事務(wù)開始時候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(會造成幻讀),MySQL 的默認(rèn)級別;

  5. ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復(fù)讀、幻讀。

臟讀 :表示一個事務(wù)能夠讀取另一個事務(wù)中還未提交的數(shù)據(jù)。比如,某個事務(wù)嘗試插入記錄 A,此時該事務(wù)還未提交,然后另一個事務(wù)嘗試讀取到了記錄 A。

不可重復(fù)讀 :是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)。

幻讀 :指同一個事務(wù)內(nèi)多次查詢返回的結(jié)果集不一樣。比如同一個事務(wù) A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產(chǎn)生了幻覺。發(fā)生幻讀的原因也是另外一個事務(wù)新增或者刪除或者修改了第一個事務(wù)結(jié)果集里面的數(shù)據(jù),同一個記錄的數(shù)據(jù)內(nèi)容被修改了,所有數(shù)據(jù)行的記錄就變多或者變少了。

5.13 Spring框架的事務(wù)管理有哪些優(yōu)點?

  • 為不同的事務(wù)API 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一個不變的編程模式。

  • 為編程式事務(wù)管理提供了一套簡單的API而不是一些復(fù)雜的事務(wù)API

  • 支持聲明式事務(wù)管理。

  • 和Spring各種數(shù)據(jù)訪問抽象層很好得集成。

5.14 你更傾向用那種事務(wù)管理類型?

大多數(shù)Spring框架的用戶選擇聲明式事務(wù)管理,因為它對應(yīng)用代碼的影響最小,因此更符合一個無侵入的輕量級容器的思想。聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,雖然比編程式事務(wù)管理(這種方式允許你通過代碼控制事務(wù))少了一點靈活性。唯一不足地方是,最細(xì)粒度只能作用到方法級別,無法做到像編程式事務(wù)那樣可以作用到代碼塊級別。

6. Spring AOP

6.1 什么是AOP?

OOP(Object-Oriented Programming)面向?qū)ο缶幊?/strong>,允許開發(fā)者定義縱向的關(guān)系,但并適用于定義橫向的關(guān)系,導(dǎo)致了大量代碼的重復(fù),而不利于各個模塊的重用。

AOP(Aspect-Oriented Programming),一般稱為面向切面編程,作為面向?qū)ο蟮囊环N補充,用于將那些與業(yè)務(wù)無關(guān),但卻對多個對象產(chǎn)生影響的公共行為和邏輯,抽取并封裝為一個可重用的模塊,這個模塊被命名為“切面”(Aspect),減少系統(tǒng)中的重復(fù)代碼,降低了模塊間的耦合度,同時提高了系統(tǒng)的可維護性??捎糜跈?quán)限認(rèn)證、日志、事務(wù)處理等。

6.2 Spring AOP and AspectJ AOP 有什么區(qū)別?AOP 有哪些實現(xiàn)方式?

AOP實現(xiàn)的關(guān)鍵在于 代理模式,AOP代理主要分為靜態(tài)代理和動態(tài)代理。靜態(tài)代理的代表為AspectJ;動態(tài)代理則以Spring AOP為代表。

1. AspectJ是靜態(tài)代理的增強,所謂靜態(tài)代理,就是AOP框架會在編譯階段生成AOP代理類,因此也稱為編譯時增強,他會在編譯階段將AspectJ(切面)織入到Java字節(jié)碼中,運行的時候就是增強之后的AOP對象。

2. Spring AOP使用的動態(tài)代理,所謂的動態(tài)代理就是說AOP框架不會去修改字節(jié)碼,而是每次運行時在內(nèi)存中臨時為方法生成一個AOP對象,這個AOP對象包含了目標(biāo)對象的全部方法,并且在特定的切點做了增強處理,并回調(diào)原對象的方法。

6.3 JDK動態(tài)代理和CGLIB動態(tài)代理的區(qū)別是什么?

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

  • JDK動態(tài)代理只提供接口的代理,不支持類的代理。核心InvocationHandler接口和Proxy類,InvocationHandler 通過invoke()方法反射來調(diào)用目標(biāo)類中的代碼,動態(tài)地將橫切邏輯和業(yè)務(wù)編織在一起;接著,Proxy利用 InvocationHandler動態(tài)創(chuàng)建一個符合某一接口的的實例, 生成目標(biāo)類的代理對象。

  • 如果代理類沒有實現(xiàn) InvocationHandler 接口,那么Spring AOP會選擇使用CGLIB來動態(tài)代理目標(biāo)類。CGLIB(Code Generation Library),是一個代碼生成的類庫,可以在運行時動態(tài)的生成指定類的一個子類對象,并覆蓋其中特定方法并添加增強代碼,從而實現(xiàn)AOP。CGLIB是通過繼承的方式做的動態(tài)代理,因此如果某個類被標(biāo)記為final,那么它是無法使用CGLIB做動態(tài)代理的。

靜態(tài)代理與動態(tài)代理區(qū)別在于生成AOP代理對象的時機不同,相對來說AspectJ的靜態(tài)代理方式具有更好的性能,但是AspectJ需要特定的編譯器進行處理,而Spring AOP則無需特定的編譯器處理。

InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最終生成的代理實例; method 是被代理目標(biāo)實例的某個具體方法; args 是被代理目標(biāo)實例某個方法的具體入?yún)? 在方法反射調(diào)用時使用。

6.4 如何理解 Spring 中的代理?

將 Advice 應(yīng)用于目標(biāo)對象后創(chuàng)建的對象稱為代理。在客戶端對象的情況下,目標(biāo)對象和代理對象是相同的。

Advice + Target Object = Proxy

6.5 請解釋一下Spring AOP核心的名稱分別是什么意思?

  1. 切面(Aspect):
    切面是通知和切點的結(jié)合。通知和切點共同定義了切面的全部內(nèi)容。 在Spring AOP中,切面可以使用通用類(基于模式的風(fēng)格) 或者在普通類中以 @AspectJ 注解來實現(xiàn)。

  2. 連接點(Join point):
    指方法,在Spring AOP中,一個連接點 總是 代表一個方法的執(zhí)行。 應(yīng)用可能有數(shù)以千計的時機應(yīng)用通知。這些時機被稱為連接點。連接點是在應(yīng)用執(zhí)行過程中能夠插入切面的一個點。這個點可以是調(diào)用方法時、拋出異常時、甚至修改一個字段時。切面代碼可以利用這些點插入到應(yīng)用的正常流程之中,并添加新的行為。

  3. 通知(Advice):
    在AOP術(shù)語中,切面的工作被稱為通知。

  4. 切入點(Pointcut):
    切點的定義會匹配通知所要織入的一個或多個連接點。我們通常使用明確的類和方法名稱,或是利用正則表達式定義所匹配的類和方法名稱來指定這些切點。

  5. 引入(Introduction):
    引入允許我們向現(xiàn)有類添加新方法或?qū)傩浴?/p>

  6. 目標(biāo)對象(Target Object):
    被一個或者多個切面(aspect)所通知(advise)的對象。它通常是一個代理對象。也有人把它叫做 被通知(adviced) 對象。 既然Spring AOP是通過運行時代理實現(xiàn)的,這個對象永遠(yuǎn)是一個 被代理(proxied) 對象。

  7. 織入(Weaving):
    織入是把切面應(yīng)用到目標(biāo)對象并創(chuàng)建新的代理對象的過程。在目標(biāo)對象的生命周期里有多少個點可以進行織入:

    • 編譯期:切面在目標(biāo)類編譯時被織入。AspectJ的織入編譯器是以這種方式織入切面的。

    • 類加載期:切面在目標(biāo)類加載到JVM時被織入。需要特殊的類加載器,它可以在目標(biāo)類被引入應(yīng)用之前增強該目標(biāo)類的字節(jié)碼。AspectJ5的加載時織入就支持以這種方式織入切面。

    • 運行期:切面在應(yīng)用運行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標(biāo)對象動態(tài)地創(chuàng)建一個代理對象。SpringAOP就是以這種方式織入切面。

6.6 為什么Spring只支持方法級別的連接點?

因為Spring基于動態(tài)代理,所以Spring只支持方法連接點。Spring缺少對字段連接點的支持,而且它不支持構(gòu)造器連接點。方法之外的連接點攔截功能,我們可以利用Aspect來補充。

6.7 Spring AOP 中,關(guān)注點和橫切關(guān)注的區(qū)別是什么?

關(guān)注點(concern)是應(yīng)用中一個模塊的行為,一個關(guān)注點可能會被定義成一個我們想實現(xiàn)的一個功能。

橫切關(guān)注點(cross-cutting concern)是一個關(guān)注點,此關(guān)注點是整個應(yīng)用都會使用的功能,并影響整個應(yīng)用,比如日志,安全和數(shù)據(jù)傳輸,幾乎應(yīng)用的每個模塊都需要的功能。因此這些都屬于橫切關(guān)注點。

6.8 Spring通知有哪些類型?

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

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

  1. 前置通知(Before):在目標(biāo)方法被調(diào)用之前調(diào)用通知功能;

  2. 后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時不會關(guān)心方法的輸出是什么;

  3. 返回通知(After-returning ):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知;

  4. 異常通知(After-throwing):在目標(biāo)方法拋出異常后調(diào)用通知;

  5. 環(huán)繞通知(Around):通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的行為。

同一個aspect,不同advice的執(zhí)行順序:

  • 沒有異常情況下的執(zhí)行順序:

    • around before advice

    • before advice

    • target method 執(zhí)行

    • around after advice

    • after advice

    • afterReturning

  • 有異常情況下的執(zhí)行順序:

    • around before advice

    • before advice

    • target method 執(zhí)行

    • around after advice

    • after advice

    • afterThrowing:異常發(fā)生

    • java.lang.RuntimeException: 異常發(fā)生

6.9 什么是切面 Aspect?

aspect 由 pointcount 和 advice 組成,切面是通知和切點的結(jié)合。 它既包含了橫切邏輯的定義, 也包括了連接點的定義. Spring AOP 就是負(fù)責(zé)實施切面的框架, 它將切面所定義的橫切邏輯編織到切面所指定的連接點中.
AOP 的工作重心在于如何將增強編織目標(biāo)對象的連接點上, 這里包含兩個工作:

  • 如何通過 pointcut 和 advice 定位到特定的 joinpoint 上

  • 如何在 advice 中編寫切面代碼.

可以簡單地認(rèn)為, 使用 @Aspect 注解的類就是切面.

6.10 什么是基于XML Schema方式的切面實現(xiàn)?

在這種情況下,切面由常規(guī)類以及基于XML的配置實現(xiàn)。

6.11 什么是基于注解的切面實現(xiàn)?

在這種情況下(基于@AspectJ的實現(xiàn)),涉及到的切面聲明的風(fēng)格與帶有java5標(biāo)注的普通java類一致。

6.12 有幾種不同類型的自動代理?

  1. BeanNameAutoProxyCreator

  2. DefaultAdvisorAutoProxyCreator

  3. Metadata autoproxying

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多