1. Spring中的Bean的生命周期

Instance執行個體化-> 設定屬性值-> 調⽤BeanNameAware的setBeanName⽅法->調⽤BeanPostProsessor的預初始化⽅法->調⽤InitializationBean的afterPropertiesSet()的⽅法->調⽤定制的初始化⽅法callCustom的init-method->調⽤BeanPostProsessor的後初始化⽅法->Bean可以使⽤了 -> 容器關閉-> 調⽤DisposableBean的destroy⽅法->調⽤定制的銷毀⽅法CallCustom的destroy-method。
- Spring對Bean進⾏執行個體化(相當于程式中的new Xx())
- Spring将值和Bean的引⽤注⼊進Bean對應的屬性中
- 如果Bean實作了BeanNameAware接⼝,Spring将Bean的ID傳遞給setBeanName()⽅法(實作BeanNameAware清主要是為了通過Bean的引⽤來獲得Bean的ID,⼀般業務中是很少有⽤到Bean的ID的)
- 如果Bean實作了BeanFactoryAware接⼝,Spring将調⽤setBeanDactory(BeanFactory bf)⽅法并把BeanFactory容器執行個體作為參數傳⼊。(實作BeanFactoryAware 主要⽬的是為了擷取Spring容器,如Bean通過Spring容器釋出事件等)
- 如果Bean實作了ApplicationContextAwaer接⼝,Spring容器将調⽤setApplicationContext(ApplicationContext ctx)⽅法,把y應⽤上下⽂作為參數傳⼊.(作⽤與BeanFactory類似都是為了擷取Spring容器,不同的是Spring容器在調⽤setApplicationContext⽅法時會把它⾃⼰作為setApplicationContext 的參數傳⼊,⽽Spring容器在調⽤setBeanDactory前需要程式員⾃⼰指定(注⼊)setBeanDactory⾥的參數BeanFactory )
- 如果Bean實作了BeanPostProcess接⼝,Spring将調⽤它們的postProcessBeforeInitialization(預初始化)⽅法(作⽤是在Bean執行個體建立成功後對進⾏增強處理,如對Bean進⾏修改,增加某個功能)
- 如果Bean實作了InitializingBean接⼝,Spring将調⽤它們的afterPropertiesSet⽅法,作⽤與在配置⽂件中對Bean使⽤init-method聲明初始化的作⽤⼀樣,都是在Bean的全部屬性設定成功後執⾏的初始化⽅法。
- 如果Bean實作了BeanPostProcess接⼝,Spring将調⽤它們的postProcessAfterInitialization(後初始化)⽅法(作⽤與7的⼀樣,隻不過7是在Bean初始化前執⾏的,⽽這個是在Bean初始化後執⾏的,時機不同 )
- 經過以上的⼯作後,Bean将⼀直駐留在應⽤上下⽂中給應⽤使⽤,直到應⽤上下⽂被銷毀
- 如果Bean實作了DispostbleBean接⼝,Spring将調⽤它的destory⽅法,作⽤與在配置⽂件中對Bean使⽤destorymethod屬性的作⽤⼀樣,都是在Bean執行個體銷毀前執⾏的⽅法。
2. SpringBoot項⽬啟動時執⾏特定的⽅法
我們可以通過實作
ApplicationRunner
和
CommandLineRunner
來實作,他們都是在SpringApplication 執⾏之後開始執⾏的。
3. SpringMVC處理請求的流程
- 請求解析和比對DipatcherServlet路徑:用戶端發出⼀個http請求給web伺服器,web伺服器對http請求進⾏解析,如果比對DispatcherServlet的請求映射路徑(在web.xml中指定),web容器将請求轉交給DispatcherServlet。
- 比對處理器Handler:DipatcherServlet接收到這個請求之後将根據請求的資訊(包括URL、Http⽅法、請求報⽂頭和請求參數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。
- 處理器進⾏處理:DispatcherServlet根據HandlerMapping找到對應的Handler,将處理權交給Handler(Handler将具體的處理進⾏封裝),再由具體的HandlerAdapter對Handler進⾏具體的調⽤。
- 處理器傳回邏輯視圖ModelAndView對象給DispatcherServlet:Handler對資料處理完成以後将傳回⼀個ModelAndView()對象給DispatcherServlet。
- Dispatcher通過ViewResolver将邏輯視圖轉化為正式視圖view:Handler傳回的ModelAndView()隻是⼀個邏輯視圖并不是⼀個正式的視圖,DispatcherSevlet通過ViewResolver将邏輯視圖轉化為真正的視圖View。
- Dispatcher通過model解析出ModelAndView()中的參數進⾏解析最終展現出完整的view并傳回給用戶端。
4. Spring AOP解決了什麼問題?怎麼實作的?
作⽤:
- AOP技術,利⽤⼀種稱為“橫切”的技術,剖解開封裝的對象内部,并将那些影響了多個類的公共⾏為封裝到⼀個可重⽤子產品,并将其名為“Aspect”,即⽅⾯。所謂“⽅⾯”,簡單地說,就是将那些與業務⽆關,卻為業務子產品所共同調⽤的邏輯或責任封裝起來,便于減少系統的重複代碼,降低子產品間的耦合度,并有利于未來的可操作性和可維護性。
實作:
- ⼀是采⽤動态代理技術,利⽤截取消息的⽅式,對該消息進⾏裝飾,以取代原有對象⾏為的執⾏;
- ⼆是采⽤靜态織⼊的⽅式,引⼊特定的文法建立“⽅⾯”,從⽽使得編譯器可以在編譯期間織⼊有關“⽅⾯”的代碼。
使⽤場景:
- Authentication 權限
- Caching 緩存
- Context passing 内容傳遞
- Error handling 錯誤處理
- Lazy loading 懶加載
- Debugging 調試
- logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準
- Performance optimization 性能優化
- Persistence 持久化
- Resource pooling 資源池
- Synchronization 同步
- Transactions 事務
⼏個概念:
- 切⾯(Aspect):對象操作過程中的截⾯,這可能是AOP中最為關鍵的術語。切⾯所要做的事就是專注于各⾃領域的邏輯實作,這樣可以使得開發邏輯更加清晰,更加适合專業的分⼯合作。由于切⾯的隔離性,降低了耦合,這樣就可以在不同的應⽤中将各個切⾯組合使⽤,從⽽是代碼重⽤性⼤⼤增加。
- 連接配接點:程式運⾏過程中的某個階段點,如某個⽅法的調⽤,或者異常的抛出。
- 處理邏輯(Advice):在某⼀個連接配接點所采⽤的處理邏輯,處理邏輯的調⽤模式通常有三種:
a.Around 在連接配接點前後插⼊預處理過程和後處理過程。
b.Before 僅在連接配接點錢出⼊處理過程。
c.Throw在連接配接點抛出異常時進⾏異常處理。 Advice有的譯為“通知”,說法不⼀,我側重于“處理邏輯”出⾃于Spring開發指南⼀⽂。
- 切點(PointCut):⼀系列連接配接點的集合,它指明處理邏輯将在合适觸發。
5. Spring事務的傳播屬性是怎麼回事?它會影響什麼?
七個事傳播屬性:
- PROPAGATION_REQUIRED – ⽀持目前事務,如果目前沒有事務,就建立⼀個事務。這是最常⻅的選擇。
- PROPAGATION_SUPPORTS – ⽀持目前事務,如果目前沒有事務,就以⾮事務⽅式執⾏。
- PROPAGATION_MANDATORY – ⽀持目前事務,如果目前沒有事務,就抛出異常。
- PROPAGATIONREQUIRESNEW – 建立事務,如果目前存在事務,把目前事務挂起。
- PROPAGATIONNOTSUPPORTED – 以⾮事務⽅式執⾏操作,如果目前存在事務,就把目前事務挂起。
- PROPAGATION_NEVER – 以⾮事務⽅式執⾏,如果目前存在事務,則抛出異常。
- PROPAGATIONNESTED – 如果目前存在事務,則在嵌套事務内執⾏。如果目前沒有事務,則進⾏與PROPAGATIONREQUIRED類似的操作。
五個隔離級别:
- ISOLATION_DEFAULT 這是⼀個PlatfromTransactionManager預設的隔離級别,使⽤資料庫預設的事務隔離級别.
- 另外四個與JDBC的隔離級别相對應:
- ISOLATIONREADUNCOMMITTED 這是事務最低的隔離級别,它充許别外⼀個事務可以看到這個事務未送出的資料。這種隔離級别會産⽣髒讀,不可重複讀和幻讀。
- ISOLATIONREADCOMMITTED 保證⼀個事務修改的資料送出後才能被另外⼀個事務讀取。另外⼀個事務不能讀取該事務未送出的資料。這種事務隔離級别可以避免髒讀出現,但是可能會出現不可重複讀和幻讀。
- ISOLATIONREPEATABLEREAD 這種事務隔離級别可以防⽌髒讀,不可重複讀。但是可能出現幻讀。它除了保證⼀個事務不能讀取另⼀個事務未送出的資料外,還保證了避免不可重複讀。
- ISOLATION_SERIALIZABLE 這是花費最⾼代價但是最可靠的事務隔離級别。事務被處理為順序執⾏。除了防⽌髒讀,不可重複讀外,還避免了幻讀。
關鍵詞:
- 幻讀:事務1讀取記錄時事務2增加了記錄并送出,事務1再次讀取時可以看到事務2新增的記錄;不可重複讀:事務1讀取記錄時,事務2更新了記錄并送出,事務1再次讀取時可以看到事務2修改後的記錄;
- 髒讀:事務1更新了記錄,但沒有送出,事務2讀取了更新後的⾏,然後事務T1復原,現在T2讀取⽆效。
6. Spring中BeanFactory和FactoryBean有什麼差別?
- BeanFactory,以Factory結尾,表示它是⼀個⼯⼚類(接⼝),⽤于管理Bean的⼀個⼯⼚。在Spring中,BeanFactory是IOC容器的核⼼接⼝,它的職責包括:執行個體化、定位、配置應⽤程式中的對象及建⽴這些對象間的依賴。
- FactoryBean以Bean結尾,表示它是⼀個Bean,不同于普通Bean的是:它是實作了FactoryBean接⼝的Bean,根據該Bean的ID從BeanFactory中擷取的實際上是FactoryBean的getObject()傳回的對象,⽽不是FactoryBean本身,如果要擷取FactoryBean對象,請在id前⾯加⼀個&符号來擷取。
7. Spring架構中IOC的原理是什麼?
- IoC(Inversion of Control)是指容器控制程式對象之間的關系,⽽不是傳統實作中,由程式代碼直接操控。控制權由應⽤代碼中轉到了外部容器,控制權的轉移是所謂反轉。 對于Spring⽽⾔,就是由Spring來控制對象的⽣命周期和對象之間的關系;IoC還有另外⼀個名字——“依賴注⼊(Dependency Injection)”。從名字上了解,所謂依賴注⼊,即元件之間的依賴關系由容器在運⾏期決定,即由容器動态地将某種依賴關系注⼊到元件之中。
- 在Spring的⼯作⽅式中,所有的類都會在spring容器中登記,告訴spring這是個什麼東⻄,你需要什麼東⻄,然後spring會在系統運⾏到适當的時候,把你要的東⻄主動給你,同時也把你交給其他需要你的東⻄。所有的類的建立、銷毀都由spring來控制,也就是說控制對象⽣存周期的不再是引⽤它的對象,⽽是spring。對于某個具體的對象⽽⾔,以前是它控制其他對象,現在是所有對象都被spring控制,是以這叫控制反轉。
- 在系統運⾏中,動态的向某個對象提供它所需要的其他對象。
- 依賴注⼊的思想是通過反射機制實作的,在執行個體化⼀個類時,它通過反射調⽤類中set⽅法将事先儲存在HashMap中的類屬性注⼊到類中。 總⽽⾔之,在傳統的對象建立⽅式中,通常由調⽤者來建立被調⽤者的執行個體,⽽在Spring中建立被調⽤者的⼯作由Spring來完成,然後注⼊調⽤者,即所謂的依賴注⼊or控制反轉。 注⼊⽅式有兩種:依賴注⼊和設定注⼊; IoC的優點:降低了元件之間的耦合,降低了業務對象之間替換的複雜性,使之能夠靈活的管理對象。
8. spring的依賴注⼊有哪⼏種⽅式?
在Spring容器中為⼀個bean配置依賴注⼊有四種⽅式:
- 使⽤屬性的setter⽅法注⼊ 這是最常⽤的⽅式;
- 使⽤構造器注⼊;
- 使⽤Filed注⼊(⽤于注解⽅式);
- 靜态、執行個體⼯⼚的⽅法注⼊;
9. ⽤Spring如何實作⼀個切⾯?
10. Spring如何實作資料庫事務?
使⽤@Transactional注解或在配置⽂件⾥⾯配置。
11. Spring加載次序Classloader
先構造函數——>然後是bean的set⽅法注⼊——>InitializingBean的afterPropertiesSet⽅法——>init-method⽅法;
InitializingBean接⼝為bean提供了初始化⽅法的⽅式,它隻包括afterPropertiesSet⽅法,凡是繼承該接⼝的類,在初始化bean的時候會執⾏該⽅法。系統則是先調⽤afterPropertiesSet⽅法,然後在調⽤init-method中指定的⽅法。
Spring裝配Bean的過程:
- 執行個體化;
- 設定屬性值;
- 如果實作了BeanNameAware接⼝,調⽤setBeanName設定Bean的ID或者Name;
- 如果實作BeanFactoryAware接⼝,調⽤setBeanFactory 設定BeanFactory;
- 如果實作ApplicationContextAware,調⽤setApplicationContext設定ApplicationContext
- 調⽤BeanPostProcessor的預先初始化⽅法;
- 調⽤InitializingBean的afterPropertiesSet()⽅法;
- 調⽤定制init-method⽅法;
- 調⽤BeanPostProcessor的後初始化⽅法;
Spring容器關閉過程:
- 調⽤DisposableBean的destroy();
- 調⽤定制的destroy-method⽅法;
12. 架構的優缺點SpringMVC,Struts2等…
- Struts2是類級别攔截,參數為類中所有⽅法共有,⼀個Action對應⼀個request上下⽂,SpringMVC是⽅法級别攔截,參數為對應⽅法所有;
- 由于Struts2需要針對每個request進⾏封裝,把request,session等servlet⽣命周期的變量封裝成⼀個⼀個Map,供給每個Action使⽤,并保證線程安全,是以在原則上,是⽐較耗費記憶體的。
- 攔截器實作機制上,Struts2有以⾃⼰的interceptor機制,SpringMVC⽤的是獨⽴的AOP⽅式,這樣導緻Struts2的配置⽂件量還是⽐SpringMVC⼤。
- SpringMVC的⼊⼝是servlet,⽽Struts2是filter
- SpringMVC內建了Ajax,使⽤⾮常⽅便,隻需⼀個注解@ResponseBody就可以實作,然後直接傳回響應⽂本即可,⽽Struts2攔截器內建了Ajax,在Action中處理時⼀般必須安裝插件或者⾃⼰寫代碼內建進去,使⽤起來也相對不⽅便。
- SpringMVC開發效率和性能⾼于Struts2。
- SpringMVC配置少,零配置。
13. IOC控制反轉與DI依賴注⼊
- IOC控制反轉:是⼀種将對象交給容器去控制的設計思想,松耦合,⽅便單元測試,增加功能重⽤性;
- DI依賴注⼊:元件之間依賴關系由容器在運⾏期決定,形象的說,即由容器動态的将某個依賴關系注⼊到元件之中。依賴注⼊的⽬的并⾮為軟體系統帶來更多功能,⽽是為了提升元件重⽤的頻率,并為系統搭建⼀個靈活、可擴充的平台。通過依賴注⼊機制,我們隻需要通過簡單的配置,⽽⽆需任何代碼就可指定⽬标需要的資源,完成⾃身的業務邏輯,⽽不需要關⼼具體的資源來⾃何處,由誰實作。
- AOP⾯向切⾯程式設計:⾯向切⾯程式設計(AOP)完善spring的依賴注⼊(DI)。
14. AOP開發
1.導⼊aop依賴包:
2.建立切面類
通知⽅法類型:
前置通知(logStart):在⽬标⽅法運⾏之前運⾏;
後置通知(logEnd):在⽬标⽅法運⾏結束之後運⾏;
傳回通知(logReturn):在⽬标⽅法正常傳回之後運⾏;
異常通知(logException):在⽬标⽅法出現異常是運⾏;
環繞通知(動态代理):⼿動推薦⽬标⽅法運⾏(joinPoint.procced())。
3.将切⾯類和⽬标類都加⼊到容器中,并開啟基于注解的aop動态代理
public class MathCalculator { 2 public int div(int i, int j) { 3 System.out.println("MathCalculator.div....."); 4 return i/j; 5 } 67 } /**
* aop
* 在程式運⾏期間動态的将某段代碼切⼊到指定⽅法指定位置進⾏運⾏的程式設計⽅式
* '@EnableAspectJAutoProxy':開啟基于注解的aop動态代理
*/
@Configuration
@EnableAspectJAutoProxy
public class MainConfigOfAOP {
/**
* 業務邏輯類加⼊容器中
*/
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
/**
* 切⾯類加⼊容器中
*
*/
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
4.測試:
15. 事務配置
1.@EnableTransactionManagement開啟事務配置功能;
2.容器中配置DataSource、JdbcTemplate、PlatformTransactionManager三個Bean執行個體;
3.使⽤@Transactional注解開啟事務。
16. springboot的啟動過程:
- 通過 SpringFactoriesLoader加載 META-INF/spring.factories⽂件,擷取并建立 SpringApplicationRunListener對象
- 然後由 SpringApplicationRunListener來發出 starting 消息
- 建立參數,并配置目前 SpringBoot 應⽤将要使⽤的 Environment
- 完成之後,依然由 SpringApplicationRunListener來發出 environmentPrepared 消息
- 建立 ApplicationContext
- 初始化 ApplicationContext,并設定 Environment,加載相關配置等
- 由 SpringApplicationRunListener來發出 contextPrepared消息,告知SpringBoot 應⽤使⽤的 ApplicationContext已準備OK
- 将各種 beans 裝載⼊ ApplicationContext,繼續由 SpringApplicationRunListener來發出 contextLoaded 消息,告知SpringBoot 應⽤使⽤的 ApplicationContext已裝填OK
- refresh ApplicationContext,完成IoC容器可⽤的最後⼀步
- 由 SpringApplicationRunListener來發出 started 消息
- 完成最終的程式的啟動
- 由 SpringApplicationRunListener來發出 running 消息,告知程式已運⾏起來了
17. spring事件的實作原理,寫出常⽤的⼏個事件
- Spring中的事件機制是⼀個觀察者模式的實作.觀察者模式就是⼀個⽬标對象管理所有相依于它的觀察者對象,并且在它本身的狀态改變時主動發出通知.Spring的事件由ApplicationContext釋出。
- ContextStartedEvent:ApplicationContext啟動後觸發的事件
- ContextStoppedEvent:ApplicationContext停⽌後觸發的事件
- ContextRefreshedEvent:ApplicationContext初始化或重新整理完成後觸發的事件
- ContextClosedEvent:ApplicationContext關閉後觸發的事件