文章目錄:
1.什么是Spring?
2.Spring由哪些模塊組成?
3.Spring中都用到了哪些設計模式?
4.什么是Spring IOC容器?有什么作用?
5.Spring IoC的實作機制
6.BeanFactory 和 ApplicationContext有什么區別?
7.什么是Spring的依賴注入(Dependency Injection)?
8.什么是Spring AOP?
9.Spring AOP 與 AspectJ AOP 有什么區別?AOP 有哪些實作方式?
10.解釋一下Spring AOP里面的幾個名詞
11.Spring AOP中的通知有哪些型別?
12.Spring支持的幾種bean的作用域
13.解釋一下Spring中bean的生命周期
14.Spring支持的事務管理型別, Spring事務實作方式有哪些?你更傾向用哪種事務管理型別?
15.什么是Spring事務的傳播行為?
16.什么是Spring事務的隔離級別?
1.什么是Spring?
Spring是一個輕量級Java開源框架,最早由Rod Johnson創建,目的是解決企業級應用開發的復雜性,簡化Java開發,Spring為開發Java應用程式提供全面的基礎架構支持,因此Java開發者可以專注于應用程式的開發,
Spring可以做很多事情,它為企業級開發提供給了豐富的功能,但是這些功能的底層都依賴于它的兩個核心特性,也就是控制反轉(IoC)也可以說依賴注入(DI)和面向切面編程(AOP),
為了降低Java開發的復雜性,Spring采取了以下4種關鍵策略
基于POJO的輕量級和最小侵入性編程;
通過依賴注入和面向介面實作松耦合;
基于切面和慣例進行宣告式編程;
通過切面和模板減少樣板式代碼,
Spring設計目標:Spring為開發者提供一個一站式輕量級應用開發平臺;
Spring設計理念:在JavaEE開發中,支持POJO和JavaBean開發方式,使應用面向介面開發,充分支持OO(面向物件)設計方法;Spring通過IoC容器實作物件耦合關系的管理,并實作依賴反轉,將物件之間的依賴關系交給IoC容器,實作解耦;
Spring框架的核心:IoC容器和AOP模塊,通過IoC容器管理POJO物件以及他們之間的耦合關系;通過AOP以動態非侵入的方式增強服務,把遍布于應用各層的功能分離出來形成可重用的功能組件,
2.Spring由哪些模塊組成?

spring core:提供了框架的基本組成部分,包括控制反轉(Inversion of Control,IOC)和依賴注入(Dependency Injection,DI)功能,
spring beans:提供了BeanFactory,是工廠模式的一個經典實作,Spring將管理物件稱為Bean,
spring context:構建于 core 封裝包基礎上的 context 封裝包,提供了一種框架式的物件訪問方法,
spring jdbc:提供了一個JDBC的抽象層,消除了煩瑣的JDBC編碼和資料庫廠商特有的錯誤代碼決議, 用于簡化JDBC,
spring aop:提供了面向切面的編程實作,讓你可以自定義攔截器、切點等,
spring Web:提供了針對 Web 開發的集成特性,例如檔案上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext,
spring test:主要為測驗提供支持的,支持使用JUnit或TestNG對Spring組件進行單元測驗和集成測驗,
3.Spring中都用到了哪些設計模式?
工廠模式:BeanFactory就是簡單工廠模式的體現,用來創建物件的實體;
單例模式:Bean默認為單例模式,
代理模式:Spring的AOP功能用到了JDK的動態代理和CGLIB位元組碼生成技術;
模板方法:用來解決代碼重復的問題,比如:RestTemplate, JmsTemplate, JpaTemplate,
觀察者模式:定義物件間一對多的依賴關系,當一個物件的狀態發生改變時,所有依賴于它的物件都會得到通知被動更新,如Spring中listener的實作--ApplicationListener,
4.什么是Spring IOC容器?有什么作用?
控制反轉即IoC (Inversion of Control),它把傳統上由程式代碼直接操控的物件的呼叫權交給容器,通過容器來實作物件組件的裝配和管理,所謂的“控制反轉”概念就是對物件組件控制權的轉移,從程式代碼本身轉移到了外部容器,
Spring IOC 負責創建物件,管理物件(通過依賴注入(DI),裝配物件,配置物件,并且管理這些物件的整個生命周期,)
IoC容器的作用:
管理物件的創建和依賴關系的維護,物件的創建并不是一件簡單的事,在物件關系比較復雜時,如果依賴關系需要程式猿來維護的話,那是相當頭疼的
解耦,由容器去維護具體的物件
托管了類的整個生命周期,比如我們需要在類的產生程序中做一些處理,最直接的例子就是代理,如果有容器程式可以把這部分處理交給容器,應用程式則無需去關心類是如何完成代理的
5.Spring IoC的實作機制
Spring 中的 IoC 的實作原理就是工廠模式加反射機制,
package com.szh.spring;
/**
*
*/
interface Fruit {
void eat();
}
class Apple implements Fruit {
public Apple() {
System.out.println("Apple類的無參構造執行了....");
}
@Override
public void eat() {
System.out.println("蘋果");
}
}
class Banana implements Fruit {
public Banana() {
System.out.println("Banana類的無參構造執行了....");
}
@Override
public void eat() {
System.out.println("香蕉");
}
}
class Factory {
public static Fruit getInstance(String className) {
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return fruit;
}
}
public class Client {
public static void main(String[] args) {
Fruit fruit = Factory.getInstance("com.szh.spring.Apple");
if (fruit != null) {
fruit.eat();
}
}
}

6.BeanFactory 和 ApplicationContext有什么區別?
BeanFactory和ApplicationContext是Spring的兩大核心介面,都可以當做Spring的容器,其中ApplicationContext是BeanFactory的子介面,
依賴關系
BeanFactory:是Spring里面最底層的介面,包含了各種Bean的定義,讀取bean配置檔案,管理bean的加載、實體化,控制bean的生命周期,維護bean之間的依賴關系,我們可以稱之為 “低級容器”,
ApplicationContext介面作為BeanFactory的派生,可以稱之為 “高級容器”,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:
繼承MessageSource,因此支持國際化,
統一的資源檔案訪問方式,
提供在監聽器中注冊bean的事件,
同時加載多個組態檔,
載入多個(有繼承關系)背景關系 ,使得每一個背景關系都專注于一個特定的層次,比如應用的web層,
加載方式
BeanFactroy采用的是延遲加載形式來注入Bean的,即只有在使用到某個Bean時(呼叫getBean()),才對該Bean進行加載實體化,這樣,我們就不能發現一些存在的Spring的配置問題,如果Bean的某一個屬性沒有注入,BeanFacotry加載后,直至第一次使用呼叫getBean方法才會拋出例外,
ApplicationContext,它是在容器啟動時,一次性創建了所有的Bean,這樣,在容器啟動時,我們就可以發現Spring中存在的配置錯誤,這樣有利于檢查所依賴屬性是否注入,ApplicationContext啟動后預載入所有的單實體Bean,通過預載入單實體bean,確保當你需要的時候,你就不用等待,因為它們已經創建好了,
相對于基本的BeanFactory,ApplicationContext 唯一的不足是占用記憶體空間,當應用程式配置Bean較多時,程式啟動較慢,
創建方式
BeanFactory通常以編程的方式被創建,ApplicationContext還能以宣告的方式創建,如使用ContextLoader,
注冊方式
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區別是:BeanFactory需要手動注冊,而ApplicationContext則是自動注冊,
7.什么是Spring的依賴注入(Dependency Injection)?
依賴注入:相對于IoC而言,依賴注入(DI)更加準確地描述了IoC的設計理念,所謂依賴注入(Dependency Injection),即組件之間的依賴關系由容器在應用系統運行期來決定,也就是由容器動態地將某種依賴關系的目標物件實體注入到應用系統中的各個關聯的組件之中,組件不做定位查詢,只提供普通的Java方法,讓容器去決定依賴關系,
依賴注入是時下最流行的IoC實作方式,依賴注入分為介面注入(Interface Injection),Setter方法注入(Setter Injection)和構造器注入(Constructor Injection)三種方式,其中介面注入由于在靈活性和易用性比較差,現在從Spring4開始已被廢棄,
構造器注入:構造器注入是容器通過呼叫一個類的構造器來實作的,該構造器有一系列引數,每個引數都必須注入,
Setter方法注入:Setter方法注入是容器通過呼叫無參構造器或無參static工廠方法實體化bean之后,呼叫該bean的setter方法來實作的依賴注入,

8.什么是Spring AOP?
AOP(Aspect-Oriented Programming),一般稱為面向切面編程,作為面向物件的一種補充,用于將那些與業務無關,但卻對多個物件產生影響的公共行為和邏輯,抽取并封裝為一個可重用的模塊,這個模塊被命名為“切面”(Aspect),通過面向切面編程減少了系統中的重復代碼,降低了模塊間的耦合度,同時提高了系統的可維護性,常用于權限認證、日志、事務處理等,
9.Spring AOP 與 AspectJ AOP 有什么區別?AOP 有哪些實作方式?
AOP實作的關鍵在于代理模式,AOP代理主要分為靜態代理和動態代理,靜態代理的代表為AspectJ;動態代理則以Spring AOP為代表,
(1)AspectJ是靜態代理的增強,所謂靜態代理,就是AOP框架會在編譯階段生成AOP代理類,因此也稱為編譯時增強,他會在編譯階段將AspectJ(切面)織入到Java位元組碼中,運行的時候就是增強之后的AOP物件,
(2)Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改位元組碼,而是每次運行時在記憶體中臨時為方法生成一個AOP物件,這個AOP物件包含了目標物件的全部方法,并且在特定的切點做了增強處理,并回呼原物件的方法,
10.解釋一下Spring AOP里面的幾個名詞

- Aspect:切面,給業務方法增加到功能,切面泛指交叉業務邏輯,常用的切面是通知(Advice),實際就是對主業務邏輯的一種增強,
- JoinPoint:連接點,連接切面的業務方法,連接點指可以被切面織入的具體方法,通常業務介面中的方法均為連接點,
- Pointcut:切入點,切入點指宣告的一個或多個連接點的集合,通過切入點指定一組方法,被標記為 final 的方法是不能作為連接點與切入點的,因為最終的是不能被修改的,不能被增強的,
- Target:目標物件,目標物件指將要被增強的物件,即包含主業務邏輯的類的物件,
- Advice:通知,通知表示切面的執行時間,Advice 也叫增強,換個角度來說,通知定義了增強代碼切入到目標代碼的時間點,是目標方法執行之前執行,還是之后執行等,通知型別不同,切入時間不同,
切入點定義切入的位置,通知定義切入的時間,
11.Spring AOP中的通知有哪些型別?
| 通知型別 | 說明 | 使用場景 |
| 前置通知(Before) | 在目標方法被執行之前呼叫通知 | |
| 后置通知(After) | 無論如何都會在目標方法執行之后呼叫通知 | 記錄日志(方法已經呼叫,但不一定成功) |
| 最終通知(After-returning ) | 無論目標方法是否拋出例外,該增強均會被執行, | 記錄日志(方法已經成功呼叫) |
| 例外通知(After-throwing) | 在目標方法拋出例外后呼叫通知 | 例外處理 |
| 環繞通知(Around) | 通知包裹了目標方法,在目標方法呼叫之前和呼叫之后執行自定義的行為 | 事務權限控制 |
12.Spring支持的幾種bean的作用域
當定義一個bean在Spring里,我們還能給這個bean宣告一個作用域,它可以通過bean的scope屬性來定義,
Spring框架支持以下五種bean的作用域:
| 作用域 | 描述 |
|---|---|
| singleton | 單例模式,在spring IoC容器僅存在一個Bean實體,默認值 |
| prototype | 原型模式,每次從容器中獲取Bean時,都回傳一個新的實體,即每次呼叫getBean()時,相當于執行newXxxBean() |
| request | 每次HTTP請求都會創建一個新的Bean,該作用域僅在基于web的Spring ApplicationContext環境下有效 |
| session | 同一個HTTP Session共享一個Bean,不同Session使用不同的Bean,該作用域僅在基于web的Spring ApplicationContext環境下有效 |
| global-session | 同一個全域的HTTP Session中共享一個Bean,一般用于Portlet應用環境,該作用域僅在基于web的Spring ApplicationContext環境下有效 |
因為經常用到的就是前兩種 singleton、prototype,所以下面通過簡單的代碼案例演示一下,
首先演示當Spring Bean的作用域設定為 默認singleton 的情況,依次是物體類、Spring組態檔、測驗方法,
package com.szh.spring;
/**
*
*/
public class Book {
private String bookName;
private String bookAuthor;
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", bookAuthor='" + bookAuthor + '\'' +
'}';
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book" class="com.szh.spring.Book" scope="singleton">
<property name="bookName" value="盜墓筆記"/>
<property name="bookAuthor" value="南派三叔"/>
</bean>
</beans>
@Test
public void testBook() {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Book book1 = context.getBean("book",Book.class);
Book book2 = context.getBean("book",Book.class);
System.out.println(book1);
System.out.println(book2);
System.out.println(book1 == book2);
}

從上面的輸出結果中可以看到,在bean的作用域為 singleton 單例的情況下,通過Spring IoC容器依次拿到的這兩個物件是一樣的,也就是說此時容器中僅存在這一個bean(Book),
下面再來演示 bean 作用域為prototype的情況,所有測驗代碼和上面的一樣,只是將組態檔中 <bean> 標簽中的 scope 屬性修改為 prototype,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="book" class="com.szh.spring.Book" scope="prototype">
<property name="bookName" value="盜墓筆記"/>
<property name="bookAuthor" value="南派三叔"/>
</bean>
</beans>

這個時候,我們可以看到從容器中拿到的這兩個物件就不一樣了,因為此時bean的作用域變成了 prototype 多實體情況,也就是說容器中可以有多個Book實體,
關于 singleton 和 prototype 的區別:
- singleton 單實體,prototype 多實體,
- 設定 scope 值是 singleton 的時候,加載 spring 組態檔時就會創建單實體物件,
設定 scope 值是 prototype 的時候,不是在加載 spring 組態檔的時候創建 物件,而是在呼叫getBean 方法時候創建多實體物件,
13.解釋一下Spring中bean的生命周期
在傳統的Java應用中,bean的生命周期很簡單,使用Java關鍵字new進行bean實體化,然后該bean就可以使用了,一旦該bean不再被使用,則由Java自動進行垃圾回收,相比之下,Spring容器中的bean的生命周期就顯得相對復雜多了,正確理解Spring bean的生命周期非常重要,因為你或許要利用Spring提供的擴展點來自定義bean的創建程序,
下圖展示了bean裝載到Spring應用背景關系中的一個典型的生命周期程序,

Spring對bean進行實體化;
Spring將值和bean的參考注入到bean對應的屬性中;(set方法賦值、參考型別、構造器等等)
如果bean實作了BeanNameAware介面,Spring將bean的ID傳遞給setBean-Name()方法;
如果bean實作了BeanFactoryAware介面,Spring將呼叫setBeanFactory()方法,將BeanFactory容器實體傳入;
如果bean實作了ApplicationContextAware介面,Spring將呼叫setApplicationContext()方法,將bean所在的應用背景關系的參考傳入進來;
如果bean實作了BeanPostProcessor介面,Spring將呼叫它們的post-ProcessBeforeInitialization()方法;
如果bean實作了InitializingBean介面,Spring將呼叫它們的after-PropertiesSet()方法,類似地如果bean使用initmethod宣告了初始化方法,該方法也會被呼叫;
此時,bean已經準備就緒,可以被應用程式使用了,它們將一直駐留在應用背景關系中,直到該應用背景關系被銷毀;
如果bean實作了DisposableBean介面,Spring將呼叫它的destroy()介面方法,同樣,如果bean使用destroy-method宣告了銷毀方法,該方法也會被呼叫,
下面簡單演示一下Spring Bean的生命周期:👇👇👇
package com.szh.spring.bean;
/**
*
*/
public class Orders {
private String name;
public Orders() {
System.out.println("第一步: 執行無參構造創建bean實體");
}
public void setName(String name) {
this.name = name;
System.out.println("第二步: 呼叫set方法設定屬性值");
}
//創建執行的初始化的方法
public void initMethod() {
System.out.println("第三步: 執行bean初始化的方法");
}
//創建執行的銷毀的方法
public void destroyMethod() {
System.out.println("第五步: 執行bean銷毀的方法");
}
}
package com.szh.spring.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
*
*/
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前執行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后執行的方法");
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orders" class="com.szh.spring.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="手機"/>
</bean>
<!-- 配置后置處理器 -->
<bean id="myBeanPost" class="com.szh.spring.bean.MyBeanPost"/>
</beans>
@Test
public void testBean() {
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean2.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean2.xml");
Orders orders = context.getBean("orders",Orders.class);
System.out.println("第四步: 獲取創建好的bean實體物件 ---> " + orders);
//手動讓bean實體銷毀
context.close();
}

bean 生命周期有七步
- 通過無參構造創建 bean 實體
- 為 bean 的屬性設定值和對其他 bean 的參考(呼叫 set 方法)
- 把 bean 實體傳遞 bean 后置處理器的方法 postProcessBeforeInitialization(實作了BeanPostProcessor介面)
- 呼叫 bean 的初始化的方法(需要進行配置初始化的方法)
- 把 bean 實體傳遞 bean 后置處理器的方法 postProcessAfterInitialization(實作了BeanPostProcessor介面)
- bean 可以使用了(物件獲取到了)
- 當容器關閉時候,呼叫 bean 的銷毀的方法(需要進行配置銷毀的方法)
14.Spring支持的事務管理型別, Spring事務實作方式有哪些?你更傾向用哪種事務管理型別?
Spring事務的本質其實就是資料庫對事務的支持,沒有資料庫的事務支持,spring是無法提供事務功能的,真正的資料庫層的事務提交和回滾是通過bin log或者redo log實作的,
Spring支持兩種型別的事務管理:
編程式事務管理:通過編程的方式管理事務,靈活性好,但是難維護,
宣告式事務管理:將業務代碼和事務管理分離,只需用注解和XML配置來管理事務,
大多數情況下選擇宣告式事務管理,雖然比編程式事務管理少了一點靈活性,最細粒度只能作用到方法級別,無法做到像編程式事務那樣可以作用到代碼塊級別,但是宣告式事務管理對應用代碼的影響最小,更符合一個無侵入的輕量級容器的思想,具有更好的可維護性,
15.什么是Spring事務的傳播行為?
spring事務的傳播行為說的是,當多個事務同時存在的時候,spring如何處理這些事務的行為,
- PROPAGATION_REQUIRED:如果當前沒有事務,就創建一個新事務,如果當前存在事務,就加入該事務,該設定是最常用的設定,
- PROPAGATION_SUPPORTS:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行,
- PROPAGATION_MANDATORY:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就拋出例外,
- PROPAGATION_REQUIRES_NEW:創建新事務,無論當前存不存在事務,都創建新事務,
- PROPAGATION_NOT_SUPPORTED:以非事務方式執行,如果當前存在事務,就把當前事務掛起,
- PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出例外,
- PROPAGATION_NESTED:如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則按REQUIRED屬性執行,

16.什么是Spring事務的隔離級別?
spring 有五大隔離級別,默認值為 ISOLATION_DEFAULT(使用資料庫的設定),其他四個隔離級別和資料庫的隔離級別一致:
ISOLATION_DEFAULT:用底層資料庫的設定隔離級別,MySQL默認的為ISOLATION_REPEATABLE_READ,
ISOLATION_READ_UNCOMMITTED:讀未提交,最低的隔離級別,一個事務可以讀取另一個事務更新但未提交的資料,(會出現臟讀、不可重復讀、幻讀);
ISOLATION_READ_COMMITTED:讀已提交,一個事務提交后才能被其他事務讀取到(會出現不可重復讀、幻讀),Oracle、SQL server 的默認級別;
ISOLATION_REPEATABLE_READ:可重復讀,對同一欄位的多次讀取結果都是一致的,除非資料被本身事務所修改(會出現幻讀),MySQL 的默認級別;
ISOLATION_SERIALIZABLE:可串行化,最高的隔離級別,可以防止臟讀、不可重復讀、幻讀,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/305440.html
標籤:java
