一、什麼是 Spring 框架?Spring 框架有哪些主要模塊?
Spring 框架是一個爲 Java 應用程序的開發提供了綜合、普遍的基礎性支持的 Java 平臺。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員能夠專一於應用程序的開發。Spring 框架自己亦是按照設計模式精心打造,這使得咱們能夠在開發環境中安心的集成 Spring 框架,不必擔憂 Spring 是如何在後臺進行工做的。html
Spring 框架至今已集成了 20 多個模塊。這些模塊主要被分以下圖所示的核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。java
二、使用 Spring 框架能帶來哪些好處?
下面列舉了一些使用 Spring 框架帶來的主要好處:web
三、什麼是控制反轉(IOC)?什麼是依賴注入?面試
四、請解釋下 Spring 框架中的 IOC?
Spring 中的 org.springframework.beans 包和 org.springframework.context 包構成了Spring 框架 IOC 容器的基礎。spring
BeanFactory 接口提供了一個先進的配置機制,使得任何類型的對象的配置成爲可能。數據庫
ApplicationContex 接口對 BeanFactory(是一個子接口)進行了擴展,在 BeanFactory 的基礎上添加了其餘功能,好比與 Spring 的 AOP 更容易集成,也提供了處理 message resource的機制(用於國際化)、事件傳播以及應用層的特別配置,好比針對 Web 應用的WebApplicationContext。編程
五、BeanFactory 和 ApplicationContext 有什麼區別?
BeanFactory 能夠理解爲含有 bean 集合的工廠類。BeanFactory 包含了種 bean 的定義,以便在接收到客戶端請求時將對應的 bean 實例化。json
BeanFactory 還能在實例化對象的時生成協做類之間的關係。此舉將 bean 自身與 bean 客戶端的配置中解放出來。BeanFactory 還包含了 bean 生命週期的控制,調用客戶端的初始化方法(initialization methods)和銷燬方法(destruction methods)。設計模式
從表面上看,application context 如同 bean factory 同樣具備 bean 定義、bean 關聯關係的設置,根據請求分發 bean 的功能。但 application context 在此基礎上還提供了其餘的功能。安全
如下是三種較常見的 ApplicationContext 實現方式:
一、ClassPathXmlApplicationContext:從 classpath 的 XML 配置文件中讀取上下文,並生成上下文定義。應用程序上下文從程序環境變量中取得。
ApplicationContext context = new ClassPathXmlApplicationContext(「application.xml」);
二、FileSystemXmlApplicationContext :由文件系統中的 XML 配置文件讀取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext(「application.xml」);
三、XmlWebApplicationContext:由 Web 應用的 XML 文件讀取上下文。
六、Spring 提供幾種配置方式來設置元數據?
將 Spring 配置到應用開發中有如下三種方式:
七、如何使用 XML 配置的方式配置 Spring?
在 Spring 框架中,依賴和服務須要在專門的配置文件來實現,我經常使用的 XML 格式的配置文件。這些配置文件的格式一般用開頭,而後一系列的 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>
八、如何用基於 Java 配置的方式配置 Spring?
Spring 對 Java 配置的支持是由@Configuration 註解和@Bean 註解來實現的。由@Bean 註解的方法將會實例化、配置和初始化一個新對象,這個對象將由 Spring 的 IOC 容器來管理。
@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.gupaoedu.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.gupaoedu")
public class AppConfig {
}
在上面的例子中,com.springtest包首先會被掃到,而後再容器內查找被@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.gupaoedu.AppConfig</param-value>
</context-param>
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-cla
ss>
</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.gupaoedu.web.MVCConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /web/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/web/*</url-pattern>
</servlet-mapping>
</web-app>
九、怎樣用註解的方式配置 Spring?
Spring 在 2.5 版本之後開始支持用註解的方式來配置依賴注入。能夠用註解的方式來替代 XML方式的 bean 描述,能夠將 bean 描述轉移到組件類的內部,只須要在相關類上、方法上或者字段聲明上使用註解便可。註解注入將會被容器在 XML 注入以前被處理,因此後者會覆蓋掉前者對於同一個屬性的處理結果。註解裝配在 Spring 中是默認關閉的。因此須要在 Spring 文件中配置一下才能使用基於註解的裝配模式。若是你想要在你的應用程序中使用關於註解的方法的話,請參考以下的配置。
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
在標籤配置完成之後,就能夠用註解的方式在 Spring 中向屬性、方法和構造方法中自動裝配變-量。
下面是幾種比較重要的註解類型:
十、請解釋 Spring Bean 的生命週期?
Spring Bean 的生命週期簡單易懂。在一個 bean 實例被初始化時,須要執行一系列的初始化操做以達到可用的狀態。一樣的,當一個 bean 不在被調用時須要進行相關的析構操做,並從 bean容器中移除。
Spring bean factory 負責管理在 spring 容器中被建立的 bean 的生命週期。Bean 的生命週期由兩組回調(call back)方法組成。
Spring 框架提供瞭如下四種方式來管理 bean 的生命週期事件:
使用 customInit()和 customDestroy()方法管理 bean 生命週期的代碼樣例以下:
<beans>
<bean id="demoBean" class="com.gupaoedu.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean>
</beans>
十一、Spring Bean 做用域之間的區別?
Spring 容器中的 bean 能夠分爲 5 個範圍。全部範圍的名稱都是自說明的,可是爲了不混淆,仍是讓咱們來解釋一下:
十二、什麼是 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>
1三、Spring 框架中的單例 Beans 是線程安全的麼?
Spring 框架並無對單例 bean 進行任何多線程的封裝處理。關於單例 bean 的線程安全和併發問題須要開發者自行去搞定。但實際上,大部分的 Spring bean 並無可變的狀態(好比Serview類和DAO類),因此在某種程度上說Spring的單例bean是線程安全的。若是你
的bean有多種狀態的話(好比 View Model 對象),就須要自行保證線程安全。最淺顯的解決辦法就是將多態 bean 的做用域由「singleton」變動爲「prototype」。
1四、請舉例說明如何在 Spring 中注入一個 Java 集合?
Spring 提供瞭如下四種集合類的配置元素:
下面看一下具體的例子:
<beans>
<!-- Definition for javaCollection -->
<bean id="javaCollection" class="com.gupaoedu.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@gupaoedu.com</prop>
<prop key="support">support@gupaoedu.com</prop>
</props>
</property>
</bean>
</beans>
1五、如何向 Spring Bean 中注入 java.util.Properties?
第一種方法是使用以下面代碼所示的 標籤:
<bean id="adminUser" class="com.howtodoinjava.common.Customer">
<!-- java.util.Properties -->
<property name="emails">
<props>
<prop key="admin">admin@gupaoedu.com</prop>
<prop key="support">support@gupaoedu.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 設置爲自動裝配:
<bean id="employeeDAO" class="com.gupaoedu.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;
}
1七、請解釋各類自動裝配模式的區別?
在 Spring 框架中共有 5 種自動裝配,讓咱們逐一分析。
1八、如何開啓基於註解的自動裝配?
要使用 @Autowired,須要註冊 AutowiredAnnotationBeanPostProcessor,能夠有如下兩種方式來實現:
一、引入配置文件中的下引入
<beans>
<context:annotation-config />
</beans>
二、在 bean 配置文件中直接引入 AutowiredAnnotationBeanPostProcessor
<beans>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>
19 、 自動裝配有哪些侷限性?
自動裝配有以下侷限性:
20、在 Spring 中能夠注入 null 或空字符串嗎?
徹底能夠。
2一、請舉例解釋@Required Annotation?
在產品級別的應用中,IOC 容器可能聲明瞭數十萬了 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;
}
}
RequiredAnnotationBeanPostProcessor 是 Spring 中的後置處理用來驗證被@Required 註解的 bean 屬性是否被正確的設置了。在使用 RequiredAnnotationBeanPostProcesso 來驗證bean 屬性以前,首先要在 IOC 容器中對其進行註冊:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
但 是 如 果 沒 有 屬 性 被 用 @Required 注 解 過 的 話 , 後 置 處 理 器 會 拋 出 一 個BeanInitializationException 異常。
2二、請舉例解釋@Autowired 註解?
@Autowired 註解對自動裝配什麼時候何處被實現提供了更多細粒度的控制。@Autowired 註解能夠像@Required 註解、構造器同樣被用於在 bean 的設值方法上自動裝配 bean 的屬性,一個參數或者帶有任意名稱或帶有多個參數的方法。
好比,能夠在設值方法上使用@Autowired 註解來替代配置文件中的 元素。當 Spring 容器在setter 方法上找到@Autowired 註解時,會嘗試用 byType 自動裝配。
固然咱們也能夠在構造方法上使用@Autowired 註解。帶有@Autowired 註解的構造方法意味着在建立一個 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.gupaoedu.TextEditor"></bean>
<!-- Definition for spellChecker bean -->
<bean id="spellChecker" class="com.gupaoedu.SpellChecker"></bean>
</beans>
2三、請舉例說明@Qualifier 註解?
@Qualifier 註解意味着能夠在被標註 bean 的字段上能夠自動裝配。Qualifier 註解能夠用來取消 Spring 不能取消的 bean 應用。下面的示例將會在 Customer 的 person 屬性中自動裝配 person 的值。
public class Customer {
@Autowired
private Person person;
}
下面咱們要在配置文件中來配置 Person 類。
<bean id="customer" class="com.gupaoedu.common.Customer" />
<bean id="personA" class="com.gupaoedu.common.Person" >
<property name="name" value="lokesh" />
</bean>
<bean id="personB" class="com.gupaoedu.common.Person" >
<property name="name" value="alex" />
</bean>
Spring 會知道要自動裝配哪一個 person bean 麼?不會的,可是運行上面的示例時,會拋出下面的異常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:No unique bean of type [com.gupaoedu.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;
}
2四、構造方法注入和設值注入有什麼區別?
請注意如下明顯的區別:
因此 Spring 用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在對象被建立以前被調用的。
2五、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 中標準的事件:
除了上面介紹的事件之外,還能夠經過擴展 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);
2六、FileSystemResource 和 ClassPathResource 有何區別?
在 FileSystemResource 中須要給出 spring-config.xml 文件在你項目中的相對路徑或者絕對路徑。在 ClassPathResource 中 spring 會在 ClassPath 中自動搜尋配置文件,因此要把ClassPathResource 文件放在 ClassPath 下。
若是將 spring-config.xml 保存在了 src 文件夾下的話,只需給出配置文件的名稱便可,由於 src文件夾是默認。簡而言之,ClassPathResource 在環境變量中讀取配置文件,FileSystemResource 在配置文件中讀取配置文件。
2七、Spring 框架中都用到了哪些設計模式?
Spring 框架中使用到了大量的設計模式,下面列舉了比較有表明性的:
2八、在 Spring 框架中如何更有效的使用 JDBC?
使用Spring JDBC框架,資源管理以及錯誤處理的代價都會減輕。開發人員只需經過statements和 queries 語句從數據庫中存取數據。Spring 框架中經過使用模板類能更有效的使用 JDBC,也就是所謂的 JdbcTemplate。
2九、Spring5 新特性