一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

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

 頭號碼甲 2021-05-09

目錄

1. Spring基礎(chǔ)

1.1 什么是 spring?

Spring是一個(gè)輕量級Java開發(fā)框架,最早有Rod Johnson創(chuàng)建,目的是為了解決企業(yè)級應(yīng)用開發(fā)的業(yè)務(wù)邏輯層和其他各層的耦合問題。它是一個(gè)分層的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ā)提供給了豐富的功能,但是這些功能的底層都依賴于它的兩個(gè)核心特性,也就是依賴注入(dependency injection,DI)和面向切面編程(aspect-oriented programming,AOP)。

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

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

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

  • 基于切面和慣例進(jìn)行聲明式編程;

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

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

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

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

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

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

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

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

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

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

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

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

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

Spring 總共大約有 20 個(gè)模塊, 由 1300 多個(gè)不同的文件構(gòu)成。 而這些組件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和設(shè)備支持(Instrmentation) 、數(shù)據(jù)訪問與集成(Data Access/Integeration)Web、 消息(Messaging) 、 Test等 幾 個(gè)模塊中。 以下是 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
    該層為類檢測和類加載器實(shí)現(xiàn)提供支持。

  • Test
    該層為使用 JUnit 和 TestNG 進(jìn)行測試提供支持。

  • 其他模塊

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

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

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

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

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

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

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

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

  • 接口
    定義功能。

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

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

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

  • 用戶程序
    它使用接口

1.7 使用 Spring 有哪些方式?

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

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

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

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

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

  • 優(yōu)點(diǎn)

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

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

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

    • 方便程序的測試
      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)用難度大大降低。

  • 缺點(diǎn)

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

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

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

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

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

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

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

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

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

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

2. Spring IoC

2.1 什么是 Spring IOC 容器?

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

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

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

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

  • 解耦,由容器去維護(hù)具體的對象

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

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

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

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

  • setter 注入

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

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

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

  • BeanFactory

  • ApplicationContext

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

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

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

BeanFactory和ApplicationContext的關(guān)系

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

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

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

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

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

小結(jié)

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

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

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

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

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

2.5 IoC 的好處有哪些?

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

  2. 它將使您的應(yīng)用程序易于測試,因?yàn)樗恍枰獑卧獪y試用例中的任何單例

  3. 或JNDI 查找機(jī)制。

  4. 它以最小的影響和最少的侵入機(jī)制促進(jìn)松耦合。

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

2.6 Spring IoC 的實(shí)現(xiàn)機(jī)制

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

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è)計(jì)支持以下功能:

  • 依賴注入

  • 依賴檢查

  • 自動(dòng)裝配

  • 支持集合

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

  • 支持回調(diào)某些方法(但是需要實(shí)現(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的加載、實(shí)例化,控制bean的生命周期,維護(hù)bean之間的依賴關(guān)系。
    ApplicationContext接口作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:

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

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

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

    • 同時(shí)加載多個(gè)配置文件。

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

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

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

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

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

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

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

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

2.10 什么是Spring的依賴注入?

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

依賴注入:相對于IoC而言,依賴注入(DI)更加準(zhǔn)確地描述了IoC的設(shè)計(jì)理念。所謂依賴注入(Dependency Injection),即組件之間的依賴關(guān)系由容器在應(yīng)用系統(tǒng)運(yùn)行期來決定,也就是由容器動(dòng)態(tài)地將某種依賴關(guān)系的目標(biāo)對象實(shí)例注入到應(yīng)用系統(tǒng)中的各個(gè)關(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é)組件的裝配,它會(huì)把符合依賴關(guān)系的對象通過屬性(JavaBean中的setter)或者是構(gòu)造器傳遞給需要的對象。

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

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

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

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

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

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

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

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

3. Spring Beans

3.1 什么是 spring bean?

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

  2. Bean 由 Spring IoC 容器管理。

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

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

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

  • 基于xml配置
    bean 所需的依賴項(xiàng)和服務(wù)在 XML 格式的配置文件中指定 。 這些配置文件通常包含許多 bean 定義和特定于應(yīng)用程序的配置選項(xià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來實(shí)現(xiàn) 。

    例如:

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

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

3.3 spring 支持幾種 bean scope?

Spring bean 支持5種scope:

  • Singleton
    每個(gè) Spring IoC 容器僅有一個(gè)單實(shí)例 。

  • Prototype
    每次請求都會(huì)產(chǎn)生一個(gè)新的實(shí)例。

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

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

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

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

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

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

1、Spring 容器根據(jù)配置中的 bean 定義中實(shí)例化 bean。
2、Spring 使用依賴注入填充所有屬性,如 bean 中所定義的配置。
3、如果 bean 實(shí)現(xiàn) BeanNameAware 接口,則工廠通過傳遞 bean 的 ID 來調(diào)用setBeanName()。
4、如果 bean 實(shí)現(xiàn) BeanFactoryAware 接口,工廠通過傳遞自身的實(shí)例來調(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 實(shí)現(xiàn) DisposableBean 接口,當(dāng) spring 容器關(guān)閉時(shí),會(huì)調(diào)用 destory()。
9、如果為 bean 指定了 destroy 方法(的 destroy-method 屬性),那么將調(diào)用它。

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

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

例如,假設(shè)我們有一個(gè) Student 類,其中引用了 Person 類。 這里我們將只創(chuàng)建一個(gè) Person 類實(shí)例并在 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的自動(dòng)裝配?

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

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

3.7 自動(dòng)裝配有哪些方式?

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

自動(dòng)裝配的不同模式:

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

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

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

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

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

3.8 自動(dòng)裝配有什么局限?

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

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

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

3.9 使用@Autowired注解自動(dòng)裝配的過程是怎樣的?

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

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

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

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

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

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

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

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

  1. Set方法注入;

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

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

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

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

  4. 實(shí)例工廠;

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

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

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

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

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

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

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

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

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

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

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

有兩個(gè)重要的bean 生命周期方法:

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

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

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

3.15 在 Spring中如何注入一個(gè)java集合?

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

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

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

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

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

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

可以。

4. Spring注解

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

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

以@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();
    }
}

4.2 怎樣開啟注解裝配?

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

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

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

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

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

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

4.4 @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;
    }
}

4.5 @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;
    }
}

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才會(huì)按照類型來裝配注入。

4.7 @Qualifier注解有什么作用?

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

4.8 @RequestMapping注解有什么用?

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

  • 類級別:
    映射請求的 URL

  • 方法級別:

    • 映射 URL

    • HTTP 請求方法

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

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

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

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

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

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

通過使用JDBC抽象和DAO模塊,保證數(shù)據(jù)庫代碼的簡潔,并能避免數(shù)據(jù)庫資源錯(cuò)誤關(guān)閉導(dǎo)致的問題,它在各種不同的數(shù)據(jù)庫的錯(cuò)誤信息之上,提供了一個(gè)統(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í),無需考慮捕獲每種技術(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ù)錯(cuò)誤處理。

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

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

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

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

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

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

  • 配置the Hibernate SessionFactory

  • 繼承HibernateDaoSupport實(shí)現(xiàn)一個(gè)DAO

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

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

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

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

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

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

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

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

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

  1. PROPAGATION_REQUIRED:
    如果當(dāng)前沒有事務(wù),就創(chuàng)建一個(gè)新事務(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è)置),其他四個(gè)隔離級別和數(shù)據(jù)庫的隔離級別一致:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6. Spring AOP

6.1 什么是AOP?

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

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

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

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

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

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

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

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

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

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

6.4 如何理解 Spring 中的代理?

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

Advice + Target Object = Proxy

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

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

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

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

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

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

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

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

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

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

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

6.6 為什么Spring只支持方法級別的連接點(diǎn)?

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

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

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

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

6.8 Spring通知有哪些類型?

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

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

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

  2. 后置通知(After):在目標(biāo)方法完成之后調(diào)用通知,此時(shí)不會(huì)關(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í)行自定義的行為。

同一個(gè)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 組成,切面是通知和切點(diǎn)的結(jié)合。 它既包含了橫切邏輯的定義, 也包括了連接點(diǎn)的定義. Spring AOP 就是負(fù)責(zé)實(shí)施切面的框架, 它將切面所定義的橫切邏輯編織到切面所指定的連接點(diǎn)中.
AOP 的工作重心在于如何將增強(qiáng)編織目標(biāo)對象的連接點(diǎn)上, 這里包含兩個(gè)工作:

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

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

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

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

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

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

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

6.12 有幾種不同類型的自動(dòng)代理?

  1. BeanNameAutoProxyCreator

  2. DefaultAdvisorAutoProxyCreator

  3. Metadata autoproxying

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    五月激情五月天综合网| 99久久精品国产麻豆| 精品午夜福利无人区乱码| 国产日产欧美精品大秀| 亚洲国产欧美精品久久| 日韩精品少妇人妻一区二区| 国产精品成人免费精品自在线观看 | 男女午夜在线免费观看视频| 亚洲一区二区精品久久av| 女人高潮被爽到呻吟在线观看| 欧美一级特黄特色大色大片| 中文字幕日韩无套内射| 小草少妇视频免费看视频| 黄片免费播放一区二区| 午夜直播免费福利平台| 欧美小黄片在线一级观看| 午夜精品福利视频观看| 欧美日韩亚洲国产综合网| 亚洲天堂男人在线观看| 亚洲精品美女三级完整版视频| 国产精品亚洲欧美一区麻豆| 久久成人国产欧美精品一区二区| 欧美成人欧美一级乱黄| 欧洲一级片一区二区三区| 性感少妇无套内射在线视频| 欧美又大又黄刺激视频| 欧美一区二区日韩一区二区| 手机在线不卡国产视频| 中文字幕中文字幕在线十八区| 欧美成人久久久免费播放| 欧美午夜不卡在线观看| 日本加勒比不卡二三四区| 国产丝袜极品黑色高跟鞋| 国产精品美女午夜视频| 国产亚洲精品香蕉视频播放| 日本午夜免费啪视频在线| 欧美尤物在线视频91| 亚洲中文字幕在线综合视频| 亚洲精品美女三级完整版视频 | 黑鬼糟蹋少妇资源在线观看| 亚洲国产香蕉视频在线观看|