Spring Framework 如今幾乎已成爲 Java Web 開發的標配框架。那麼,做爲 Java 程序員,你對 Spring 的主要技術點又掌握了多少呢?不妨用本文的問題來檢測一下。前端
VersionFeatureSpring 2.5發佈於 2007 年。這是第一個支持註解的版本。Spring 3.0發佈於 2009 年。它徹底利用了 Java5 中的改進,併爲 JEE6 提供了支持。Spring 4.0發佈於 2013 年。這是第一個徹底支持 JAVA8 的版本。java
Spring 是一個開源應用框架,旨在下降應用程序開發的複雜度。程序員
它是輕量級、鬆散耦合的。web
它具備分層體系結構,容許用戶選擇組件,同時還爲 J2EE 應用程序開發提供了一個有凝聚力的框架。面試
它能夠集成其餘框架,如 Structs、Hibernate、EJB 等,因此又稱爲框架的框架。spring
AOP – 該層支持面向切面編程數據庫
Instrumentation – 該層爲類檢測和類加載器實現提供支持。編程
Test – 該層爲使用 JUnit 和 TestNG 進行測試提供支持。安全
幾個雜項模塊:bash
Spring 配置文件是 XML 文件。該文件主要包含類信息。它描述了這些類是如何配置以及相互引入的。可是,XML 配置文件冗長且更加乾淨。若是沒有正確規劃和編寫,那麼在大項目中管理變得很是困難。
Spring 應用通常有如下組件:
接口 - 定義功能。
Bean 類 - 它包含屬性,setter 和 getter 方法,函數等。
Spring 面向切面編程(AOP) - 提供面向切面編程的功能。
Bean 配置文件 - 包含類的信息以及如何配置它們。
用戶程序 - 它使用接口。
使用 Spring 有如下方式:
做爲一個成熟的 Spring Web 應用程序。
做爲第三方 Web 框架,使用 Spring Frameworks 中間層。
用於遠程使用。
做爲企業級 Java Bean,它能夠包裝現有的 POJO(Plain Old Java Objects)。
Spring 框架的核心是 Spring 容器。容器建立對象,將它們裝配在一塊兒,配置它們並管理它們的完整生命週期。Spring 容器使用依賴注入來管理組成應用程序的組件。容器經過讀取提供的配置元數據來接收對象進行實例化,配置和組裝的指令。該元數據能夠經過 XML,Java 註解或 Java 代碼提供。
在依賴注入中,您沒必要建立對象,但必須描述如何建立它們。您不是直接在代碼中將組件和服務鏈接在一塊兒,而是描述配置文件中哪些組件須要哪些服務。由 IoC 容器將它們裝配在一塊兒。
一般,依賴注入能夠經過三種方式完成,即:
構造函數注入
setter 注入
接口注入
在 Spring Framework 中,僅使用構造函數和 setter 注入。
構造函數注入setter 注入沒有部分注入有部分注入不會覆蓋 setter 屬性會覆蓋 setter 屬性任意修改都會建立一個新實例任意修改不會建立一個新實例適用於設置不少屬性適用於設置少許屬性
BeanFactory - BeanFactory 就像一個包含 bean 集合的工廠類。它會在客戶端要求時實例化 bean。
ApplicationContext - ApplicationContext 接口擴展了 BeanFactory 接口。它在 BeanFactory 基礎上提供了一些額外的功能。
BeanFactoryApplicationContext它使用懶加載它使用即時加載它使用語法顯式提供資源對象它本身建立和管理資源對象不支持國際化支持國際化不支持基於依賴的註解支持基於依賴的註解
IoC 的一些好處是:
它將最小化應用程序中的代碼量。
它將使您的應用程序易於測試,由於它不須要單元測試用例中的任何單例或 JNDI 查找機制。
它以最小的影響和最少的侵入機制促進鬆耦合。
它支持即時的實例化和延遲加載服務。
Spring 中的 IoC 的實現原理就是工廠模式加反射機制。
示例:
它們是構成用戶應用程序主幹的對象。
Bean 由 Spring IoC 容器管理。
它們由 Spring IoC 容器實例化,配置,裝配和管理。
Bean 是基於用戶提供給容器的配置元數據建立。
bean 所需的依賴項和服務在 XML 格式的配置文件中指定。這些配置文件一般包含許多 bean 定義和特定於應用程序的配置選項。它們一般以 bean 標籤開頭。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean"> <property name="name" value="Edureka"></property> </bean> 複製代碼
您能夠經過在相關的類,方法或字段聲明上使用註解,將 bean 配置爲組件類自己,而不是使用 XML 來描述 bean 裝配。默認狀況下,Spring 容器中未打開註解裝配。所以,您須要在使用它以前在 Spring 配置文件中啓用它。例如:
<beans> <context:annotation-config/> <!-- bean definitions go here --> </beans> 複製代碼
Spring 的 Java 配置是經過使用 @Bean 和 @Configuration 來實現。
@Bean 註解扮演與 <bean /> 元素相同的角色。
@Configuration 類容許經過簡單地調用同一個類中的其餘 @Bean 方法來定義 bean 間依賴關係。
例如:
@Configuration public class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); } } 複製代碼
Spring bean 支持 5 種 scope:
Singleton - 每一個 Spring IoC 容器僅有一個單實例。
Prototype - 每次請求都會產生一個新的實例。
Request - 每一次 HTTP 請求都會產生一個新的實例,而且該 bean 僅在當前 HTTP 請求內有效。
Session - 每一次 HTTP 請求都會產生一個新的 bean,同時該 bean 僅在當前 HTTP session 內有效。
Global-session - 相似於標準的 HTTP Session 做用域,不過它僅僅在基於 portlet 的 web 應用中才有意義。Portlet 規範定義了全局 Session 的概念,它被全部構成某個 portlet web 應用的各類不一樣的 portlet 所共享。在 global session 做用域中定義的 bean 被限定於全局 portlet Session 的生命週期範圍內。若是你在 web 中使用 global session 做用域來標識 bean,那麼 web 會自動當成 session 類型來使用。
僅當用戶使用支持 Web 的 ApplicationContext 時,最後三個纔可用。
spring bean 容器的生命週期流程以下:
Spring 容器根據配置中的 bean 定義中實例化 bean。
Spring 使用依賴注入填充全部屬性,如 bean 中所定義的配置。
若是 bean 實現 BeanNameAware 接口,則工廠經過傳遞 bean 的 ID 來調用 setBeanName()。
若是 bean 實現 BeanFactoryAware 接口,工廠經過傳遞自身的實例來調用 setBeanFactory()。
若是存在與 bean 關聯的任何 BeanPostProcessors,則調用 preProcessBeforeInitialization() 方法。
若是爲 bean 指定了 init 方法(<bean> 的 init-method 屬性),那麼將調用它。
最後,若是存在與 bean 關聯的任何 BeanPostProcessors,則將調用 postProcessAfterInitialization() 方法。
若是 bean 實現 DisposableBean 接口,當 spring 容器關閉時,會調用 destory()。
若是爲 bean 指定了 destroy 方法(<bean> 的 destroy-method 屬性),那麼將調用它。
只有將 bean 用做另外一個 bean 的屬性時,才能將 bean 聲明爲內部 bean。爲了定義 bean,Spring 的基於 XML 的配置元數據在 <property> 或 <constructor-arg>中提供了 <bean> 元素的使用。內部 bean 老是匿名的,它們老是做爲原型。
例如,假設咱們有一個 Student 類,其中引用了 Person 類。這裏咱們將只建立一個 Person 類實例並在 Student 中使用它。
Student.java public class Student { private Person person; //Setters and Getters } public class Person { private String name; private String address; //Setters and Getters } bean.xml <bean id=「StudentBean" class="com.edureka.Student"> <property name="person"> <!--This is inner bean --> <bean class="com.edureka.Person"> <property name="name" value=「Scott"></property> <property name="address" value=「Bangalore"></property> </bean> </property> </bean> 複製代碼
當 bean 在 Spring 容器中組合在一塊兒時,它被稱爲裝配或 bean 裝配。 Spring 容器須要知道須要什麼 bean 以及容器應該如何使用依賴注入來將 bean 綁定在一塊兒,同時裝配 bean。
Spring 容器可以自動裝配 bean。也就是說,能夠經過檢查 BeanFactory 的內容讓 Spring 自動解析 bean 的協做者。
自動裝配的不一樣模式:
no - 這是默認設置,表示沒有自動裝配。應使用顯式 bean 引用進行裝配。
byName - 它根據 bean 的名稱注入對象依賴項。它匹配並裝配其屬性與 XML 文件中由相同名稱定義的 bean。
byType - 它根據類型注入對象依賴項。若是屬性的類型與 XML 文件中的一個 bean 名稱匹配,則匹配並裝配屬性。
構造函數 - 它經過調用類的構造函數來注入依賴項。它有大量的參數。
autodetect - 首先容器嘗試經過構造函數使用 autowire 裝配,若是不能,則嘗試經過 byType 自動裝配。
覆蓋的可能性 - 您始終可使用 <constructor-arg> 和 <property> 設置指定依賴項,這將覆蓋自動裝配。
基本元數據類型 - 簡單屬性(如原數據類型,字符串和類)沒法自動裝配。
使人困惑的性質 - 老是喜歡使用明確的裝配,由於自動裝配不太精確。
不使用 XML 來描述 bean 裝配,開發人員經過在相關的類,方法或字段聲明上使用註解將配置移動到組件類自己。它能夠做爲 XML 設置的替代方案。例如:
Spring 的 Java 配置是經過使用 @Bean 和 @Configuration 來實現。
例如:
@Configuration public class StudentConfig { @Bean public StudentBean myStudent() { return new StudentBean(); } } 複製代碼
默認狀況下,Spring 容器中未打開註解裝配。所以,要使用基於註解裝配,咱們必須經過配置<context:annotation-config /> 元素在 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 屬性 setter 方法。此註解僅指示必須在配置時使用 bean 定義中的顯式屬性值或使用自動裝配填充受影響的 bean 屬性。若是還沒有填充受影響的 bean 屬性,則容器將拋出 BeanInitializationException。
示例:
public class Employee { private String name; @Required public void setName(String name){ this.name=name; } public string getName(){ return name; } } 複製代碼
@Autowired 能夠更準確地控制應該在何處以及如何進行自動裝配。此註解用於在 setter 方法,構造函數,具備任意名稱或多個參數的屬性或方法上自動裝配 bean。默認狀況下,它是類型驅動的注入。
public class Employee { private String name; @Autowired public void setName(String name) { this.name=name; } public string getName(){ return name; } } 複製代碼
當您建立多個相同類型的 bean 並但願僅使用屬性裝配其中一個 bean 時,您可使用@Qualifier 註解和 @Autowired 經過指定應該裝配哪一個確切的 bean 來消除歧義。
例如,這裏咱們分別有兩個類,Employee 和 EmpAccount。在 EmpAccount 中,使用@Qualifier 指定了必須裝配 id 爲 emp1 的 bean。
Employee.java public class Employee { private String name; @Autowired public void setName(String name) { this.name=name; } public string getName() { return name; } } EmpAccount.java public class EmpAccount { private Employee emp; @Autowired @Qualifier(emp1) public void showName() { System.out.println(「Employee name : 」+emp.getName); } } 複製代碼
@RequestMapping 註解用於將特定 HTTP 請求方法映射到將處理相應請求的控制器中的特定類/方法。此註釋可應用於兩個級別:
Spring DAO 使得 JDBC,Hibernate 或 JDO 這樣的數據訪問技術更容易以一種統一的方式工做。這使得用戶容易在持久性技術之間切換。它還容許您在編寫代碼時,無需考慮捕獲每種技術不一樣的異常。
咱們能夠經過兩種方式使用 Spring 訪問 Hibernate:
Spring 支持兩種類型的事務管理:
AOP(Aspect-Oriented Programming), 即 面向切面編程, 它與 OOP( Object-Oriented Programming, 面向對象編程) 相輔相成, 提供了與 OOP 不一樣的抽象軟件結構的視角.
在 OOP 中, 咱們以類(class)做爲咱們的基本單元, 而 AOP 中的基本單元是 Aspect(切面)
aspect 由 pointcount 和 advice 組成, 它既包含了橫切邏輯的定義, 也包括了鏈接點的定義. Spring AOP 就是負責實施切面的框架, 它將切面所定義的橫切邏輯編織到切面所指定的鏈接點中.
AOP 的工做重心在於如何將加強編織目標對象的鏈接點上, 這裏包含兩個工做:
如何經過 pointcut 和 advice 定位到特定的 joinpoint 上
如何在 advice 中編寫切面代碼.
能夠簡單地認爲, 使用 @Aspect 註解的類就是切面.
程序運行中的一些時間點, 例如一個方法的執行, 或者是一個異常的處理.
在 Spring AOP 中, join point 老是方法的執行點。
特定 JoinPoint 處的 Aspect 所採起的動做稱爲 Advice。Spring AOP 使用一個 Advice 做爲攔截器,在 JoinPoint 「周圍」維護一系列的攔截器。
Before - 這些類型的 Advice 在 joinpoint 方法以前執行,並使用 @Before 註解標記進行配置。
After Returning - 這些類型的 Advice 在鏈接點方法正常執行後執行,並使用@AfterReturning 註解標記進行配置。
After Throwing - 這些類型的 Advice 僅在 joinpoint 方法經過拋出異常退出並使用 @AfterThrowing 註解標記配置時執行。
After (finally) - 這些類型的 Advice 在鏈接點方法以後執行,不管方法退出是正常仍是異常返回,並使用 @After 註解標記進行配置。
Around - 這些類型的 Advice 在鏈接點以前和以後執行,並使用 @Around 註解標記進行配置。
concern 是咱們想要在應用程序的特定模塊中定義的行爲。它能夠定義爲咱們想要實現的功能。
cross-cutting concern 是一個適用於整個應用的行爲,這會影響整個應用程序。例如,日誌記錄,安全性和數據傳輸是應用程序幾乎每一個模塊都須要關注的問題,所以它們是跨領域的問題。
實現 AOP 的技術,主要分爲兩大類:
靜態代理 - 指使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,所以也稱爲編譯時加強;
編譯時編織(特殊編譯器實現)
類加載時編織(特殊的類加載器實現)。
動態代理 - 在運行時在內存中「臨時」生成 AOP 動態代理類,所以也被稱爲運行時加強。
JDK 動態代理
CGLIB
Spring AOP 基於動態代理方式實現;AspectJ 基於靜態代理方式實現。
Spring AOP 僅支持方法級別的 PointCut;提供了徹底的 AOP 支持,它還支持屬性級別的 PointCut。
將 Advice 應用於目標對象後建立的對象稱爲代理。在客戶端對象的狀況下,目標對象和代理對象是相同的。
Advice + Target Object = Proxy
爲了建立一個 advice 對象而連接一個 aspect 和其它應用類型或對象,稱爲編織(Weaving)。在 Spring AOP 中,編織在運行時執行。請參考下圖:
Spring Web MVC 框架提供 模型-視圖-控制器 架構和隨時可用的組件,用於開發靈活且鬆散耦合的 Web 應用程序。 MVC 模式有助於分離應用程序的不一樣方面,如輸入邏輯,業務邏輯和 UI 邏輯,同時在全部這些元素之間提供鬆散耦合。
7.2. 描述一下 DispatcherServlet 的工做流程
DispatcherServlet 的工做流程能夠用一幅圖來講明:
向服務器發送 HTTP 請求,請求被前端控制器 DispatcherServlet 捕獲。
DispatcherServlet 根據 -servlet.xml 中的配置對請求的 URL 進行解析,獲得請求資源標識符(URI)。而後根據該 URI,調用 HandlerMapping 得到該 Handler 配置的全部相關的對象(包括 Handler 對象以及 Handler 對象對應的攔截器),最後以HandlerExecutionChain 對象的形式返回。
DispatcherServlet 根據得到的Handler,選擇一個合適的HandlerAdapter。(附註:若是成功得到HandlerAdapter後,此時將開始執行攔截器的 preHandler(...)方法)。
提取Request中的模型數據,填充Handler入參,開始執行Handler(Controller)。 在填充Handler的入參過程當中,根據你的配置,Spring 將幫你作一些額外的工做:
HttpMessageConveter: 將請求消息(如 Json、xml 等數據)轉換成一個對象,將對象轉換爲指定的響應信息。
數據轉換:對請求消息進行數據轉換。如String轉換成Integer、Double等。
數據根式化:對請求消息進行數據格式化。 如將字符串轉換成格式化數字或格式化日期等。
數據驗證: 驗證數據的有效性(長度、格式等),驗證結果存儲到BindingResult或Error中。
Handler(Controller)執行完成後,向 DispatcherServlet 返回一個ModelAndView 對象;
根據返回的ModelAndView,選擇一個適合的 ViewResolver(必須是已經註冊到 Spring 容器中的ViewResolver)返回給DispatcherServlet。
ViewResolver 結合Model和View,來渲染視圖。
視圖負責將渲染結果返回給客戶端。
7.3. 介紹一下 WebApplicationContext
WebApplicationContext 是 ApplicationContext 的擴展。它具備 Web 應用程序所需的一些額外功能。它與普通的 ApplicationContext 在解析主題和決定與哪一個 servlet 關聯的能力方面有所不一樣。
原文:http://developer.51cto.com/art/201808/580655.htm