1.什麼是 Spring 架構?Spring 架構有哪些主要子產品?
Spring 架構是一個為 Java 應用程式的開發提供了綜合、廣泛的基礎性支援的 Java 平台。Spring幫助開發者解決了開發中基礎性的問題,使得開發人員可以專注于應用程式的開發。Spring 架構本身亦是按照設計模式精心打造,這使得我們可以在開發環境中安心的內建 Spring 架構,不必擔心 Spring 是如何在背景進行工作的。
Spring 架構至今已內建了 20 多個子產品。這些子產品主要被分如下圖所示的核心容器、資料通路/內建,、Web、AOP(面向切面程式設計)、工具、消息和測試子產品。

2.使用 Spring 架構能帶來哪些好處?
下面列舉了一些使用 Spring 架構帶來的主要好處:
1、Dependency Injection(DI) 方法使得構造器和 JavaBean properties 檔案中的依賴關系一目了然。
2、與 EJB 容器相比較,IOC 容器更加趨向于輕量級。這樣一來 IOC 容器在有限的記憶體和 CPU資源的情況下進行應用程式的開發和釋出就變得十分有利。
3、Spring 并沒有閉門造車,Spring 利用了已有的技術比如 ORM 架構、logging 架構、J2EE、Quartz 和 JDK Timer,以及其他視圖技術。
4、Spring 架構是按照子產品的形式來組織的。由包和類的編号就可以看出其所屬的子產品,開發者僅僅需要選用他們需要的子產品即可。
5、要測試一項用 Spring 開發的應用程式十分簡單,因為測試相關的環境代碼都已經囊括在架構中了。更加簡單的是,利用 JavaBean 形式的 POJO 類,可以很友善的利用依賴注入來寫入測試資料。
6、Spring 的 Web 架構亦是一個精心設計的 Web MVC 架構,為開發者們在 web 架構的選擇上提供了一個除了主流架構比如 Struts、過度設計的、不流行 web 架構的以外的有力選項。
7、Spring 提供了一個便捷的事務管理接口,适用于小型的本地事務處理(比如在單 DB 的環境下)和複雜的共同僚務處理(比如利用 JTA 的複雜 DB 環境)。
3.什麼是控制反轉(IOC)?什麼是依賴注入?
1、控制反轉是應用于軟體工程領域中的,在運作時被裝配器對象來綁定耦合對象的一種程式設計技巧,對象之間耦合關系在編譯時通常是未知的。在傳統的程式設計方式中,業務邏輯的流程是由應用程式中的早已被設定好關聯關系的對象來決定的。在使用控制反轉的情況下,業務邏輯的流程是由對象關系圖來決定的,該對象關系圖由裝配器負責執行個體化,這種實作方式還可以将對象之間的關聯關系的定義抽象化。而綁定的過程是通過“依賴注入”實作的。
2、控制反轉是一種以給予應用程式中目标元件更多控制為目的設計範式,并在我們的實際工作中起到了有效的作用。
3、依賴注入是在編譯階段尚未知所需的功能是來自哪個的類的情況下,将其他對象所依賴的功能對象執行個體化的模式。這就需要一種機制用來激活相應的元件以提供特定的功能,是以依賴注入是控制反轉的基礎。否則如果在元件不受架構控制的情況下,架構又怎麼知道要建立哪個元件?
4、在 Java 中依然注入有以下三種實作方式:
A.構造器注入
B.Setter 方法注入
C.接口注入
4.請解釋下 Spring 架構中的 IOC?
Spring 中的 org.springframework.beans 包和org.springframework.context 包構成了Spring 架構 IOC 容器的基礎。
BeanFactory 接口提供了一個先進的配置機制,使得任何類型的對象的配置成為可能。
ApplicationContex 接口對 BeanFactory(是一個子接口)進行了擴充,在 BeanFactory 的基礎上添加了其他功能,比如與 Spring 的 AOP 更容易內建,也提供了處理 message resource的機制(用于國際化)、事件傳播以及應用層的特别配置,比如針對 Web 應用的WebApplicationContext。
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(“application.xml”);
2、FileSystemXmlApplicationContext :由檔案系統中的 XML 配置檔案讀取上下文。ApplicationContext context = new FileSystemXmlApplicationContext(“application.xml”);
3、XmlWebApplicationContext:由 Web 應用的 XML 檔案讀取上下文。
6.Spring 提供幾種配置方式來設定中繼資料?
将 Spring 配置到應用開發中有以下三種方式:
1.基于 XML 的配置
2.基于注解的配置
3.基于 Java 的配置
7.如何使用 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>
複制
8、如何用基于 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.gupaoedu 包首先會被掃到,然後再容器内查找被@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>
複制
9.怎樣用注解的方式配置 Spring?
Spring 在 2.5 版本以後開始支援用注解的方式來配置依賴注入。可以用注解的方式來替代 XML方式的 bean 描述,可以将 bean 描述轉移到元件類的内部,隻需要在相關類上、方法上或者字段聲明上使用注解即可。注解注入将會被容器在 XML 注入之前被處理,是以後者會覆寫掉前者對于同一個屬性的處理結果。注解裝配在 Spring 中是預設關閉的。是以需要在 Spring 檔案中配置一下才能使用基于注解的裝配模式。如果你想要在你的應用程式中使用關于注解的方法的話,請參考如下的配置。
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
複制
在标簽配置完成以後,就可以用注解的方式在 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 的生命周期事件:
1、InitializingBean 和 DisposableBean 回調接口
2、針對特殊行為的其他 Aware 接口
3、Bean 配置檔案中的 Custom init()方法和 destroy()方法
4、@PostConstruct 和@PreDestroy 注解方式
使用 customInit()和 customDestroy()方法管理 bean 生命周期的代碼樣例如下:
<beans>
<bean id="demoBean" class="com.gupaoedu.task.DemoBean"
init-method="customInit" destroy-method="customDestroy">
</bean>
</beans>
複制
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 作用域效果相同。
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 集合?
Spring 提供了以下四種集合類的配置元素:
1、該标簽用來裝配可重複的 list 值。
2、該标簽用來裝配沒有重複的 set 值。
3、該标簽可用來注入鍵和值可以為任何類型的鍵值對。
4、該标簽支援注入鍵和值都是字元串類型的鍵值對。
下面看一下具體的例子:
<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">[email protected]</prop>
<prop key="support">[email protected]</prop>
</props>
</property>
</bean>
</beans>
複制
15.如何向 Spring Bean 中注入 java.util.Properties?
第一種方法是使用如下面代碼所示的 标簽:
<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.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;
}
複制
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、引入配置檔案中的下引入
<beans>
<context:annotation-config />
</beans>
複制
2、在 bean 配置檔案中直接引入AutowiredAnnotationBeanPostProcessor
<beans>
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor"/>
</beans>
複制
19 . 自動裝配有哪些局限性?
自動裝配有如下局限性:重寫:你仍然需要使用 和< property>設定指明依賴,這意味着總要重寫自動裝配。原生資料類型:你不能自動裝配簡單的屬性,如原生類型、字元串和類。模糊特性:自動裝配總是沒有自定義裝配精确,是以,如果可能盡量使用自定義裝配。
20.在 Spring 中可以注入 null 或空字元串嗎?
完全可以。
21.請舉例解釋@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.RequiredAnnotationBeanPostProce
ssor" />
複制
但 是 如 果 沒 有 屬 性 被 用 @Required 注 解 過 的 話 , 後 置 處 理 器 會 抛 出 一 個BeanInitializationException 異常。
22.請舉例解釋@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>
複制
23.請舉例說明@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;
}
複制
24.構造方法注入和設值注入有什麼差別?
請注意以下明顯的差別:
1.在設值注入方法支援大部分的依賴注入,如果我們僅需要注入 int、string 和 long 型的變量,我們不要用設值的方法注入。對于基本類型,如果我們沒有注入的話,可以為基本類型設定預設值。在構造方法注入不支援大部分的依賴注入,因為在調用構造方法中必須傳入正确的構造參數,否則的話為報錯。
2.設值注入不會重寫構造方法的值。如果我們對同一個變量同時使用了構造方法注入又使用了設定方法注入的話,那麼構造方法将不能覆寫由設值方法注入的值。很明顯,因為構造方法盡在對象被建立時調用。
3.在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時對象的依賴關系有可能是不完整的。而在另一種情況下,構造器注入則不允許生成依賴關系不完整的對象。
4. 在 設 值 注 入 時 如 果 對 象 A 和 對 象 B 互 相 依 賴 , 在 創 建 對 象 A 時 Spring 會 抛 出sObjectCurrentlyInCreationException 異常,因為在 B 對象被建立之前 A 對象是不能被建立的,反之亦然。是以 Spring 用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在對象被建立之前被調用的。
25.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);
複制
26、FileSystemResource 和 ClassPathResource 有何差別?
在 FileSystemResource 中需要給出 spring-config.xml 檔案在你項目中的相對路徑或者絕對路徑。在 ClassPathResource 中 spring 會在ClassPath 中自動搜尋配置檔案,是以要把ClassPathResource 檔案放在 ClassPath 下。如果将 spring-config.xml 儲存在了 src 檔案夾下的話,隻需給出配置檔案的名稱即可,因為 src檔案夾是預設。
簡而言之,ClassPathResource 在環境變量中讀取配置檔案FileSystemResource 在配置檔案中讀取配置檔案。
27.Spring 架構中都用到了哪些設計模式?
Spring 架構中使用到了大量的設計模式,下面列舉了比較有代表性的:
1、代理模式—在 AOP 和 remoting 中被用的比較多。
2、單例模式:在 spring 配置檔案中定義的 bean 預設為單例模式。
3、模闆模式:用來解決代碼重複的問題。
比如. RestTemplate, JmsTemplate, JpaTemplate。
4、委派模式:Spring 提供了 DispatcherServlet 來對請求進行分發。
5、工廠模式:BeanFactory 用來建立對象的執行個體,貫穿于 BeanFactory / ApplicationContext接口的核心理念。
6、代理模式:AOP 思想的底層實作技術,Spring 中采用 JDK Proxy 和 CgLib 類庫。
28.在 Spring 架構中如何更有效的使用 JDBC?
使用Spring JDBC架構,資源管理以及錯誤處理的代價都會減輕。開發人員隻需通過statements和 queries 語句從資料庫中存取資料。Spring 架構中通過使用模闆類能更有效的使用 JDBC,也就是所謂的 JdbcTemplate。
29.Spring5 新特性
1、依賴 JDK 8+和 Java EE7+以上版本
2、首次采用反應式程式設計模型
3、支援使用注解進行程式設計
4、新增函數式程式設計
5、支援使用 REST 斷點執行反應式程式設計
6、支援 HTTP 2.0
7、新增 Kotlin 和 Spring WebFlux
8、可使用 Lambda 表達式注冊 Bean
9、Spring WebMVC 支援最新的 API
10、使用 JUnit5 執行條件和并發測試
11、使用 Spring WebFlux 執行內建測試
12、核心容器優化