天天看點

面試常被問的25個Spring知識點

面試常被問的25個Spring知識點

同名原創公衆号: 程式大視界

                                                                             150道Java面試基礎題(含答案)

25個經典的Spring面試問答

本人收集了一些在大家在面試時被經常問及的關于Spring的主要問題,這些問題有可能在你下次面試時就會被問到。對于本文中未提及的Spring其他子產品,我會單獨分享面試的問題和答案。

歡迎大家向我推薦你在面試過程中遇到關于Spring的問題。我會把大家推薦的問題添加到下面的Spring常用面試題清單中供大家參考。

問題清單:

  1. 什麼是Spring架構?Spring架構有哪些主要子產品?
  2. 使用Spring架構有什麼好處?
  3. 什麼是控制反轉(IOC)?什麼是依賴注入?
  4. 請解釋下Spring中的IOC?
  5. BeanFactory和ApplicationContext有什麼差別?
  6. 将Spring配置到你的應用中共有幾種方法?
  7. 什麼基于XML的配置?
  8. 什麼基Java的配置?
  9. 怎樣用注解的方式配置Spring?
  10. 描述Spring Bean的生命周期?
  11. 描述Spring中各種Bean的範圍?
  12. 什麼是Spring的嵌入beans?
  13. Spring架構中的單例bean是否是線程安全的?
  14. 請舉例說明如何用Spring注入一個Java的集合類?
  15. 請舉例說明如何在Spring的Bean中注入一個java.util.Properties?
  16. 請解釋Spring的Bean的自動生成原理?
  17. 請辨析自動生成Bean之間子產品的差別?
  18. 如何開啟基于基于注解的自動寫入?
  19. 請舉例說明@Required注解?
  20. 請舉例說明@Autowired注解?
  21. 請舉例說明@Qualifier注解?
  22. 請說明構造器注入和setter方法注入之間的差別?
  23. Spring架構中不同類型event有什麼差別?
  24. FileSystemResource和ClassPathResource有何差別?
  25. 請列舉Spring架構中用了哪些設計模式?

1、什麼是Spring架構?Spring架構有哪些主要子產品?

Spring架構是一個為Java應用程式的開發提供了綜合、廣泛的基礎性支援的Java平台。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注于應用程式的開發。Spring架構本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的內建Spring架構,不必擔心Spring是如何在背景進行工作的。

Spring架構至今已內建了20多個子產品。這些子產品主要被分如下圖所示的核心容器、資料通路/內建,、Web、AOP(面向切面程式設計)、工具、消息和測試子產品。

面試常被問的25個Spring知識點

更多資訊:Spring 架構教程。

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)?什麼是依賴注入(DI)?

控制反轉是應用于軟體工程領域中的,在運作時被裝配器對象來綁定耦合對象的一種程式設計技巧,對象之間耦合關系在編譯時通常是未知的。在傳統的程式設計方式中,業務邏輯的流程是由應用程式中的早已被設定好關聯關系的對象來決定的。在使用控制反轉的情況下,業務邏輯的流程是由對象關系圖來決定的,該對象關系圖由裝配器負責執行個體化,這種實作方式還可以将對象之間的關聯關系的定義抽象化。而綁定的過程是通過“依賴注入”實作的。

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

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

在Java中依然注入有以下三種實作方式:

  1. 構造器注入
  2. Setter方法注入
  3. 接口注入

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 容器的核心接口。

5、BeanFactory和ApplicationContext有什麼差別?

BeanFactory 可以了解為含有bean集合的工廠類。BeanFactory 包含了種bean的定義,以便在接收到用戶端請求時将對應的bean執行個體化。

BeanFactory還能在執行個體化對象的時生成協作類之間的關系。此舉将bean自身與bean用戶端的配置中解放出來。BeanFactory還包含了bean生命周期的控制,調用用戶端的初始化方法(initialization methods)和銷毀方法(destruction methods)。

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

  1. 提供了支援國際化的文本消息
  2. 統一的資源檔案讀取方式
  3. 已在監聽器中注冊的bean的事件

以下是三種較常見的 ApplicationContext 實作方式:

1、ClassPathXmlApplicationContext:從classpath的XML配置檔案中讀取上下文,并生成上下文定義。應用程式上下文從程式環境變量中取得。

ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);

2、FileSystemXmlApplicationContext :由檔案系統中的XML配置檔案讀取上下文。

ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);

3、XmlWebApplicationContext:由Web應用的XML檔案讀取上下文。

6、Spring有幾種配置方式?

将Spring配置到應用開發中有以下三種方式:

  1. 基于XML的配置
  2. 基于注解的配置
  3. 基于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.howtodoinjava.services.MyServiceImpl"/>

</beans>

上述配置方式的執行個體化方式如下:利用AnnotationConfigApplicationContext 類進行執行個體化

public static void main(String[] args) {

    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

    MyService myService = ctx.getBean(MyService.class);

    myService.doStuff();

}

要使用元件組建掃描,僅需用@Configuration進行注解即可:

@Configuration

@ComponentScan(basePackages = "com.howtodoinjava")

public class AppConfig  {

    ...

}

在上面的例子中,com.acme包首先會被掃到,然後再容器内查找被@Component 聲明的類,找到後将這些類按照Sring bean定義進行注冊。

如果你要在你的web應用開發中選用上述的配置的方式的話,需要用AnnotationConfigWebApplicationContext 類來讀取配置檔案,可以用來配置Spring的Servlet監聽器ContrextLoaderListener或者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中向屬性、方法和構造方法中自動裝配變量。

下面是幾種比較重要的注解類型:

  1. @Required:該注解應用于設值方法。
  2. @Autowired:該注解應用于有值設值方法、非設值方法、構造方法和變量。
  3. @Qualifier:該注解和@Autowired注解搭配使用,用于消除特定bean自動裝配的歧義。
  4. 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)方法組成。

  1. 初始化之後調用的回調方法。
  2. 銷毀之前調用的回調方法。

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

  • InitializingBean和DisposableBean回調接口
  • 針對特殊行為的其他Aware接口
  • Bean配置檔案中的Custom init()方法和destroy()方法
  • @PostConstruct和@PreDestroy注解方式

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

<beans>

    <bean id="demoBean" class="com.howtodoinjava.task.DemoBean"

            init-method="customInit" destroy-method="customDestroy"></bean>

</beans>

更多内容請參考:Spring生命周期Spring Bean Life Cycle。

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

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

  1. singleton:這種bean範圍是預設的,這種範圍確定不管接受到多少個請求,每個容器中隻有一個bean的執行個體,單例的模式由bean factory自身來維護。
  2. prototype:原形範圍與單例範圍相反,為每一個bean請求提供一個執行個體。
  3. request:在請求bean範圍内會每一個來自用戶端的網絡請求建立一個執行個體,在請求完成以後,bean會失效并被垃圾回收器回收。
  4. Session:與請求範圍類似,確定每個session中有一個bean的執行個體,在session過期後,bean會随之失效。
  5. global-session:global-session和Portlet應用相關。當你的應用部署在Portlet容器中工作時,它包含很多portlet。如果你想要聲明讓所有的portlet共用全局的存儲變量的話,那麼這全局變量需要存儲在global-session中。

全局作用域與Servlet中的session作用域效果相同。

更多内容請參考 : Spring Bean Scopes。

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.howtodoinjava.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">[email protected]</prop>

            <prop key="support">[email protected]</prop>

        </props>

    </property>

   </bean>

</beans>

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

第一種方法是使用如下面代碼所示的<props> 标簽:

<bean id="adminUser" class="com.howtodoinjava.common.Customer">

    <!-- java.util.Properties -->

    <property name="emails">

        <props>

            <prop key="admin">[email protected]</prop>

            <prop key="support">[email protected]</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. byName:該選項可以根據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 annotation?

在産品級别的應用中,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">

   </bean>

   <!-- Definition for spellChecker bean -->

   <bean id="spellChecker" class="com.howtodoinjava.SpellChecker">

   </bean>

</beans>

21、請舉例說明@Qualifier注解?

@Qualifier注解意味着可以在被标注bean的字段上可以自動裝配。Qualifier注解可以用來取消Spring不能取消的bean應用。

下面的示例将會在Customer的person屬性中自動裝配person的值。

public class Customer

{

    @Autowired

    private Person person;

}

下面我們要在配置檔案中來配置Person類。

<bean id="customer" class="com.howtodoinjava.common.Customer" />

<bean id="personA" class="com.howtodoinjava.common.Person" >

    <property name="name" value="lokesh" />

</bean>

<bean id="personB" class="com.howtodoinjava.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。
  • 前端控制器—Srping提供了DispatcherServlet來對請求進行分發。
  • 視圖幫助(View Helper )—Spring提供了一系列的JSP标簽,高效宏來輔助将分散的代碼整合在視圖裡。
  • 依賴注入—貫穿于BeanFactory / ApplicationContext接口的核心理念。
  • 工廠模式—BeanFactory用來建立對象的執行個體。
面試常被問的25個Spring知識點

關注公衆号: nick_coding1024

覺得對你有幫助,關注部落格和公衆号。不定期分享最新前沿技術架構和bat大廠常用技術等,加群不定期分享行業内大牛直播講課以及獲得視訊課件資料等。