Spring在面試中真的是經常被問到,所以今天也給大家總結了一下Spring知識點!
我變禿了,也變強了
PDF過大放不下,完整PDF戳這裡免費領取,暗號:CSDN
Spring 框架是一個為 Java 應用程式的開發提供了綜合、廣泛的基礎性支援的 Java 平臺。幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注於應用程式的開發。
Spring 框架本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的整合 Spring 框架,不必擔心 Spring 是如何在後臺進行工作的。
Spring 框架至今已整合了 20 多個模組。這些模組主要被分如下圖所示的核心容器、資料存取/整合,、Web、AOP(面向切面程式設計)、工具、訊息和測試模組。
下面列舉了一些使用 Spring 框架帶來的主要好處:
控制反轉是應用於軟體工程領域中的,在執行時被裝配器物件來繫結耦合物件的一種程式設計技巧,物件之間耦合關係在編譯時通常是未知的。
在傳統的程式設計方式中,業務邏輯的流程是由應用程式中的早已被設定好關聯關係的物件來決定的。在使用控制反轉的情況下,業務邏輯的流程是由物件關係圖來決定的,該物件關係圖由裝配 器負責範例化,這種實現方式還可以將物件之間的關聯關係的定義抽象化。而繫結的過程是通過「依賴注入」實現的。
控制反轉是一種以給予應用程式中目標元件更多控制為目的設計正規化,並在我們的實際工作中起到了有效的作用。
依賴注入是在編譯階段尚未知所需的功能是來自哪個的類的情況下,將其他物件所依賴的功能物件範例化的模式。這就需要一種機制用來啟用相應的元件以提供特定的功能,所以依賴注入是控制反轉的基礎。否則如果在元件不受框架控制的情況下,框架又怎麼知道要建立哪個元件?
在 Java 中依賴注入有以下三種實現方式:
Spring 中的 org.springframework.beans 包和 org.springframework.context 包構成了 Spring 框架 IoC 容器的基礎。
BeanFactory 介面提供了一個先進的設定機制,使得任何型別的物件的設定成為可能。
ApplicationContex 介面對 BeanFactory (是一個子介面)進行了擴充套件,在 BeanFactory的基礎上新增了其他功能,比如與 Spring 的 AOP 更容易整合,也提供了處理 message resource的機制(用於國際化)、事件傳播以及應用層的特別設定,比如針對 Web 應用的WebApplicationContext。
org.springframework.beans.factory.BeanFactory 是 Spring IoC 容器的具體實現,用來包裝和管理前面提到的各種 bean。BeanFactory 介面是 Spring IoC 容器的核心介面。
IOC:把物件的建立、初始化、銷燬交給 spring 來管理,而不是由開發者控制,實現控制反轉。
BeanFactory 可以理解為含有 bean 集合的工廠類。BeanFactory 包含了種 bean 的定義,以便在接收到使用者端請求時將對應的 bean 範例化。
BeanFactory 還能在範例化物件的時生成共同作業類之間的關係。此舉將 bean 自身與 bean 使用者端的設定中解放出來。BeanFactory 還包含 了 bean 生命週期的控制,呼叫使用者端的初始化方法
(initialization methods)和銷燬方法(destruction methods)。
從表面上看,application context 如同 bean factory 一樣具有 bean 定義、bean 關聯關係的設定,根據請求分發 bean 的功能。但 applicationcontext 在此基礎上還提供了其他的功能。
以下是三種較常見的 ApplicationContext 實現方式:
1、ClassPathXmlApplicationContext:從 classpath 的 XML 組態檔中讀取上下文,並生成上下文定義。應用程式上下文從程式環境變數中
ApplicationContext context = newClassPathXmlApplicationContext(「bean.xml」);
2、FileSystemXmlApplicationContext :由檔案系統中的 XML 組態檔讀取上下文。
ApplicationContext context = newFileSystemXmlApplicationContext(「bean.xml」);
3、XmlWebApplicationContext:由 Web 應用的 XML 檔案讀取上下文。
4、AnnotationConfigApplicationContext(基於 Java 設定啟動容器)
將 Spring 設定到應用開發中有以下三種方式(方法詳解在後三題):
在 Spring 框架中,依賴和服務需要在專門的組態檔來實現,我常用的 XML 格式的組態檔。這些組態檔的格式通常用 <beans>開頭,然後一系列的 bean 定義和專門的應用設定選項組成。
SpringXML 設定的主要目的時候是使所有的 Spring 元件都可以用 xml 檔案的形式來進行設定。這意味著不會出現其他的 Spring 設定型別(比如宣告的方式或基於 Java Class 的設定方式)
Spring 的 XML 設定方式是使用被 Spring 名稱空間的所支援的一系列的 XML 標籤來實現的。
Spring 有以下主要的名稱空間:context、beans、jdbc、tx、aop、mvc 和 aso。如:
<beans>
<!-- JSON Support -->
<bean name="viewResolver"class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean name="jsonTemplate"class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
<bean id="restTemplate"class="org.springframework.web.client.RestTemplate"/>
</beans>
下面這個 web.xml 僅僅設定了 DispatcherServlet,這件最簡單的設定便能滿足應用程式設定執行時元件的需求。
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Spring 對 Java 設定的支援是由@Configuration 註解和@Bean 註解來實現的。由@Bean 註解的方法將會範例化、設定和初始化一個 新物件,這個物件將由 Spring 的 IOC 容器來管理。
@Bean 宣告所起到的作用與<bean/> 元素類似。被 @Configuration 所註解的類則表示這個類的主要目的是作為 bean 定義的資源。被@Configuration 宣告的類可以通過在同一個類的 內部呼叫@bean 方法來設定嵌入 bean 的依賴關係。
最簡單的@Configuration 宣告類請參考下面的程式碼:
@Configuration
public class AppConfig{
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
對於上面的@Beans 組態檔相同的 XML 組態檔如下:
<beans>
<bean id="myService" class="com.somnus.services.MyServiceImpl"/>
</beans>
上述設定方式的範例化方式如下:利用 AnnotationConfigApplicationContext 類進行範例化:
public static void main(String[] args) {
ApplicationContext ctx = newAnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
要使用元件組建掃描,僅需用@Configuration 進行註解即可:
@Configuration
@ComponentScan(basePackages = "com.somnus")
public class AppConfig {
...
}
在上面的例子中,com.acme 包首先會被掃到,然後再容器內查詢被@Component 宣告的類,找到後將這些類按照 Sring bean 定義進行註冊。
如果你要在你的 web 應用開發中選用上述的設定的方式的話,需要用AnnotationConfigWebApplicationContext類來讀 取組態檔,可以用來設定 Spring 的Servlet 監聽器ContextLoaderListener或者Spring MVC的DispatcherServlet。
<web-app>
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited fully-qualified @Configuration classes. Fully-qualified packages may also be specified for component-scanning -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.howtodoinjava.AppConfig</param-value>
</context-param>
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma-or space-delimited and fully-qualified @Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.howtodoinjava.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /app/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
Spring 在 2.5 版本以後開始支援用註解的方式來設定依賴注入。可以用註解的方式來替代 XML 方式的 bean 描述,可以將 bean 描述轉移到元件類的 內部,只需要在相關類上、方法上或者欄位宣告上使用註解即可。註解注入將會被容器在 XML 注入之前被處理,所以後者會覆蓋掉前者對於同一個屬性的處理結果。
註解裝配在 Spring 中是預設關閉的。所以需要在 Spring 檔案中設定一下才能使用基於註解的裝配
模式。如果你想要在你的應用程式中使用關於註解的方法的話,請參考如下的設定。
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
在 <context:annotation-config/>標籤設定完成以後,就可以用註解的方式在Spring 中向屬性、方法和構造方法中自動裝配變數。
下面是幾種比較重要的註解型別:
Spring Bean 的生命週期簡單易懂。在一個 bean 範例被初始化時,需要執行一系列的初始化操作以達到可用的狀態。同樣的,當一個 bean 不在被呼叫時需要進行相關的解構操作,並從 bean 容器中移除。
Spring bean factory 負責管理在 spring 容器中被建立的 bean 的生命週期。Bean 的生命週期由兩組回撥(call back)方法組成。
Spring 框架提供了以下四種方式來管理 bean 的生命週期事件:
使用 customInit() 和 customDestroy()方法管理 bean 生命週期的程式碼樣例如下:
<beans>
<bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit" destroy method="customDestroy"></bean>
</beans>
Spring 容器中的 bean 可以分為 5 個範圍。所有範圍的名稱都是自說明的,但是為了避免混淆,還是讓我們來解釋一下:
在 Spring 框架中,無論何時 bean 被使用時,當僅被呼叫了一個屬性。一個明智的做法是將這個bean 宣告為內部 bean。內部 bean 可以用 setter 注入「屬性」和構造方法注入「構造引數」的方式來實現。
比如,在我們的應用程式中,一個 Customer 類參照了一個 Person 類,我們的要做的是建立一個Person 的範例,然後在 Customer 內部使用。
public class Customer{
private Person person;
//Setters and Getters
}
public class Person{
private String name;
private String address;
private int age;
//Setters and Getters
}
內部 bean 的宣告方式如下:
<bean id="CustomerBean" class="com.somnus.common.Customer">
<property name="person">
<!-- This is inner bean -->
<bean class="com.howtodoinjava.common.Person">
<property name="name" value="lokesh" />
<property name="address" value="India" />
<property name="age" value="34" />
</bean>
</property>
</bean>
Spring 框架並沒有對單例 bean 進行任何多執行緒的封裝處理。關於單例 bean 的執行緒安全和並行問題需要開發者自行去搞定。但實際上,大部分的 Spring bean 並沒有可變的狀態(比如 Serview 類和 DAO 類),所以在某種程度上說 Spring 的單例 bean 是執行緒安全的。如果你的 bean 有多種狀態的話(比如 View Model 物件),就需要自行保證執行緒安全。最淺顯的解決辦法就是將多型 bean 的作用域由「singleton」變更為「prototype」。
Spring 提供了以下四種集合類的設定元素:
下面看一下具體的例子:
<beans>
<!-- Definition for javaCollection -->
<bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
<!-- java.util.List -->
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<!-- java.util.Set -->
<property name="customSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</set>
</property>
<!-- java.util.Map -->
<property name="customMap">
<map>
<entry key="1" value="INDIA"/>
<entry key="2" value="Pakistan"/>
<entry key="3" value="USA"/>
<entry key="4" value="UK"/>
</map>
</property>
<!-- java.util.Properties -->
<property name="customProperies">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
</beans>
使用如下面程式碼所示的<props> 標籤:
<bean id="adminUser" class="com.somnus.common.Customer">
<!-- java.util.Properties -->
<property name="emails">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
也可用」util:」名稱空間來從 properties 檔案中建立出一個 propertiesbean,然後利用 setter 方法注入 bean 的參照。
在 Spring 框架中,在組態檔中設定 bean 的依賴關係是一個很好的機制,Spring 容器還可以自動裝配合作關係 bean 之間的關聯關係。這意味著 Spring 可以通過向 Bean Factory 中注入的方式自動搞定 bean 之間的依賴關係。自動裝配可以設定在每個 bean 上,也可以設定在特定的 bean上。
下面的 XML 組態檔表明瞭如何根據名稱將一個 bean 設定為自動裝配:
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了 bean 組態檔中提供的自動裝配模式,還可以使用 @Autowired 註解來自動裝配指定的 bean。在使用@Autowired 註解之前需要在按照如下的設定方式在 Spring 組態檔進行設定才可以使用。
<context:annotation-config />
也可以通過在組態檔中設定 AutowiredAnnotationBeanPostProcessor 達到相同的效果。
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
設定好以後就可以使用 @Autowired 來標註了。
@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
this.manager = manager;
}
在 Spring 框架中共有 5 種自動裝配,讓我們逐一分析。
要使用 @Autowired,需要註冊 AutowiredAnnotationBeanPostProcessor,可以有以下兩種方式來實現:
1、引入組態檔中的<bean>下引入 <context:annotation-config>
<beans>
<context:annotation-config />
</beans>
2、在 bean 組態檔中直接引入 AutowiredAnnotationBeanPostProcessor
<beans>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>
在產品級別的應用中,IOC 容器可能宣告了數十萬了 bean,bean 與 bean 之間有著複雜的依賴關係。設值註解方法的短板之一就是驗證所有的屬性是否被註解是一項十分困難的操作。可以通過在<bean>中設定「dependency-check」來解決這個問題。
在應用程式的生命週期中,你可能不大願意花時間在驗證所有 bean 的屬性是否按照上下文件案正確設定。或者你寧可驗證某個 bean 的特定屬性是否被正確的設定。即使是用「dependency-check」屬性也不能很好的解決這個問題,在這種情況下,你需要使用 @Required 註解。需要用如下的方式使用來標明 bean 的設值方法。
public class EmployeeFactoryBean extends AbstractFactoryBean<Object>{
private String designation;
public String getDesignation() {
return designation;
}
@Required
public void setDesignation(String designation) {
this.designation = designation;
}
//more code here
}
RequiredAnnotationBeanPostProcessor 是 Spring 中的後置處理用來驗證被@Required 註解的 bean 屬性是否被正確的設定了。在使用RequiredAnnotationBeanPostProcesso 來驗證 bean 屬性之前,首先要在 IoC 容器中對其進行註冊:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
但是如果沒有屬性被用@Required 註解過的話,後置處理器會丟擲一個BeanInitializationException 異常。
@Autowired 註解對自動裝配何時何處被實現提供了更多細粒度的控制。 @Autowired 註解可以像@Required 註解、構造器一樣被用於在 bean 的設值方法上自動裝配 bean的屬性,一個引數或者帶有任意名稱或帶有多個引數的方法。
比如,可以在設值方法上使用 @Autowired 註解來替代組態檔中的 <property>元素。當 Spring 容器在 setter 方法上找到@Autowired 註解時,會嘗試用 byType自動裝配。
當然我們也可以在構造方法上使用 @Autowired 註解。帶有 @Autowired 註解的構造方法意味著在建立一個 bean 時將會被自動裝配,即便在組態檔中使用 <constructor-arg> 元素。
public class TextEditor {
private SpellChecker spellChecker;
@Autowired
public TextEditor(SpellChecker spellChecker){
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
下面是沒有構造引數的設定方式:
<beans>
<context:annotation-config/>
<!-- Definition for textEditor bean without constructor-arg -->
<bean id="textEditor" class="com.howtodoinjava.TextEditor"/>
<!-- Definition for spellChecker bean -->
<bean id="spellChecker" class="com.howtodoinjava.SpellChecker"/>
</beans>
@Qualifier 註解意味著可以在被標註 bean 的欄位上可以自動裝配。 Qualifier 註解可以用來取消 Spring 不能取消的 bean 應用。
下面的範例將會在 Customer 的 person 屬性中自動裝配 person 的值。
public class Customer{
@Autowired
private Person person;
}
下面我們要在組態檔中來設定 Person 類。
<bean id="customer" class="com.somnus.common.Customer" />
<bean id="personA" class="com.somnus.common.Person" >
<property name="name" value="lokesh" />
</bean>
<bean id="personB" class="com.somnus.common.Person" >
<property name="name" value="alex" />
</bean>
Spring 會知道要自動裝配哪個 person bean 麼?不會的,但是執行上面的範例時,會丟擲下面的異常:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.howtodoinjava.common.Person] is defined:
expected single matching bean but found 2: [personA, personB]
要解決上面的問題,需要使用 @Quanlifier 註解來告訴 Spring 容器要裝配哪個 bean:
public class Customer{
@Autowired
@Qualifier("personA")
private Person person;
}
請注意以下明顯的區別:
Spring 的 ApplicationContext 提供了支援事件和程式碼中監聽器的功能。
我們可以建立 bean 用來監聽在 ApplicationContext 中釋出的事件。 ApplicationEvent類和在 ApplicationContext 介面 中處理的事件,如果一個 bean 實現了ApplicationListener 介面,當一個 ApplicationEvent 被髮布以後,bean會自動被通知。
public class AllApplicationEventListener implements ApplicationListener
< ApplicationEvent >{
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent){
//process event
}
}
Spring 提供了以下 5 中標準的事件:
除了上面介紹的事件以外,還可以通過擴充套件 ApplicationEvent 類來開發自定義的事件。
public class CustomApplicationEvent extends ApplicationEvent{
public CustomApplicationEvent ( Object source, final String msg ){
super(source);
System.out.println("Created a Custom event");
}
}
為了監聽這個事件,還需要建立一個監聽器:
public class CustomEventListener implements ApplicationListener <CustomApplicationEvent >{
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
//handle event
}
}
之後通過 applicationContext 介面的 publishEvent()方法來發布自定義事件。
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");
applicationContext.publishEvent(customEvent);
在 FileSystemResource 中需要給出 spring-config.xml 檔案在你專案中的相對路徑或者絕對路徑。在 ClassPathResource 中 spring 會在 ClassPath 中自動搜尋組態檔,所以要把ClassPathResource 檔案放在 ClassPath 下。
如果將 spring-config.xml 儲存在了 src 資料夾下的話,只需給出組態檔的名稱即可,因為src 資料夾是預設。
簡而言之,ClassPathResource 在環境變數中讀取組態檔,FileSystemResource 在組態檔中讀取組態檔。
Spring 框架中使用到了大量的設計模式,下面列舉了比較有代表性的:
平常用的的技術點也不止Spring,也不好全部寫出來了,所以全部都總結成了PDF,都是免費給大家的,幫大家一起成為大佬。
免費資料領取:戳這裡免費領取,暗號:CSDN
愛程式設計,愛分享,聽說點贊+關注的都進大廠了哦!!!