javascript
25个经典的Spring面试问答
為什么80%的碼農都做不了架構師?>>> ??
本人收集了一些在大家在面試時被經常問及的關于Spring的主要問題,這些問題有可能在你下次面試時就會被問到。對于本文中未提及的Spring其他模塊,我會單獨分享面試的問題和答案。 歡迎大家向我推薦你在面試過程中遇到關于Spring的問題。我會把大家推薦的問題添加到下面的Spring常用面試題清單中供大家參考。問題清單:
1、什么是Spring框架?Spring框架有哪些主要模塊?
Spring框架是一個為Java應用程序的開發提供了綜合、廣泛的基礎性支持的Java平臺。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注于應用程序的開發。Spring框架本身亦是按照 設計模式精心打造,這使得我們可以在開發環境中安心的集成Spring框架,不必擔心Spring是如何在后臺進行工作的。 Spring框架至今已集成了20多個模塊。這些模塊主要被分如下圖所示的核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。 更多信息: 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)?什么是依賴注入?
控制反轉是應用于軟件工程領域中的,在運行時被裝配器對象來綁定耦合對象的一種編程技巧,對象之間耦合關系在編譯時通常是未知的。在傳統的編程方式中,業務邏輯的流程是由應用程序中的早已被設定好關聯關系的對象來決定的。在使用控制反轉的情況下,業務邏輯的流程是由對象關系圖來決定的,該對象關系圖由裝配器負責實例化,這種實現方式還可以將對象之間的關聯關系的定義抽象化。而綁定的過程是通過“依賴注入”實現的。
控制反轉是一種以給予應用程序中目標組件更多控制為目的設計范式,并在我們的實際工作中起到了有效的作用。
依賴注入是在編譯階段尚未知所需的功能是來自哪個的類的情況下,將其他對象所依賴的功能對象實例化的模式。這就需要一種機制用來激活相應的組件以提供特定的功能,所以依賴注入是控制反轉的基礎。否則如果在組件不受框架控制的情況下,框架又怎么知道要創建哪個組件?
在Java中依然注入有以下三種實現方式:
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在此基礎上還提供了其他的功能。
以下是三種較常見的?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配置到應用開發中有以下三種方式:
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 {@Beanpublic 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 AnnotationConfigWebApplicationContextinstead 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-delimitedfully-qualified @Configuration classes. Fully-qualified packages may also bespecified 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 AnnotationConfigWebApplicationContextinstead 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-delimitedand 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中向屬性、方法和構造方法中自動裝配變量。
下面是幾種比較重要的注解類型:
10、請解釋Spring Bean的生命周期?
Spring Bean的生命周期簡單易懂。在一個bean實例被初始化時,需要執行一系列的初始化操作以達到可用的狀態。同樣的,當一個bean不在被調用時需要進行相關的析構操作,并從bean容器中移除。 Spring bean factory 負責管理在spring容器中被創建的bean的生命周期。Bean的生命周期由兩組回調(call back)方法組成。- InitializingBean和DisposableBean回調接口
- 針對特殊行為的其他Aware接口
- Bean配置文件中的Custom init()方法和destroy()方法
- @PostConstruct和@PreDestroy注解方式
11、Spring Bean的作用域之間有什么區別?
Spring容器中的bean可以分為5個范圍。所有范圍的名稱都是自說明的,但是為了避免混淆,還是讓我們來解釋一下:全局作用域與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">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.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的引用。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種自動裝配,讓我們逐一分析。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;}@Requiredpublic 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;@Autowiredpublic 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 {@Autowiredprivate 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、構造方法注入和設值注入有什么區別?
請注意以下明顯的區別:23、Spring框架中有哪些不同類型的事件?
Spring的ApplicationContext?提供了支持事件和代碼中監聽器的功能。 我們可以創建bean用來監聽在ApplicationContext?中發布的事件。ApplicationEvent類和在ApplicationContext接口中處理的事件,如果一個bean實現了ApplicationListener接口,當一個ApplicationEvent?被發布以后,bean會自動被通知。 public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent > {@Overridepublic void onApplicationEvent(ApplicationEvent applicationEvent){//process event} } Spring 提供了以下5中標準的事件: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用來創建對象的實例。
轉載于:https://my.oschina.net/ecp/blog/635426
總結
以上是生活随笔為你收集整理的25个经典的Spring面试问答的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java——容器(Comparable)
- 下一篇: HBase 6、用Phoenix Jav