Spring面試問答

 

本人收集了一些在你們在面試時被常常問及的關於Spring的主要問題,這些問題有可能在你下次面試時就會被問到。對於本文中未說起的Spring其餘模塊,我會單獨分享面試的問題和答案。html

歡迎你們向我推薦你在面試過程當中遇到關於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框架中用了哪些設計模式?

一、什麼是Spring框架?Spring框架有哪些主要模塊?

Spring框架是一個爲Java應用程序的開發提供了綜合、普遍的基礎性支持的Java平臺。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員能夠專一於應用程序的開發。Spring框架自己亦是按照設計模式精心打造,這使得咱們能夠在開發環境中安心的集成Spring框架,沒必要擔憂Spring是如何在後臺進行工做的。java

Spring框架至今已集成了20多個模塊。這些模塊主要被分以下圖所示的核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。web

更多信息:Spring 框架教程面試

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

下面列舉了一些使用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環境)。

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

控制反轉是應用於軟件工程領域中的,在運行時被裝配器對象來綁定耦合對象的一種編程技巧,對象之間耦合關係在編譯時一般是未知的。在傳統的編程方式中,業務邏輯的流程是由應用程序中的早已被設定好關聯關係的對象來決定的。在使用控制反轉的狀況下,業務邏輯的流程是由對象關係圖來決定的,該對象關係圖由裝配器負責實例化,這種實現方式還能夠將對象之間的關聯關係的定義抽象化。而綁定的過程是經過「依賴注入」實現的。shell

控制反轉是一種以給予應用程序中目標組件更多控制爲目的設計範式,並在咱們的實際工做中起到了有效的做用。編程

依賴注入是在編譯階段還沒有知所需的功能是來自哪一個的類的狀況下,將其餘對象所依賴的功能對象實例化的模式。這就須要一種機制用來激活相應的組件以提供特定的功能,因此依賴注入是控制反轉的基礎。不然若是在組件不受框架控制的狀況下,框架又怎麼知道要建立哪一個組件?json

在Java中依然注入有如下三種實現方式:設計模式

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

四、請解釋下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 容器的核心接口。

五、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 實現方式:

一、ClassPathXmlApplicationContext:從classpath的XML配置文件中讀取上下文,並生成上下文定義。應用程序上下文從程序環境變量中取得。

1
ApplicationContext context = new ClassPathXmlApplicationContext(「bean.xml」);

二、FileSystemXmlApplicationContext :由文件系統中的XML配置文件讀取上下文。

1
ApplicationContext context = new FileSystemXmlApplicationContext(「bean.xml」);

三、XmlWebApplicationContext:由Web應用的XML文件讀取上下文。

六、Spring有幾種配置方式?

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

  1. 基於XML的配置
  2. 基於註解的配置
  3. 基於Java的配置

七、如何用基於XML配置的方式配置Spring?

在Spring框架中,依賴和服務須要在專門的配置文件來實現,我經常使用的XML格式的配置文件。這些配置文件的格式一般用<beans>開頭,而後一系列的bean定義和專門的應用配置選項組成。

SpringXML配置的主要目的時候是使全部的Spring組件均可以用xml文件的形式來進行配置。這意味着不會出現其餘的Spring配置類型(好比聲明的方式或基於Java Class的配置方式)

Spring的XML配置方式是使用被Spring命名空間的所支持的一系列的XML標籤來實現的。Spring有如下主要的命名空間:context、beans、jdbc、tx、aop、mvc和aso。

1
2
3
4
5
6
7
8
9
< 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這件最簡單的配置便能知足應用程序配置運行時組件的需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< 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 >

八、如何用基於Java配置的方式配置Spring?

Spring對Java配置的支持是由@Configuration註解和@Bean註解來實現的。由@Bean註解的方法將會實例化、配置和初始化一個新對象,這個對象將由Spring的IoC容器來管理。@Bean聲明所起到的做用與<bean/> 元素相似。被@Configuration所註解的類則表示這個類的主要目的是做爲bean定義的資源。被@Configuration聲明的類能夠經過在同一個類的內部調用@bean方法來設置嵌入bean的依賴關係。

最簡單的@Configuration 聲明類請參考下面的代碼:

1
2
3
4
5
6
7
8
@Configuration
public class AppConfig
{
     @Bean
     public MyService myService() {
         return new MyServiceImpl();
     }
}

對於上面的@Beans配置文件相同的XML配置文件以下:

1
2
3
< beans >
     < bean id = "myService" class = "com.howtodoinjava.services.MyServiceImpl" />
</ beans >

上述配置方式的實例化方式以下:利用AnnotationConfigApplicationContext 類進行實例化

1
2
3
4
5
public static void main(String[] args) {
     ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig. class );
     MyService myService = ctx.getBean(MyService. class );
     myService.doStuff();
}

要使用組件組建掃描,僅需用@Configuration進行註解便可:

1
2
3
4
5
@Configuration
@ComponentScan (basePackages = "com.howtodoinjava" )
public class AppConfig  {
     ...
}

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

若是你要在你的web應用開發中選用上述的配置的方式的話,須要用AnnotationConfigWebApplicationContext 類來讀取配置文件,能夠用來配置Spring的Servlet監聽器ContrextLoaderListener或者Spring MVC的DispatcherServlet。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
< 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?

Spring在2.5版本之後開始支持用註解的方式來配置依賴注入。能夠用註解的方式來替代XML方式的bean描述,能夠將bean描述轉移到組件類的內部,只須要在相關類上、方法上或者字段聲明上使用註解便可。註解注入將會被容器在XML注入以前被處理,因此後者會覆蓋掉前者對於同一個屬性的處理結果。

註解裝配在Spring中是默認關閉的。因此須要在Spring文件中配置一下才能使用基於註解的裝配模式。若是你想要在你的應用程序中使用關於註解的方法的話,請參考以下的配置。

1
2
3
4
5
6
< 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。

十、請解釋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生命週期的代碼樣例以下:

1
2
3
4
< beans >
     < bean id = "demoBean" class = "com.howtodoinjava.task.DemoBean"
             init-method = "customInit" destroy-method = "customDestroy" ></ bean >
</ beans >

更多內容請參考:Spring生命週期Spring Bean Life Cycle

十一、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

十二、什麼是Spring inner beans?

在Spring框架中,不管什麼時候bean被使用時,當僅被調用了一個屬性。一個明智的作法是將這個bean聲明爲內部bean。內部bean能夠用setter注入「屬性」和構造方法注入「構造參數」的方式來實現。

好比,在咱們的應用程序中,一個Customer類引用了一個Person類,咱們的要作的是建立一個Person的實例,而後在Customer內部使用。

1
2
3
4
5
6
public class Customer
{
     private Person person;
 
     //Setters and Getters
}
1
2
3
4
5
6
7
8
public class Person
{
     private String name;
     private String address;
     private int age;
 
     //Setters and Getters
}

內部bean的聲明方式以下:

1
2
3
4
5
6
7
8
9
10
< 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 >

1三、Spring框架中的單例Beans是線程安全的麼?

Spring框架並無對單例bean進行任何多線程的封裝處理。關於單例bean的線程安全和併發問題須要開發者自行去搞定。但實際上,大部分的Spring bean並無可變的狀態(好比Serview類和DAO類),因此在某種程度上說Spring的單例bean是線程安全的。若是你的bean有多種狀態的話(好比 View Model 對象),就須要自行保證線程安全。

最淺顯的解決辦法就是將多態bean的做用域由「singleton」變動爲「prototype」。

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

Spring提供瞭如下四種集合類的配置元素:

  • <list> :   該標籤用來裝配可重複的list值。
  • <set> :    該標籤用來裝配沒有重複的set值。
  • <map>:   該標籤可用來注入鍵和值能夠爲任何類型的鍵值對。
  • <props> : 該標籤支持注入鍵和值都是字符串類型的鍵值對。

下面看一下具體的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
< 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 >

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

第一種方法是使用以下面代碼所示的<props> 標籤:

1
2
3
4
5
6
7
8
9
10
11
< bean id = "adminUser" class = "com.howtodoinjava.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的引用。

1六、請解釋Spring Bean的自動裝配?

在Spring框架中,在配置文件中設定bean的依賴關係是一個很好的機制,Spring容器還能夠自動裝配合做關係bean之間的關聯關係。這意味着Spring能夠經過向Bean Factory中注入的方式自動搞定bean之間的依賴關係。自動裝配能夠設置在每一個bean上,也能夠設定在特定的bean上。

下面的XML配置文件代表瞭如何根據名稱將一個bean設置爲自動裝配:

1
< bean id = "employeeDAO" class = "com.howtodoinjava.EmployeeDAOImpl" autowire = "byName" />

除了bean配置文件中提供的自動裝配模式,還可使用@Autowired註解來自動裝配指定的bean。在使用@Autowired註解以前須要在按照以下的配置方式在Spring配置文件進行配置纔可使用。

1
< context:annotation-config />

也能夠經過在配置文件中配置AutowiredAnnotationBeanPostProcessor 達到相同的效果。

1
< bean class = "org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

配置好之後就可使用@Autowired來標註了。

1
2
3
4
@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
     this .manager = manager;
}

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

在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的自動裝配方式。

1八、如何開啓基於註解的自動裝配?

要使用 @Autowired,須要註冊 AutowiredAnnotationBeanPostProcessor,能夠有如下兩種方式來實現:

一、引入配置文件中的<bean>下引入 <context:annotation-config>

1
2
3
< beans >
     < context:annotation-config />
</ beans >

二、在bean配置文件中直接引入AutowiredAnnotationBeanPostProcessor

1
2
3
< beans >
     < bean class = "org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
</ beans >

1九、請舉例解釋@Required註解?

在產品級別的應用中,IoC容器可能聲明瞭數十萬了bean,bean與bean之間有着複雜的依賴關係。設值註解方法的短板之一就是驗證全部的屬性是否被註解是一項十分困難的操做。能夠經過在<bean>中設置「dependency-check」來解決這個問題。

在應用程序的生命週期中,你可能不大願意花時間在驗證全部bean的屬性是否按照上下文文件正確配置。或者你寧肯驗證某個bean的特定屬性是否被正確的設置。即便是用「dependency-check」屬性也不能很好的解決這個問題,在這種狀況下,你須要使用@Required 註解。

須要用以下的方式使用來標明bean的設值方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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容器中對其進行註冊:

1
< 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> 元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
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();
    }
}

下面是沒有構造參數的配置方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
< 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 >

2一、請舉例說明@Qualifier註解?

@Qualifier註解意味着能夠在被標註bean的字段上能夠自動裝配。Qualifier註解能夠用來取消Spring不能取消的bean應用。

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

1
2
3
4
5
public class Customer
{
     @Autowired
     private Person person;
}

下面咱們要在配置文件中來配置Person類。

1
2
3
4
5
6
7
8
9
< 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麼?不會的,可是運行上面的示例時,會拋出下面的異常:

1
2
3
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:

1
2
3
4
5
6
public class Customer
{
     @Autowired
     @Qualifier ( "personA" )
     private Person person;
}

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

請注意如下明顯的區別:

  1. 在設值注入方法支持大部分的依賴注入,若是咱們僅須要注入int、string和long型的變量,咱們不要用設值的方法注入。對於基本類型,若是咱們沒有注入的話,能夠爲基本類型設置默認值。在構造方法注入不支持大部分的依賴注入,由於在調用構造方法中必須傳入正確的構造參數,不然的話爲報錯。
  2. 設值注入不會重寫構造方法的值。若是咱們對同一個變量同時使用了構造方法注入又使用了設置方法注入的話,那麼構造方法將不能覆蓋由設值方法注入的值。很明顯,由於構造方法盡在對象被建立時調用。
  3. 在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時對象的依賴關係有多是不完整的。而在另外一種狀況下,構造器注入則不容許生成依賴關係不完整的對象。
  4. 在設值注入時若是對象A和對象B互相依賴,在建立對象A時Spring會拋出sObjectCurrentlyInCreationException異常,由於在B對象被建立以前A對象是不能被建立的,反之亦然。因此Spring用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在對象被建立以前被調用的。

2三、Spring框架中有哪些不一樣類型的事件?

Spring的ApplicationContext 提供了支持事件和代碼中監聽器的功能。

咱們能夠建立bean用來監聽在ApplicationContext 中發佈的事件。ApplicationEvent類和在ApplicationContext接口中處理的事件,若是一個bean實現了ApplicationListener接口,當一個ApplicationEvent 被髮布之後,bean會自動被通知。

1
2
3
4
5
6
7
8
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 類來開發自定義的事件。

1
2
3
4
5
6
7
8
public class CustomApplicationEvent extends ApplicationEvent
{
     public CustomApplicationEvent ( Object source, final String msg )
     {
         super (source);
         System.out.println( "Created a Custom event" );
     }
}

爲了監聽這個事件,還須要建立一個監聽器:

1
2
3
4
5
6
7
public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >
{
     @Override
     public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
         //handle event
     }
}

以後經過applicationContext接口的publishEvent()方法來發布自定義事件。

1
2
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message" );
applicationContext.publishEvent(customEvent);

2四、FileSystemResource和ClassPathResource有何區別?

FileSystemResource 中須要給出spring-config.xml文件在你項目中的相對路徑或者絕對路徑。在ClassPathResource中spring會在ClassPath中自動搜尋配置文件,因此要把ClassPathResource 文件放在ClassPath下。

若是將spring-config.xml保存在了src文件夾下的話,只需給出配置文件的名稱便可,由於src文件夾是默認。

簡而言之,ClassPathResource在環境變量中讀取配置文件,FileSystemResource在配置文件中讀取配置文件。

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

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

  • 代理模式—在AOP和remoting中被用的比較多。
  • 單例模式—在spring配置文件中定義的bean默認爲單例模式。
  • 模板方法—用來解決代碼重複的問題。好比. RestTemplateJmsTemplateJpaTemplate。
  • 前端控制器—Spring提供了DispatcherServlet來對請求進行分發。
  • 視圖幫助(View Helper )—Spring提供了一系列的JSP標籤,高效宏來輔助將分散的代碼整合在視圖裏。
  • 依賴注入—貫穿於BeanFactory / ApplicationContext接口的核心理念。
  • 工廠模式—BeanFactory用來建立對象的實例。
相關文章
相關標籤/搜索