我收集了一些spring面試的問題,這些問題可能會在下一次技術面試中遇到。對於其餘spring模塊,我將單獨分享面試問題和答案。前端
若是你能將在之前面試中碰到的,且你認爲這些應該是一個有spring經驗的人可能被問到的問題發給我,我將不勝感激!java
我將把它們添加到這個列表中。這將對其餘學習者也會有很大的幫助。web
1. 什麼是Spring框架?它的主要模塊有哪些?面試
2. 使用Spring框架的好處是什麼?spring
3.什麼是控制反轉(IoC)和依賴注入?數據庫
4. 在Spring框架中的IoC是怎麼樣子的 ?編程
5. BeanFactory和ApplicationContext之間的區別?json
6. 將Spring配置到應用程序中的方式有哪些?設計模式
7. 基於xml的Spring配置是什麼樣子的?安全
8. 基於Spring java的配置是什麼樣子的?
9. 基於Spring註解的配置是什麼樣子的?
10. 請解釋一下Spring Bean的生命週期?
11. Spring Bean做用域的有哪些?
12. Spring的內部Bean是什麼?
13. 在Spring框架中,單例bean線程安全嗎?
14. 如何在Spring中注入Java集合?請給個例子好嗎?
15. 如何將一個java.util.屬性注入到Spring Bean?
16. 解釋一下Spring Bean的自動注入式什麼樣的?
17. 請解釋一下不一樣的bean自動注入模式?
18. 怎麼打開基於註釋的自動注入的?
19. 可否用例子解釋一下@ required註解嗎?
20.可否用例子解釋一下@ autowired註解嗎?
21. 可否用例子講解一下@qualifier註解嗎?
22. 構造方法注入和setter注入之間的區別嗎?
23. spring框架的事件類型有哪些?
24. FileSystemResource和ClassPathResource之間的區別嗎?
25. 列舉一些Spring框架中使用的設計模式?
Spring框架是一個Java平臺,提供全面的基礎設施支持開發Java應用程序。Spring處理基礎設施部分,這樣你就能夠專一於應用程序部分。Spring框架內,把一級對象經過設計模式封裝起來,您能夠放心的集成到您本身的應用程序而不用關注他們如何在後臺工做。
目前,Spring框架由功能組織成大約20個模塊。這些模塊分爲核心容器、數據訪問/集成、Web,AOP(面向切面的編程)、instrument(支持和類加載器的實現來在特定的應用服務器上使用)、消息、和測試,以下列圖所示。
下面是一些使用Spring框架的好處的列表:
依賴注入和控制反轉是對同一件事情的不一樣描述,從某個方面講,就是它們描述的角度不一樣。
依賴注入是從應用程序的角度在描述,能夠把依賴注入描述完整點:應用程序依賴容器建立並注入它所須要的外部資源;
而控制反轉是從容器的角度在描述,描述完整點:容器控制應用程序,由容器反向的嚮應用程序注入應用程序所須要的外部資源。
在Java中,依賴注入可能發生三種方法:
org.springframework.beans
和org.springframework.context
包是Spring框架IoC容器的基礎。
BeanFactory
接口提供了一個高級的配置機制來管理任意屬性的對象。
ApplicationContext
接口基於BeanFactory構建的
(是一個子接口)並添加其餘功能,如Spring的AOP功能,信息資源處理(用於國際化)、事件傳播和應用程序層的特定上下文如在web應用程序中使用WebApplicationContext
。
org.springframework.beans.factory.BeanFactory是
Spring IoC容器真是展示,負責管理上述bean。BeanFactory接口是Spring IoC容器接口的核心。
一個BeanFactory
就像包含bean集合的工廠類。BeanFactory在內部
持有多個Bean的定義,當客戶端請求bean時,將bean進行實例化。
初始化時BeanFactory
可以保持對象的依賴關係。這減輕了負擔從bean自己和bean客戶機的配置。 BeanFactory在
一個bean的生命週期也能其做用,它能夠調用bean的自定義初始化和銷燬方法。
表面上看,applicationContext和BeanFactory是同樣。一樣加載bean定義,將bean鏈接在一塊兒,分發bean。但applicationContext還提供:
三個經常使用的ApplicationContext實現是:
ApplicationContext context = new ClassPathXmlApplicationContext(「bean.xml」);
FileSystemXmlApplicationContext
:它從文件系統的一個XML文件加載上下文定義的。從文件系統加載應用程序上下文經過以下代碼實現。
ApplicationContext context = new FileSystemXmlApplicationContext(「bean.xml」);
XmlWebApplicationContext
:它從一個web應用程序中包含的XML文件加載context。配置spring到您的應用程序有三種方式:
在Spring框架中,bean所需的依賴和服務在定義在配置文件中,配置文件一般是XML格式。一般這些配置文件都以<beans>
標籤開始,含有大量的bean定義和特定於應用程序的配置選項。Spring XML配置的主要目標是讓全部spring組件經過使用XML配置文件。
這意味着不會出現任何其餘類型的Spring配置(如經過Java類註釋或配置)。Spring XML配置中使用Spring命名空間提供的XML標記中使用的配置;Spring命名空間主要有:context、bean、jdbc、tx, aop, mvc等。
<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
類容許inter-bean定義經過簡單地調用實現依賴關係。最簡單的@Configuration
註解類以下:
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } }
上面註解類等價於基於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.howtodoinjava包將被掃描,尋找任何帶註解@Component
的類,這些類將在容器內登記爲Spring bean。
若是你使用以上的方式配置一個web應用程序,那麼須要AnnotationConfigWebApplicationContext
類來使之生效。AnnotationConfigWebApplicationContext的使用能夠經過配置Spring ContextLoaderListener的
servlet listener,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註解以前,咱們須要在咱們的Spring配置文件啓用它。若是你想在Spring應用程序中使用的自動註解,考慮配置文件上加上下面的配置。
<beans> <context:annotation-config/> <!-- bean definitions go here --> </beans>
一旦配置了<context:annotation-config/>
,代表在Spring中您能夠開始使用屬性,方法和構造函數的自動注入。
一些重要的註解:
一個Spring bean的生命週期很容易理解。當一個bean實例化時可能須要執行一些初始化動做進入使bean達到一個可用的狀態。一樣,當再也不須要bean時,將bean從容器中移除,可能須要銷燬。
Spring beanFactory經過Spring容器負責管理bean的生命週期。bean的生命週期包括能夠大致分類爲兩類的回調方法
Spring框架提供瞭如下四種方法控制bean的生命週期事件:
例如, customInit()
和 customDestroy()
方法生命週期方法的例子。
<beans> <bean id="demoBean" class="com.howtodoinjava.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean> </beans>
spring容器中的bean有5中scope,分別是:
在Spring框架中,當一個bean只用於一個特定屬性,建議將它聲明爲一個內在的bean。內部bean同時支持setter注入屬性和構造函數注入「constructor-arg」。
例如,假設一個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="adminis"></property> <property name="address" value="India"></property> <property name="age" value="34"></property> </bean> </property> </bean>
Spring框架不對單例的bean作任何多線程的處理。單例的bean的併發問題和線程安全是開發人員的責任。
而實際上,大多數spring bean沒有可變狀態(例如服務和DAO的類),這樣的話自己是線程安全的。但若是您的bean有可變狀態(例如視圖模型對象),這就須要你來確保線程安全。
這個問題最簡單和明顯的解決方案是改變bean Scope,可變的bean從「單例」到「原型」。
Spring提供了四種類型的配置元素集合,以下:
<list>:幫助注入一組值,容許重複。
<set>:幫助注入一組值,不容許重複。
< map>:幫助注入一個K-V的集合,名稱和值能夠是任何類型的。
<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>
第一個方法是使用<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:「名稱空間建立bean的屬性文件,並使用bean的setter方法注入。
<util:properties id="emails" location="classpath:com/foo/emails.properties" />
在spring框架中,在配置文件中設置bean的依賴是一個很好的辦法,但spring容器也可以自動注入不一樣bean之間的關係。這意味着,經過檢查BeanFactory的內容它能夠爲您的bean自動注入其餘bean。
能夠爲每一個bean指定是否自動注入,所以能夠支持一些Bean支持自動注入,而一些bean不會自動注入。
下面從XML配置文件摘錄了自動根據名稱注入的bean。
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了提供的自動裝配模式bean配置文件,也能夠在bean類中指定自動裝配使用 @Autowired
註釋。
注意:在bean類使用@Autowired註解
,您必須在spring應用程序中先啓用下面的註解。
<context:annotation-config />
也能夠經過在配置文件使用AutowiredAnnotationBeanPostProcessor
bean來完成。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
如今,當註釋配置已經啓用,您能夠自由使用@Autowired來
自動注入bean依賴關係,以你喜歡的方式。
@Autowired public EmployeeDAOImpl ( EmployeeManager manager ) { this.manager = manager; }
在Spring有五個自動注入模式。讓咱們逐個討論。
要啓用@Autowired
,你必須註冊AutowiredAnnotationBeanPostProcessor
,你能夠用兩種方式。
1. 在bean配置文件使用<context:annotation-config >
。
<beans> <context:annotation-config /> </beans>
2. 直接將AutowiredAnnotationBeanPostProcessor放到
bean配置文件。
<beans> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> </beans>
在大規模的應用程序中,IoC容器中可能會有成百上千的bean聲明,以及它們之間的依賴關係一般是很是複雜的。
setter注入的缺點之一是,很難給你檢查出所需的全部屬性是否已經注入。
爲了克服這個問題,您能夠設置bean的「dependency-check」屬性,能夠設置四個屬性的其中之一即 none, simple, objects or all (沒有一個是默認選項)。
在現實生活中應用程序中,您將不會感興趣檢查全部上下文中的bean屬性配置文件。而你想要檢查一些特定的bean是否已設置特定的屬性。在這種狀況下,Spring的依賴項檢查功能將再也不適用,。
爲了解決這個問題,您可使用@Required
註解。在bean屬性使用@Required
註解的setter方法類文件以下:
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 bean後置處理程序,檢查@Required註解的
全部的bean屬性是否已設置。使用這個bean屬性檢查後置處理程序,您必須註冊在Spring IoC容器中。
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
若是@Required註解的任何屬性
沒有設置,這個bean的處理器會拋出一個BeanInitializationException
異常。
@Autowired
註解提供了更細粒度的控制,以及應該如何完成自動注入。@Autowired
註解和@Required註解
同樣,可用於bean的自動注入,它能夠做用於構造方法,屬性或具備任意名稱和/或多個參數的方法。
例如,您可使用@Autowired
註解的setter方法來代替在XML配置文件中的<property>
元素。當Spring找到一個@Autowired
註解的方法,它嘗試使用byType自動注入的方法。
您能夠將@Autowired應用到
構造方法。一個構造方法使用@Autowired註解
代表,即便在XML文件沒有配置bean的<constructor-arg>
元素,當建立bean時,構造方法也會自動注入。
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>
@Qualifier限定哪一個bean應該被自動注入
。當Spring沒法判斷出哪一個bean應該被注入時,@Qualifier註解有助於消除歧義bean的自動注入。
參見下面的例子,
public class Customer
{
@Autowired
private Person person;
}
咱們有兩個bean定義爲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 知道哪一個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應該被autowired的。
public class Customer { @Autowired @Qualifier("personA") private Person person; }
有如下幾點明顯的差別:
ObjectCurrentlyInCreationException
。因此Spring能夠經過setter注入,從而解決循環依賴的問題。Spring的ApplicationContext具備代碼層上
支持事件和監聽器的功能。咱們能夠建立bean監聽經過ApplicationContext發佈的事件。ApplicationContext裏的事件處理經過提供ApplicationEven
t類和ApplicationListener
接口來完成。因此若是一個bean實現了ApplicationListener接口
,當一個ApplicationEvent
發佈到ApplicationContext時,該bean將接到
通知。
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent > { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { //process event } }
Spring提供瞭如下5標準事件:
ConfigurableApplicationContext
接口的refresh()方法來觸發。除了上面的事件,您能夠經過擴展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 } }
發佈這個事件:
CustomApplicationEvent customEvent = new CustomApplicationEvent( applicationContext, "Test message" ); applicationContext.publishEvent ( customEvent );
在FileSystemResource中
你須要給出spring-config.xml
(Spring配置)文件相對於您的項目的相對路徑或文件的絕對位置。
在ClassPathResource中Sping
查找文件使用ClassPath,所以
spring-config.xml
應該包含在類路徑下。
一句話,ClassPathResource在類路徑下搜索和FileSystemResource在文件系統下搜索。
有不少不一樣的設計模式,但有一些明顯的:
JmsTemplate
, JpaTemplate
.DispatcherServlet
,確保傳入請求被分派到你的控制器。BeanFactory
/ ApplicationContext的核心
概念。原文:https://howtodoinjava.com/interview-questions/top-spring-interview-questions-with-answers/