面試官問我憑什麼敢來面試?我用Spring把他懟了。

2020-10-25 14:01:12

前言

Spring在面試中真的是經常被問到,所以今天也給大家總結了一下Spring知識點!

我變禿了,也變強了

PDF過大放不下,完整PDF戳這裡免費領取,暗號:CSDN

1 、什麼是 Spring  框架?Spring框架有哪些主要模組?

Spring 框架是一個為 Java 應用程式的開發提供了綜合、廣泛的基礎性支援的 Java 平臺。幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注於應用程式的開發。

Spring 框架本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的整合 Spring 框架,不必擔心 Spring 是如何在後臺進行工作的。

Spring 框架至今已整合了 20 多個模組。這些模組主要被分如下圖所示的核心容器、資料存取/整合,、Web、AOP(面向切面程式設計)、工具、訊息和測試模組。

 

2 、使用 Spring  框架能帶來哪些好處?

下面列舉了一些使用 Spring 框架帶來的主要好處:

  •  Dependency Injection(DI) 方法使得構造器和 JavaBean properties 檔案中的依賴關係一目瞭然。
  • 與 EJB 容器相比較,IoC 容器更加趨向於輕量級。這樣一來 IoC 容器在有限的記憶體和 CPU 資源的情況下進行應用程式的開發和釋出就變得十分有利。
  • Spring 並沒有閉門造車,Spring 利用了已有的技術比如 ORM 框架、logging 框架、J2EE、Quartz 和 JDK Timer,以及其他檢視技術。
  • Spring 框架是按照模組的形式來組織的。由包和類的編號就可以看出其所屬的模組,開發者僅僅需要選用他們需要的模組即可。
  • 要測試一項用 Spring 開發的應用程式十分簡單,因為測試相關的環境程式碼都已經囊括在框架中了。更加簡單的是,利用 JavaBean 形式的 POJO 類,可以很方便的利用依賴注入來寫入測試資料。
  •  Spring 的 Web 框架亦是一個精心設計的 Web MVC 框架,為開發者們在 web 框架的選擇上提供了一個除了主流框架比如 Struts、過度設計的、不流行 web 框架的以外的有力選項。
  •  Spring 提供了一個便捷的事務管理介面,適用於小型的本地事物處理(比如在單 DB 的環境下)和複雜的共同事物處理(比如利用 JTA 的複雜 DB 環境)。

 

3 、什麼是控制反轉(IOC) ?什麼是依賴注入?

控制反轉是應用於軟體工程領域中的,在執行時被裝配器物件來繫結耦合物件的一種程式設計技巧,物件之間耦合關係在編譯時通常是未知的。

在傳統的程式設計方式中,業務邏輯的流程是由應用程式中的早已被設定好關聯關係的物件來決定的。在使用控制反轉的情況下,業務邏輯的流程是由物件關係圖來決定的,該物件關係圖由裝配 器負責範例化,這種實現方式還可以將物件之間的關聯關係的定義抽象化。而繫結的過程是通過「依賴注入」實現的。

控制反轉是一種以給予應用程式中目標元件更多控制為目的設計正規化,並在我們的實際工作中起到了有效的作用。

依賴注入是在編譯階段尚未知所需的功能是來自哪個的類的情況下,將其他物件所依賴的功能物件範例化的模式。這就需要一種機制用來啟用相應的元件以提供特定的功能,所以依賴注入是控制反轉的基礎。否則如果在元件不受框架控制的情況下,框架又怎麼知道要建立哪個元件?

在 Java 中依賴注入有以下三種實現方式:

  • 構造器注入
  • Setter 方法注入
  • 介面注入

 

4 、請解釋下 Spring框架中的 IOC

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 來管理,而不是由開發者控制,實現控制反轉。

 

5 、BeanFactory 和 和 ApplicationContext 

BeanFactory 可以理解為含有 bean 集合的工廠類。BeanFactory 包含了種 bean 的定義,以便在接收到使用者端請求時將對應的 bean 範例化。

BeanFactory 還能在範例化物件的時生成共同作業類之間的關係。此舉將 bean 自身與 bean 使用者端的設定中解放出來。BeanFactory 還包含 了 bean 生命週期的控制,呼叫使用者端的初始化方法
(initialization methods)和銷燬方法(destruction methods)。

從表面上看,application context 如同 bean factory 一樣具有 bean 定義、bean 關聯關係的設定,根據請求分發 bean 的功能。但 applicationcontext 在此基礎上還提供了其他的功能

  • 提供了支援國際化的文字訊息
  • 統一的資原始檔讀取方式
  • 已在監聽器中註冊的 bean 的事件

以下是三種較常見的 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 設定啟動容器)

 

6 、Spring  有幾種設定方式?

將 Spring 設定到應用開發中有以下三種方式(方法詳解在後三題):

  • 基於 XML 的設定
  • 基於註解的設定
  • 基於 Java 的設定

 

7 、如何用基於 XML  設定的方式設定 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>

 

8 、如何用基於 Java  設定的方式設定 Spring?

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>

 

9 、怎樣用註解的方式設定 Spring

Spring 在 2.5 版本以後開始支援用註解的方式來設定依賴注入。可以用註解的方式來替代 XML 方式的 bean 描述,可以將 bean 描述轉移到元件類的 內部,只需要在相關類上、方法上或者欄位宣告上使用註解即可。註解注入將會被容器在 XML 注入之前被處理,所以後者會覆蓋掉前者對於同一個屬性的處理結果。

註解裝配在 Spring 中是預設關閉的。所以需要在 Spring 檔案中設定一下才能使用基於註解的裝配
模式。如果你想要在你的應用程式中使用關於註解的方法的話,請參考如下的設定

<beans>
   <context:annotation-config/>
   <!-- bean definitions go here -->
</beans>

在 <context:annotation-config/>標籤設定完成以後,就可以用註解的方式在Spring 中向屬性、方法和構造方法中自動裝配變數。

下面是幾種比較重要的註解型別:

  • @Required:該註解應用於設值方法。
  • @Autowired:該註解應用於有值設值方法、非設值方法、構造方法和變數。
  • @Qualifier:該註解和@Autowired 註解搭配使用,用於消除特定 bean 自動裝配的歧義。
  • JSR-250 Annotations:Spring 支援基於 JSR-250 註解的以下註解,@Resource、@PostConstruct 和 @PreDestroy。

 

10 、請解釋 Spring Bean  的生命週期?

Spring Bean 的生命週期簡單易懂。在一個 bean 範例被初始化時,需要執行一系列的初始化操作以達到可用的狀態。同樣的,當一個 bean 不在被呼叫時需要進行相關的解構操作,並從 bean 容器中移除。

Spring bean factory 負責管理在 spring 容器中被建立的 bean 的生命週期。Bean 的生命週期由兩組回撥(call back)方法組成。

  • 初始化之後呼叫的回撥方法。
  • 銷燬之前呼叫的回撥方法。

Spring 框架提供了以下四種方式來管理 bean 的生命週期事件:

  • InitializingBean 和 DisposableBean 回撥介面
  • 針對特殊行為的其他 Aware 介面
  • Bean 組態檔中的 Custom init()方法和 destroy()方法
  • @PostConstruct 和@PreDestroy 註解方式

使用 customInit() 和 customDestroy()方法管理 bean 生命週期的程式碼樣例如下:

<beans>
   <bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit" destroy method="customDestroy"></bean>
</beans>

 

11 、Spring Bean  的作用域之間有什麼區別?

Spring 容器中的 bean 可以分為 5 個範圍。所有範圍的名稱都是自說明的,但是為了避免混淆,還是讓我們來解釋一下:

  1. singleton:這種 bean 範圍是預設的,這種範圍確保不管接受到多少個請求,每個容器中只有一個bean 的範例,單例的模式由 bean factory 自身來維護。
  2. 2prototype:原形範圍與單例範圍相反,為每一個 bean 請求提供一個範例。
  3. request:在請求 bean 範圍內會每一個來自使用者端的網路請求建立一個範例,在請求完成以後,bean 會失效並被垃圾回收器回收。
  4. Session:與請求範圍類似,確保每個 session 中有一個 bean 的範例,在 session 過期後,bean會隨之失效。
  5. global- session:global-session 和 Portlet 應用相關。當你的應用部署在 Portlet 容器中工作時,它包含很多 portlet。如果 你想要宣告讓所有的 portlet 共用全域性的儲存變數的話,那麼這全域性變數需要儲存在 global-session 中。全域性作用域與 Servlet 中的 session 作用域效果相同。

 

12 、什麼是 Spring inner beans ?

在 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>

 

13 、Spring  框架中的單例 Beans 

Spring 框架並沒有對單例 bean 進行任何多執行緒的封裝處理。關於單例 bean 的執行緒安全和並行問題需要開發者自行去搞定。但實際上,大部分的 Spring bean 並沒有可變的狀態(比如 Serview 類和 DAO 類),所以在某種程度上說 Spring 的單例 bean 是執行緒安全的。如果你的 bean 有多種狀態的話(比如 View Model 物件),就需要自行保證執行緒安全。最淺顯的解決辦法就是將多型 bean 的作用域由「singleton」變更為「prototype」。

 

14 、請舉例說明如何在 Spring  中注入一個 Java Collection ?

Spring 提供了以下四種集合類的設定元素:

  • <list> : 該標籤用來裝配可重複的 list 值。
  • <set> : 該標籤用來裝配沒有重複的 set 值。
  • <map>: 該標籤可用來注入鍵和值可以為任何型別的鍵值對。
  • <props> : 該標籤支援注入鍵和值都是字串型別的鍵值對。

下面看一下具體的例子:

<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>

 

15 、如何向 Spring Bean  中注入一個 Java.util.Properties

使用如下面程式碼所示的<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 的參照。

 

16 、請解釋 Spring 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;
}

 

17 、請解釋自動裝配模式的區別?

在 Spring 框架中共有 5 種自動裝配,讓我們逐一分析。

  1. no:這是 Spring 框架的預設設定,在該設定下自動裝配是關閉的,開發者需要自行在 bean 定義中用標籤明確的設定依賴關係。
  2. 2byName:該選項可以根據 bean 名稱設定依賴關係。當向一個 bean 中自動裝配一個屬性時,容器將根據 bean 的名稱自動在在組態檔中查詢一個匹配的 bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
  3. byType:該選項可以根據 bean 型別設定依賴關係。當向一個 bean 中自動裝配一個屬性時,容器將根據 bean 的型別自動在在組態檔中查詢一個匹配的 bean。如果找到的話,就裝配這個屬性,如果沒找到的話就報錯。
  4. constructor:造器的自動裝配和 byType 模式類似,但是僅僅適用於與有構造器相同引數的bean,如果在容器中沒有找到與構造器引數型別一致的 bean,那麼將會丟擲異常。
  5. autodetect:該模式自動探測使用構造器自動裝配或者 byType 自動裝配。首先,首先會嘗試找合適的帶引數的構造器,如果找到的話就是用構造器自動裝配,如果在 bean 內部沒有找到相應的構造器或者是無參構造器,容器就會自動選擇 byTpe 的自動裝配方式

 

18 、如何開啟基於註解的自動裝配?

要使用  @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>

 

19 、請舉例解釋@Required  註解?

在產品級別的應用中,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 異常

 

20 、請舉例解釋@Autowired註解?

@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>

 

21 、請舉例說明@Qualifier 註解

@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;
}

 

22 、構造方法注入和設值注入有什麼區別?

請注意以下明顯的區別:

  1.  在設值注入方法支援大部分的依賴注入,如果我們僅需 要注入 int、string 和 long 型的變數,我們不要用設值的方法注入。對於基本型別,如果我們沒有注入的話,可以為基本型別設定預設值。在構造方法 注入不支援大部分的依賴注入,因為在呼叫構造方法中必須傳入正確的構造引數,否則的話為報錯。
  2. 設值注入不會重寫構造方法的值。如果我們對同一個變數同時使用了構造方法注入又使用了設定方法注入的話,那麼構造方法將不能覆蓋由設值方法注入的值。很明顯,因為構造方法盡在物件被建立時呼叫。
  3. 在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時物件的依賴關係有可能是不完整的。而在另一種情況下,構造器注入則不允許生成依賴關係不完整的物件。
  4. 在設值注入時如果物件 A 和物件 B 互相依賴,在建立物件 A 時 Spring 會丟擲SObjectCurrentlyInCreationException 異常,因為在 B 物件被建立之前 A 物件是不能被建立的,反之亦然。所以 Spring 用設值注入的方法解決了迴圈依賴的問題,因物件的設值方法是在物件被建立之前被呼叫的。

 

23 、Spring  框架中有哪些不同型別的事件?

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 中標準的事件:

  1. 上下文更新事件(ContextRefreshedEvent):該事件會在 ApplicationContext 被初始化或者更新時釋出。也可以在呼叫 ConfigurableApplicationContext 介面中的 refresh()方法時被觸發。
  2. 上下文開始事件(ContextStartedEvent):當容器呼叫 ConfigurableApplicationContext 的Start()方法開始/重新開始容器時觸發該事件。
  3. 上下文停止事件(ContextStoppedEvent):當容器呼叫 ConfigurableApplicationContext 的Stop()方法停止容器時觸發該事件。
  4. 上下文關閉事件(ContextClosedEvent):當 ApplicationContext 被關閉時觸發該事件。容器被關閉時,其管理的所有單例 Bean 都被銷燬。
  5. 請求處理事件(RequestHandledEvent):在 Web 應用中,當一個 http 請求(request)結束觸發該事件。

除了上面介紹的事件以外,還可以通過擴充套件 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);

 

24 、FileSystemResource 和 和 ClassPathResource 

在 FileSystemResource 中需要給出 spring-config.xml 檔案在你專案中的相對路徑或者絕對路徑。在 ClassPathResource 中 spring 會在 ClassPath 中自動搜尋組態檔,所以要把ClassPathResource 檔案放在 ClassPath 下。

如果將 spring-config.xml 儲存在了 src 資料夾下的話,只需給出組態檔的名稱即可,因為src 資料夾是預設。

簡而言之,ClassPathResource 在環境變數中讀取組態檔,FileSystemResource 在組態檔中讀取組態檔。

 

25 、Spring  框架中都用到了哪些設計模式?

Spring 框架中使用到了大量的設計模式,下面列舉了比較有代表性的:

  • 代理模式—在 AOP 和 remoting 中被用的比較多。
  • 單例模式—在 spring 組態檔中定義的 bean 預設為單例模式。
  • 模板方法—用來解決程式碼重複的問題。比如. RestTemplate,  JmsTemplate ,  JpaTemplate。
  • 前端控制器—Spring 提供了 DispatcherServlet 來對請求進行分發。
  • 檢視幫助(View Helper )—Spring 提供了一系列的 JSP 標籤,高效宏來輔助將分散的程式碼整合在檢視裡。
  • 依賴注入—貫穿於 BeanFactory /  ApplicationContext 介面的核心理念。
  • 工廠模式—BeanFactory 用來建立物件的範例

 

26.最後

平常用的的技術點也不止Spring,也不好全部寫出來了,所以全部都總結成了PDF,都是免費給大家的,幫大家一起成為大佬

免費資料領取:戳這裡免費領取,暗號:CSDN

愛程式設計,愛分享,聽說點贊+關注的都進大廠了哦!!!