框架相關(guān)

簡述JWT?

答:
概述:JWT是基于Token驗證方式的一種基本實現(xiàn)

  1. Header :描述 JWT 的元數(shù)據(jù)。定義了生成簽名的算法以及 Token 的類型。

  2. Payload(負(fù)載):用來存放實際需要傳遞的數(shù)據(jù)

  3. Signature(簽名):服務(wù)器通過Payload、Header和一個密鑰(secret)使用 Header 里面指定的簽名算法(默認(rèn)是 HMAC SHA256)生成。

在基于 Token 進行身份驗證的的應(yīng)用程序中,服務(wù)器通過Payload、Header和一個密鑰(secret)創(chuàng)建令牌(Token)并將 Token 發(fā)送給客戶端,客戶端將 Token 保存在 Cookie 或者 localStorage 里面,以后客戶端發(fā)出的所有請求都會攜帶這個令牌。你可以把它放在 Cookie 里面自動發(fā)送,但是這樣不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization字段中:Authorization: Bearer Token。

spring如何實現(xiàn)依賴注入?

答:spring實現(xiàn)依賴注入有兩種方式:構(gòu)造函數(shù)注入和setter注入

依賴注入可以理解Spring如何幫我們把我們在配置文件寫的依賴關(guān)系實現(xiàn)。IOC可以認(rèn)為是在中間加了一個代理,我們叫他做什么,他就做什么,原來new的方式可以理解為,我自己去做,而IOC是我叫你去做。

Spring如何解決循環(huán)依賴?

答:循環(huán)依賴如下圖,就是A依賴B的同時B也依賴了A,或者C依賴了自己,在實例化的時候可能會導(dǎo)致,開始實例化A的時候發(fā)現(xiàn)A里面有B,然后又去實例化B,然后B里面又有A,無限循環(huán)


循環(huán)依賴
@Component
public class A {
 // A中注入了B
 @Autowired
 private B b;
}
---
@Component
public class B {
 // B中注入了A
 @Autowired
 private A a;
}
---
// 自己依賴自己
@Component
public class C {
 // C中注入了C
 @Autowired
 private C c;
}
  • 解決方法:
    • 三級緩存:1、singletonObjects:用于存放完全初始化好的 bean,從該緩存中取出的 bean 可以直接使用 2、earlySingletonObjects: 存放原始的 bean 對象(尚未填充屬性),用于解決循環(huán)依賴 3、singletonFactories:存放 bean 工廠對象,用于解決循環(huán)依賴

    • Spring 解決循環(huán)依賴的過程:

      • 首先 A 完成初始化第一步并將自己提前曝光出來(通過 ObjectFactory 將自己提前曝光),在初始化的時候,發(fā)現(xiàn)自己依賴對象 B,此時就會去嘗試 get(B),這個時候發(fā)現(xiàn) B 還沒有被創(chuàng)建出來
      • 然后 B 就走創(chuàng)建流程,在 B 初始化的時候,同樣發(fā)現(xiàn)自己依賴A,于是嘗試 get(A),這個時候由于 A 已經(jīng)添加至緩存中(一般都是添加至三級緩存 singletonFactories ),通過 ObjectFactory 提前曝光,所以可以通過 ObjectFactory.getObject() 方法來拿到 A 對象,B拿到 A 對象后順利完成初始化,然后將自己添加到一級緩存中
      • 回到 A,A 也可以拿到 B 對象,完成初始化,到這里整個鏈路就已經(jīng)完成了初始化過程了。

其實兩重依賴就能解決循環(huán)依賴的問題了,比如A-B循環(huán),A先初始化,然后發(fā)現(xiàn)A里面有B,那么就去初始化B,并把半成品的A放進二級緩存里,然后B里面發(fā)現(xiàn)有A,去緩存里找,找到,B成功初始化,放進一級緩存,然后A創(chuàng)建也就完成了。那么為什么還要三重緩存呢,這里主要是為那些有AOP的Bean對象考慮,我們假設(shè)A是有經(jīng)過代理,我們可以在二重循環(huán)中發(fā)現(xiàn)在B從緩存獲取A的時候,獲取的是半成品的A,而這個A還沒有經(jīng)過代理,所以跟我們想象的是完全不同的,所以Spring定義了第三級緩存,在第三級緩存中判斷返回半成品引用的時候,是否需要進行代理,這里會返回有代理沒有代理的引用。

Spring中bean的作用域?

答:
在spring配置文件定義Bean時,通過聲明scope配置項,可以定義Bean的作用域,一共有五種:

1、singleton:IOC容器僅創(chuàng)建一個Bean實例,IOC容器每次返回的是同一個Bean實例。(默認(rèn)的作用域

2、prototype:IOC容器可以創(chuàng)建多個Bean實例,每次返回的都是一個新的實例。

3、request:該屬性僅對HTTP請求產(chǎn)生作用,使用該屬性定義Bean時,每次HTTP請求都會創(chuàng)建一個新的Bean,適用于WebApplicationContext環(huán)境。

4、 session:該屬性僅用于HTTP Session,同一個Session共享一個Bean實例。不同Session使用不同的實例。

5、global-session:該屬性僅用于HTTP Session,同session作用域不同的是,所有的Session共享一個Bean實例。

Spring中bean的生命周期?

答:

1. 實例化Bean

  • 對于BeanFactory容器,當(dāng)客戶向容器請求一個尚未初始化的bean時,或初始化bean的時候需要注入另一個尚未初始化的依賴時,容器就會調(diào)用createBean進行實例化。
  • 對于ApplicationContext容器,當(dāng)容器啟動結(jié)束后,便實例化所有的bean。
  • 容器通過獲取BeanDefinition對象中的信息進行實例化。并且這一步僅僅是簡單的實例化,并未進行依賴注入(還沒有為成員變量賦值)。
  • 實例化對象被包裝在BeanWrapper對象中,BeanWrapper提供了設(shè)置對象屬性的接口,從而避免了使用反射機制設(shè)置屬性。

2. 設(shè)置對象屬性(依賴注入)

  • 實例化后的對象被封裝在BeanWrapper對象中,并且此時對象仍然是一個原生的狀態(tài),并沒有進行依賴注入。
  • 緊接著,Spring根據(jù)BeanDefinition中的信息進行依賴注入。
  • 并且通過BeanWrapper提供的設(shè)置屬性的接口完成依賴注入。

3. 注入Aware接口(讓Bean對象知道Spring的存在,比如BeanNameAware,就是讓Bean知道自己在Spring里的ID)

  • 緊接著,Spring會檢測該對象是否實現(xiàn)了xxxAware接口,并將相關(guān)的xxxAware實例注入給bean。

4. BeanPostProcessor
當(dāng)經(jīng)過上述幾個步驟后,bean對象已經(jīng)被正確構(gòu)造,但如果你想要對象被使用前再進行一些自定義的處理,就可以通過BeanPostProcessor接口實現(xiàn)。
該接口提供了兩個函數(shù):

  • postProcessBeforeInitialzation( Object bean, String beanName ) 當(dāng)前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數(shù)會先于InitialzationBean執(zhí)行,因此稱為前置處理。 所有Aware接口的注入就是在這一步完成的。
  • postProcessAfterInitialzation( Object bean, String beanName ) 當(dāng)前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數(shù)會在InitialzationBean完成后執(zhí)行,因此稱為后置處理。

5. InitializingBean與init-method
當(dāng)BeanPostProcessor的前置處理完成后就會進入本階段。 InitializingBean接口只有一個函數(shù):

  • afterPropertiesSet()
    這一階段也可以在bean正式構(gòu)造完成前增加我們自定義的邏輯,但它與前置處理不同,由于該函數(shù)并不會把當(dāng)前bean對象傳進來,因此在這一步?jīng)]辦法處理對象本身,只能增加一些額外的邏輯。 若要使用它,我們需要讓bean實現(xiàn)該接口,并把要增加的邏輯寫在該函數(shù)中。然后Spring會在前置處理完成后檢測當(dāng)前bean是否實現(xiàn)了該接口,并執(zhí)行afterPropertiesSet函數(shù)。

  • 當(dāng)然,Spring為了降低對客戶代碼的侵入性,給bean的配置提供了init-method屬性,該屬性指定了在這一階段需要執(zhí)行的函數(shù)名。Spring便會在初始化階段執(zhí)行我們設(shè)置的函數(shù)。init-method本質(zhì)上仍然使用了InitializingBean接口。

6. DisposableBean和destroy-method
和init-method一樣,通過給destroy-method指定函數(shù),就可以在bean銷毀前執(zhí)行指定的邏輯。

Spring 事務(wù)中哪幾種事務(wù)傳播行為?

答:
事務(wù)傳播行為是為了解決業(yè)務(wù)層方法之間互相調(diào)用的事務(wù)問題。

當(dāng)事務(wù)方法被另一個事務(wù)方法調(diào)用時,必須指定事務(wù)應(yīng)該如何傳播。例如:方法可能繼續(xù)在現(xiàn)有事務(wù)中運行,也可能開啟一個新事務(wù),并在自己的事務(wù)中運行。

正確的事務(wù)傳播行為可能的值如下:

1.TransactionDefinition.PROPAGATION_REQUIRED

使用的最多的一個事務(wù)傳播行為,我們平時經(jīng)常使用的@Transactional注解默認(rèn)使用就是這個事務(wù)傳播行為。如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。

2.TransactionDefinition.PROPAGATION_REQUIRES_NEW

創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。也就是說不管外部方法是否開啟事務(wù),Propagation.REQUIRES_NEW修飾的內(nèi)部方法會新開啟自己的事務(wù),且開啟的事務(wù)相互獨立,互不干擾。

3.TransactionDefinition.PROPAGATION_NESTED

如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行;如果當(dāng)前沒有事務(wù),則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。

4.TransactionDefinition.PROPAGATION_MANDATORY

如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。(mandatory:強制性)

這個使用的很少。

Mybatis的映射配置文件中,動態(tài)傳遞參數(shù)有兩種方式:#{}和${},它們有什么區(qū)別?

答:
1、#{}為參數(shù)占位符?即sql預(yù)編譯,${}為字符串替換,即sql拼接

2、變量替換后,#{} 對應(yīng)的變量自動加上單引號,${} 對應(yīng)的變量不會加上單引號

3、#{}能防止sql注入,${}不能防止sql注入

簡述Shiro?

答:首先我們的權(quán)限認(rèn)證基本上基于下圖。


認(rèn)證過程

先驗證你是否有這個用戶,然后再獲取該用戶相關(guān)的權(quán)限(這里有兩種劃分形式,將某一個特定的權(quán)限分配給用戶,還是將特定的權(quán)限集合在一起,成為一個角色,再分配給用戶)
而shiro以三個主要的對象來實現(xiàn)這些功能,分別是subject、SecurityManager、Realm

  • subject:這個主要是跟我們的外層邏輯交互的對象,也就是說我們可以根據(jù)這個對象的一些方法來判斷是否有權(quán)限,是否是某個角色,來進行資源管理
  • SecurityManager:他負(fù)責(zé)所有的subject的管理,比如認(rèn)證和授權(quán)、還有緩存等相關(guān)管理
  • Realm:這個也就是我們大部分代碼的集中區(qū)域了,這里主要有兩個方法,認(rèn)證方法和授權(quán)方法,subject的角色與權(quán)限都是再這里進行邏輯產(chǎn)生的。

Springboot自動裝配原理?

答:

  • 什么是自動裝配:通過注解或者一些簡單的配置就能在 Spring Boot 的幫助下實現(xiàn)某塊功能。
  • 原理:在我們每一個SpringBoot應(yīng)用中,有一個注解@SpringBootApplication,大概可以把 @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。這三個注解的作用分別是:
    1、@EnableAutoConfiguration:啟用 SpringBoot 的自動配置機制。
    2、@Configuration:允許在上下文中注冊額外的 bean 或?qū)肫渌渲妙悺?br> 3、@ComponentScan: 掃描被@Component (@Service,@Controller)注解的 bean,注解默認(rèn)會掃描啟動類所在的包下所有的類 ,可以自定義不掃描某些 bean。如下圖所示,容器中將排除TypeExcludeFilter和AutoConfigurationExcludeFilter。
    而這里的enableAutoConfiguration是實現(xiàn)自動裝配的關(guān)鍵,這里注解會導(dǎo)入一個類AutoConfigurationImportSelector,他實現(xiàn)了一個接口ImportSelector,接口定義了一個方法selectImports,該方法主要用于獲取所有符合條件的類的全限定類名,這些類需要被加載到 IoC 容器中。而在具體的這個方法的實現(xiàn)中,有個叫getAutoConfigurationEntry()的方法被調(diào)用。這個方法第一步會判斷自動裝配是否開啟,第二步獲取Exclude和Excludename。第三步獲取需要自動裝配的所有配置類,讀取META-INF/spring.factories。這個文件里有我們需要自動裝配的所有類的全類名。接著就利用反射將對應(yīng)的類注入Spring容器即可。而且也并不是每次自動裝配都是完完全全裝配所有的類的。有一個注解@ConditionalOnXXX,他可以做一些邏輯判斷,在某些時候一些是沒有必要裝配的。另外引入一個starter,他在meta-inf/spring.factories的配置就會被讀取,然后自動裝配相應(yīng)的類
  • 如何實現(xiàn)一個 Starter:
  1. 首先我們要引入Spring的相關(guān)依賴,比如Spring給我們定義Starter的基本版本,我們在Maven中加dependence即可。
  2. 將相應(yīng)的類加上@Bean和@ConditionalOnClass(如果不設(shè)置條件也可以不添加)
  3. 最后在mete-inf/的Spring.factory中寫上自動裝配類的全類名即可
  4. 這樣一個Starter就完成了

總結(jié):也就是說我們Spring的啟動注解中,包含了一個enableAutoConfiguration的這個注解,這個注解會導(dǎo)入一個實現(xiàn)自動裝配的類,他有一個方法,會掃描所有Starter的Spring.factory文件里的相關(guān)類,而且并不是每次都加載全部,在ConditionOnclass的注解下可能只會裝配部分。

Spring IOC的理解?

答:中間人,門面模式,從你自己做,到你叫別人幫你做,其實本質(zhì)上我認(rèn)為就是,將那些通用或者難實現(xiàn)的代碼,交給哪些最厲害的程序員去寫,而我們只注重我們的個性化需求,但是你如果沒有通過容器,直接new這樣,無從下手,所以采用門面模式

將類交給spring容器的3種辦法

答:

  • 注解方式:
    1@Bean
    2)@Component
    3)@Import方式
  • XML方式:
    4)xml注冊Bean,如果spring配置元數(shù)據(jù)的方式是xml時,可以手動在xml注冊第三方j(luò)ar包中的類。

spring源碼aop怎么實現(xiàn)的,aop用在哪里?

答:原理就是當(dāng)我們從Spring容器中獲取bean的時候,他根據(jù)動態(tài)代理返回一個代理對象,具體代理在調(diào)用我們真正的方法的時候用了什么,是基于我們自己的注解配置。動態(tài)代理參考其他

攔截器和過濾器的區(qū)別?

參考鏈接

@AutoWired、@Qualified、@Resource三個注解的區(qū)別 ?

答:
一、@Autowired,@Qualifier

// @Autowired只按照類型注入,如果想按照名稱注入,配合@Qualifier使用
@Autowired
@Qualifier("studentDao")

二、@Resource

// 如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常
@Resource(name = "studentDao",type = StudentDao.class)

// 如果指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
@Resource(name = "studentDao")

// 如果指定了type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或者找到多個,都會拋出異常
@Resource(type = StudentDao.class)

// 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有匹配,則回退為一個原始類型進行匹配,如果匹配則自動裝配;
@Resource

本質(zhì)上兩者都是標(biāo)志bean自動注入,只是標(biāo)準(zhǔn)不同,Resource是JDK中的標(biāo)準(zhǔn),假如有其他DI框架也同樣適用

事務(wù)傳播機制底層原理?

事務(wù)傳播機制基本概念
事務(wù)傳播機制具體例子
事務(wù)底層實現(xiàn)原理

  • 什么是事務(wù)的傳播?
    Spring 除了封裝了事務(wù)控制之外,還抽象出了 事務(wù)的傳播 這個概念,事務(wù)的傳播并不是關(guān)系型數(shù)據(jù)庫所定義的,而是Spring在封裝事務(wù)時做的增強擴展,可以通過@Transactional 指定事務(wù)的傳播,具體類型如下

  • 為什么會有傳播機制?
    spring 對事務(wù)的控制,是使用 aop 切面實現(xiàn)的,我們不用關(guān)心事務(wù)的開始,提交 ,回滾,只需要在方法上加 @Transactional 注解,這時候就有問題了。

  • 場景一: serviceA 方法調(diào)用了 serviceB 方法,但兩個方法都有事務(wù),這個時候如果 serviceB 方法異常,是讓 serviceB 方法提交,還是兩個一起回滾。

  • 場景二:serviceA 方法調(diào)用了 serviceB 方法,但是只有 serviceA 方法加了事務(wù),是否把 serviceB 也加入 serviceA 的事務(wù),如果 serviceB 異常,是否回滾 serviceA 。

  • 場景三:serviceA 方法調(diào)用了 serviceB 方法,兩者都有事務(wù),serviceB 已經(jīng)正常執(zhí)行完,但 serviceA 異常,是否需要回滾 serviceB 的數(shù)據(jù)。

  • 傳播機制生效條件
    因為 spring 是使用 aop 來代理事務(wù)控制 ,是針對于接口或類的,所以在同一個 service 類中兩個方法的調(diào)用,傳播機制是不生效的

1、PROPAGATION_REQUIRED:如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中。Spring的默認(rèn)事務(wù)傳播類型

2、PROPAGATION_SUPPORTS:支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。

3、PROPAGATION_MANDATORY:使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。

4、PROPAGATION_REQUIRES_NEW:新建事務(wù),如果當(dāng)前存在事務(wù),把當(dā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ù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容