什么是spring?
Spring是一個輕量級Java開發框架,最早有Rod Johnson創建,目的是為了解決企業級應用開發的業務邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack(一站式)輕量級開源框架,為開發Java應用程序提供全面的基礎架構支持。Spring負責基礎架構,因此Java開發者可以專注于應用程序的開發。
Spring最根本的使命是解決企業級應用開發的復雜性,即簡化Java開發。
Spring可以做很多事情,它為企業級開發提供給了豐富的功能,但是這些功能的底層都依賴于它的兩個核心特性,也就是依賴注入(dependency injection,DI)和面向切面編程(aspect-oriented programming,AOP)。
為了降低Java開發的復雜性,Spring采取了以下4種關鍵策略
基于POJO的輕量級和最小侵入性編程;
通過依賴注入和面向接口實現松耦合;
基于切面和慣例進行聲明式編程;
通過切面和模板減少樣板式代碼。
Spring 框架中都用到了哪些設計模式?
工廠模式:BeanFactory就是簡單工廠模式的體現,用來創建對象的實例;
單例模式:Bean默認為單例模式。
代理模式:Spring的AOP功能用到了JDK的動態代理和CGLIB字節碼生成技術;
模板方法:用來解決代碼重復的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。
觀察者模式:定義對象鍵一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都會得到通知被制動更新,如Spring中listener的實現–ApplicationListener。
什么是Spring IOC 容器?
控制反轉即IoC (Inversion of Control),它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。
Spring IOC 負責創建對象,管理對象(通過依賴注入(DI),裝配對象,配置對象,并且管理這些對象的整個生命周期。
控制反轉(IoC)有什么作用
- 管理對象的創建和依賴關系的維護。
- 解耦,由容器去維護具體的對象
什么是Spring的依賴注入?
控制反轉IoC是一個很大的概念,可以用不同的方式來實現。其主要實現方式有兩種:依賴注入和依賴查找
依賴注入:相對于IoC而言,依賴注入(DI)更加準確地描述了IoC的設計理念。所謂依賴注入(Dependency Injection),即組件之間的依賴關系由容器在應用系統運行期來決定,也就是由容器動態地將某種依賴關系的目標對象實例注入到應用系統中的各個關聯的組件之中。組件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關系。
依賴注入的基本原則
依賴注入的基本原則是:應用組件不應該負責查找資源或者其他依賴的協作對象。配置對象的工作應該由IoC容器負責,“查找資源”的邏輯應該從應用組件的代碼中抽取出來,交給IoC容器負責。容器全權負責組件的裝配,它會把符合依賴關系的對象通過屬性(JavaBean中的setter)或者是構造器傳遞給需要的對象。
依賴注入有什么優勢
依賴注入之所以更流行是因為它是一種更可取的方式:讓容器全權負責依賴查詢,受管組件只需要暴露JavaBean的setter方法或者帶參數的構造器或者接口,使容器可以在初始化時組裝對象的依賴關系。其與依賴查找方式相比,主要優勢為:
查找定位操作與應用代碼完全無關。
不依賴于容器的API,可以很容易地在任何容器以外使用應用對象。
不需要特殊的接口,絕大多數對象可以做到完全不必依賴容器。
有哪些不同類型的依賴注入實現方式?
依賴注入是時下最流行的IoC實現方式,依賴注入分為接口注入(Interface Injection),Setter方法注入(Setter Injection)和構造器注入(Constructor Injection)三種方式。其中接口注入由于在靈活性和易用性比較差,現在從Spring4開始已被廢棄。
構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列參數,每個參數代表一個對其他類的依賴。
Setter方法注入:Setter方法注入是容器通過調用無參構造器或無參static工廠 方法實例化bean之后,調用該bean的setter方法,即實現了基于setter的依賴注入。
Spring 中的 IOC(控制反轉) 的實現原理就是工廠模式加反射機制。
BeanFactory 和 ApplicationContext有什么區別?
BeanFactory和ApplicationContext是Spring的兩大核心接口,都可以當做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
依賴關系
BeanFactory:是Spring里面最底層的接口,包含了各種Bean的定義,讀取bean配置文檔,管理bean的加載、實例化,控制bean的生命周期,維護bean之間的依賴關系。
ApplicationContext接口作為BeanFactory的派生,除了提供BeanFactory所具有的功能外,還提供了更完整的框架功能:
- 繼承MessageSource,因此支持國際化。
- 統一的資源文件訪問方式。
- 提供在監聽器中注冊bean的事件。
- 同時加載多個配置文件。
加載方式
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則是自動注冊。
什么是Spring beans?
Spring beans 是那些形成Spring應用的主干的java對象。它們被Spring IOC容器初始化,裝配,和管理。這些beans通過容器中配置的元數據創建。比如,以XML文件中 的形式定義。
一個Spring Bean 的定義包含容器必知的所有配置元數據,包括如何創建一個bean,它的生命周期詳情及它的依賴。
這里有三種重要的方法給Spring 容器提供配置元數據。
- XML配置文件。
- 基于注解的配置。
- 基于java的配置。
Spring配置文件是個XML 文件,這個文件包含了類信息,描述了如何配置它們,以及如何相互調用。
Spring基于xml注入bean的幾種方式
- Set方法注入;
- 構造器注入:①通過index設置參數的位置;②通過type設置參數類型;
- 靜態工廠注入;
- 實例工廠;
怎樣定義類的作用域?
當定義一個 在Spring里,我們還能給這個bean聲明一個作用域。它可以通過bean 定義中的scope屬性來定義。如,當Spring要在需要的時候每次生產一個新的bean實例,bean的scope屬性被指定為prototype。另一方面,一個bean每次使用的時候必須返回同一個實例,這個bean的scope 屬性 必須設為 singleton。
singleton : bean在每個Spring ioc 容器中只有一個實例。
prototype:一個bean的定義可以有多個實例。
request:每次http請求都會創建一個bean,該作用域僅在基于web的Spring ApplicationContext情形下有效。
session:在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基于web的Spring ApplicationContext情形下有效。
global-session:在一個全局的HTTP Session中,一個bean定義對應一個實例。該作用域僅在基于web的Spring ApplicationContext情形下有效。
Spring框架中的單例bean是線程安全的嗎?
不是,Spring框架中的單例bean不是線程安全的。
spring 中的 bean 默認是單例模式,spring 框架并沒有對單例 bean 進行多線程的封裝處理。
實際上大部分時候 spring bean 無狀態的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態的話(比如 view model 對象),那就要開發者自己去保證線程安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當于 new Bean()了,所以就可以保證線程安全了。
Spring框架中bean的生命周期
在傳統的Java應用中,bean的生命周期很簡單。使用Java關鍵字new進行bean實例化,然后該bean就可以使用了。一旦該bean不再被使用,則由Java自動進行垃圾回收。相比之下,Spring容器中的bean的生命周期就顯得相對復雜多了。正確理解Spring bean的生命周期非常重要,因為你或許要利用Spring提供的擴展點來自定義bean的創建過程。下圖展示了bean裝載到Spring應用上下文中的一個典型的生命周期過程。
什么是bean的自動裝配?
在Spring框架中,在配置文件中設定bean的依賴關系是一個很好的機制,Spring 容器能夠自動裝配相互合作的bean,這意味著容器不需要和配置,能通過Bean工廠自動處理bean之間的協作。這意味著 Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關系。自動裝配可以設置在每個bean上,也可以設定在特定的bean上。
使用@Autowired注解自動裝配的過程是怎樣的?
使用@Autowired注解來自動裝配指定的bean。在使用@Autowired注解之前需要在Spring配置文件進行配置,<context:annotation-config />。
在啟動spring IoC時,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor后置處理器,當容器掃描到@Autowied、@Resource或@Inject時,就會在IoC容器自動查找需要的bean,并裝配給該對象的屬性。在使用@Autowired時,首先在容器中查詢對應類型的bean:
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數據;
如果查詢的結果不止一個,那么@Autowired會根據名稱來查找;
如果上述查找的結果為空,那么會拋出異常。解決方法時,使用required=false。
Spring 常用注解
@Component:這將 java 類標記為 bean。它是任何 Spring 管理組件的通用構造型。spring 的組件掃描機制現在可以將其拾取并將其拉入應用程序環境中。
@Controller:這將一個類標記為 Spring Web MVC 控制器。標有它的 Bean 會自動導入到 IoC 容器中。
@Service:此注解是組件注解的特化。它不會對 @Component 注解提供任何其他行為。您可以在服務層類中使用 @Service 而不是 >@Component,因為它以更好的方式指定了意圖。
@Repository:這個注解是具有類似用途和功能的 @Component 注解的特化。它為 DAO 提供了額外的好處。它將 DAO 導入 IoC 容器,并使未經檢查的異常有資格轉換為 Spring DataAccessException。
@Required :這個注解表明bean的屬性必須在配置的時候設置,通過一個bean定義的顯式的屬性值或通過自動裝配,若@Required注解的bean屬性未被設置,容器將拋出BeanInitializationException
@Autowired默認是按照類型裝配注入的,默認情況下它要求依賴對象必須存在(可以設置它required屬性為false)。@Autowired 注解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required一樣,修飾setter方法、構造器、屬性或者具有任意名稱和/或多個參數的PN方法。
Spring支持的事務管理類型, 事務實現方式有哪些?
編程式事務管理:這意味你通過編程的方式管理事務,給你帶來極大的靈活性,但是難維護。
聲明式事務管理:這意味著你可以將業務代碼和事務管理分離,你只需用注解和XML配置來管理事務。
Spring事務的本質其實就是數據庫對事務的支持,沒有數據庫的事務支持,spring是無法提供事務功能的。真正的數據庫層的事務提交和回滾是通過binlog或者redo log實現的。