<meta charset="utf-8">
以下為spring常見面試問題:
1万皿、什么是Spring框架?Spring框架有哪些主要模塊?
Spring框架是一個為Java應(yīng)用程序的開發(fā)提供了綜合、廣泛的基礎(chǔ)性支持的Java平臺门烂。
Spring幫助開發(fā)者解決了開發(fā)中基礎(chǔ)性的問題,使得開發(fā)人員可以專注于應(yīng)用程序的開發(fā)兄淫。
Spring框架本身亦是按照設(shè)計模式精心打造屯远,這使得我們可以在開發(fā)環(huán)境中安心的集成Spring框架,不必?fù)?dān)心Spring是如何在后臺進(jìn)行工作的捕虽。
Spring框架至今已集成了20多個模塊氓润。這些模塊主要被分如下圖所示的核心容器、數(shù)據(jù)訪問/集成,薯鳍、Web、AOP(面向切面編程)挨措、工具挖滤、消息和測試模塊。
2浅役、使用Spring框架能帶來哪些好處斩松?
下面列舉了一些使用Spring框架帶來的主要好處:
- Dependency Injection(DI) 方法使得構(gòu)造器和JavaBean properties文件中的依賴關(guān)系一目了然。
- 與EJB容器相比較觉既,IoC容器更加趨向于輕量級惧盹。這樣一來IoC容器在有限的內(nèi)存和CPU資源的情況下進(jìn)行應(yīng)用程序的開發(fā)和發(fā)布就變得十分有利。
- Spring并沒有閉門造車瞪讼,Spring利用了已有的技術(shù)比如ORM框架钧椰、logging框架、J2EE符欠、Quartz和JDK Timer嫡霞,以及其他視圖技術(shù)。
- Spring框架是按照模塊的形式來組織的希柿。由包和類的編號就可以看出其所屬的模塊诊沪,開發(fā)者僅僅需要選用他們需要的模塊即可。
- 要測試一項用Spring開發(fā)的應(yīng)用程序十分簡單曾撤,因為測試相關(guān)的環(huán)境代碼都已經(jīng)囊括在框架中了端姚。更加簡單的是,利用JavaBean形式的POJO類挤悉,可以很方便的利用依賴注入來寫入測試數(shù)據(jù)渐裸。
- Spring的Web框架亦是一個精心設(shè)計的Web MVC框架,為開發(fā)者們在web框架的選擇上提供了一個除了主流框架比如Struts、過度設(shè)計的橄仆、不流行web框架的以外的有力選項剩膘。
- Spring提供了一個便捷的事務(wù)管理接口,適用于小型的本地事物處理(比如在單DB的環(huán)境下)和復(fù)雜的共同事物處理(比如利用JTA的復(fù)雜DB環(huán)境)盆顾。
3怠褐、什么是控制反轉(zhuǎn)(IOC)?什么是依賴注入您宪?
控制反轉(zhuǎn)是應(yīng)用于軟件工程領(lǐng)域中的奈懒,在運行時被裝配器對象來綁定耦合對象的一種編程技巧,對象之間耦合關(guān)系在編譯時通常是未知的宪巨。在傳統(tǒng)的編程方式中磷杏,業(yè) 務(wù)邏輯的流程是由應(yīng)用程序中的早已被設(shè)定好關(guān)聯(lián)關(guān)系的對象來決定的。在使用控制反轉(zhuǎn)的情況下捏卓,業(yè)務(wù)邏輯的流程是由對象關(guān)系圖來決定的极祸,該對象關(guān)系圖由裝配 器負(fù)責(zé)實例化,這種實現(xiàn)方式還可以將對象之間的關(guān)聯(lián)關(guān)系的定義抽象化怠晴。而綁定的過程是通過“依賴注入”實現(xiàn)的遥金。
控制反轉(zhuǎn)是一種以給予應(yīng)用程序中目標(biāo)組件更多控制為目的設(shè)計范式,并在我們的實際工作中起到了有效的作用蒜田。
依賴注入是在編譯階段尚未知所需的功能是來自哪個的類的情況下稿械,將其他對象所依賴的功能對象實例化的模式。這就需要一種機(jī)制用來激活相應(yīng)的組件以提供特定的功能冲粤,所以依賴注入是控制反轉(zhuǎn)的基礎(chǔ)美莫。否則如果在組件不受框架控制的情況下,框架又怎么知道要創(chuàng)建哪個組件梯捕?
在Java中依然注入有以下三種實現(xiàn)方式:
- 構(gòu)造器注入
- Setter方法注入
- 接口注入
4厢呵、請解釋下Spring框架中的IoC?
Spring中的 org.springframework.beans 包和 org.springframework.context包構(gòu)成了Spring框架IoC容器的基礎(chǔ)傀顾。
BeanFactory 接口提供了一個先進(jìn)的配置機(jī)制述吸,使得任何類型的對象的配置成為可能。ApplicationContex接口對BeanFactory(是一個子接口)進(jìn)行了擴(kuò)展锣笨,在BeanFactory的基礎(chǔ)上添加了其他功能蝌矛,比如與Spring的AOP更容易集成,也提供了處理message resource的機(jī)制(用于國際化)错英、事件傳播以及應(yīng)用層的特別配置入撒,比如針對Web應(yīng)用的WebApplicationContext。
org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具體實現(xiàn)椭岩,用來包裝和管理前面提到的各種bean茅逮。BeanFactory接口是Spring IoC 容器的核心接口璃赡。
IOC:把對象的創(chuàng)建、初始化献雅、銷毀交給spring來管理碉考,而不是由開發(fā)者控制,實現(xiàn)控制反轉(zhuǎn)挺身。
5侯谁、BeanFactory和ApplicationContext有什么區(qū)別?
BeanFactory 可以理解為含有bean集合的工廠類章钾。BeanFactory 包含了種bean的定義墙贱,以便在接收到客戶端請求時將對應(yīng)的bean實例化。
BeanFactory還能在實例化對象的時生成協(xié)作類之間的關(guān)系贱傀。此舉將bean自身與bean客戶端的配置中解放出來惨撇。BeanFactory還包含 了bean生命周期的控制,調(diào)用客戶端的初始化方法(initialization methods)和銷毀方法(destruction methods)府寒。
從表面上看魁衙,application context如同bean factory一樣具有bean定義、bean關(guān)聯(lián)關(guān)系的設(shè)置株搔,根據(jù)請求分發(fā)bean的功能剖淀。但applicationcontext在此基礎(chǔ)上還提供了其他的功能。
- 提供了支持國際化的文本消息
- 統(tǒng)一的資源文件讀取方式
- 已在監(jiān)聽器中注冊的bean的事件
以下是三種較常見的 ApplicationContext 實現(xiàn)方式:
1邪狞、ClassPathXmlApplicationContext:從classpath的XML配置文件中讀取上下文,并生成上下文定義茅撞。應(yīng)用程序上下文從程序環(huán)境變量中
ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
2帆卓、FileSystemXmlApplicationContext :由文件系統(tǒng)中的XML配置文件讀取上下文。
ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
3米丘、XmlWebApplicationContext:由Web應(yīng)用的XML文件讀取上下文剑令。
4.AnnotationConfigApplicationContext(基于Java配置啟動容器)
[圖片上傳失敗...(image-b4dae9-1585553420746)]
6、Spring有幾種配置方式拄查?
將Spring配置到應(yīng)用開發(fā)中有以下三種方式:
- 基于XML的配置
- 基于注解的配置
- 基于Java的配置
7吁津、如何用基于XML配置的方式配置Spring?
在Spring框架中堕扶,依賴和服務(wù)需要在專門的配置文件來實現(xiàn)碍脏,我常用的XML格式的配置文件。這些配置文件的格式通常用<beans>開頭稍算,然后一系列的bean定義和專門的應(yīng)用配置選項組成典尾。
SpringXML配置的主要目的時候是使所有的Spring組件都可以用xml文件的形式來進(jìn)行配置。這意味著不會出現(xiàn)其他的Spring配置類型(比如聲明的方式或基于Java Class的配置方式)
Spring的XML配置方式是使用被Spring命名空間的所支持的一系列的XML標(biāo)簽來實現(xiàn)的糊探。Spring有以下主要的命名空間:context钾埂、beans河闰、jdbc、tx褥紫、aop姜性、mvc和aso。
如:
[圖片上傳失敗...(image-1b4eb6-1585553420746)]
<beans>
<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>
[圖片上傳失敗...(image-4dd034-1585553420746)]
下面這個web.xml僅僅配置了DispatcherServlet髓考,這件最簡單的配置便能滿足應(yīng)用程序配置運行時組件的需求部念。
[圖片上傳失敗...(image-266dd1-1585553420746)]
<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>
[圖片上傳失敗...(image-5aca59-1585553420745)]
8、如何用基于Java配置的方式配置Spring绳军?
Spring對Java配置的支持是由@Configuration注解和@Bean注解來實現(xiàn)的印机。由@Bean注解的方法將會實例化、配置和初始化一個 新對象门驾,這個對象將由Spring的IoC容器來管理射赛。@Bean聲明所起到的作用與<bean/> 元素類似。被 @Configuration所注解的類則表示這個類的主要目的是作為bean定義的資源奶是。被@Configuration聲明的類可以通過在同一個類的 內(nèi)部調(diào)用@bean方法來設(shè)置嵌入bean的依賴關(guān)系楣责。
最簡單的@Configuration 聲明類請參考下面的代碼:
[圖片上傳失敗...(image-8e2f52-1585553420745)]
@Configuration
public class AppConfig{
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
[圖片上傳失敗...(image-573541-1585553420745)]
對于上面的@Beans配置文件相同的XML配置文件如下:
<beans>
<bean id="myService" class="com.somnus.services.MyServiceImpl"/>
</beans>
上述配置方式的實例化方式如下:利用AnnotationConfigApplicationContext 類進(jìn)行實例化
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
要使用組件組建掃描,僅需用@Configuration進(jìn)行注解即可:
@Configuration
@ComponentScan(basePackages = "com.somnus")
public class AppConfig {
...
}
在上面的例子中聂沙,com.acme包首先會被掃到秆麸,然后再容器內(nèi)查找被@Component 聲明的類,找到后將這些類按照Sring bean定義進(jìn)行注冊及汉。
如果你要在你的web應(yīng)用開發(fā)中選用上述的配置的方式的話沮趣,需要用AnnotationConfigWebApplicationContext 類來讀 取配置文件,可以用來配置Spring的Servlet監(jiān)聽器ContextLoaderListener或者Spring MVC的DispatcherServlet坷随。
[圖片上傳失敗...(image-8b11a2-1585553420744)]
<web-app>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.howtodoinjava.AppConfig</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.howtodoinjava.web.MvcConfig</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app
[圖片上傳失敗...(image-a500a1-1585553420743)]
9房铭、怎樣用注解的方式配置Spring?
Spring在2.5版本以后開始支持用注解的方式來配置依賴注入温眉「追耍可以用注解的方式來替代XML方式的bean描述,可以將bean描述轉(zhuǎn)移到組件類的 內(nèi)部类溢,只需要在相關(guān)類上凌蔬、方法上或者字段聲明上使用注解即可。注解注入將會被容器在XML注入之前被處理闯冷,所以后者會覆蓋掉前者對于同一個屬性的處理結(jié) 果砂心。
注解裝配在Spring中是默認(rèn)關(guān)閉的。所以需要在Spring文件中配置一下才能使用基于注解的裝配模式蛇耀。如果你想要在你的應(yīng)用程序中使用關(guān)于注解的方法的話计贰,請參考如下的配置。
<beans>
<context:annotation-config/>
</beans>
在 <context:annotation-config/>標(biāo)簽配置完成以后蒂窒,就可以用注解的方式在Spring中向?qū)傩栽甑埂⒎椒ê蜆?gòu)造方法中自動裝配變量荞怒。
下面是幾種比較重要的注解類型:
- @Required:該注解應(yīng)用于設(shè)值方法。
- @Autowired:該注解應(yīng)用于有值設(shè)值方法秧秉、非設(shè)值方法褐桌、構(gòu)造方法和變量。
- @Qualifier:該注解和@Autowired注解搭配使用象迎,用于消除特定bean自動裝配的歧義荧嵌。
- JSR-250 Annotations:Spring支持基于JSR-250 注解的以下注解,@Resource砾淌、@PostConstruct 和 @PreDestroy啦撮。
10、請解釋Spring Bean的生命周期汪厨?
Spring Bean的生命周期簡單易懂赃春。在一個bean實例被初始化時,需要執(zhí)行一系列的初始化操作以達(dá)到可用的狀態(tài)劫乱。同樣的织中,當(dāng)一個bean不在被調(diào)用時需要進(jìn)行相關(guān)的析構(gòu)操作,并從bean容器中移除衷戈。
Spring bean factory 負(fù)責(zé)管理在spring容器中被創(chuàng)建的bean的生命周期狭吼。Bean的生命周期由兩組回調(diào)(call back)方法組成。
- 初始化之后調(diào)用的回調(diào)方法殖妇。
- 銷毀之前調(diào)用的回調(diào)方法刁笙。
Spring框架提供了以下四種方式來管理bean的生命周期事件:
- InitializingBean和DisposableBean回調(diào)接口
- 針對特殊行為的其他Aware接口
- Bean配置文件中的Custom init()方法和destroy()方法
- @PostConstruct和@PreDestroy注解方式
使用customInit()和 customDestroy()方法管理bean生命周期的代碼樣例如下:
<beans>
<bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean>
</beans>
11、Spring Bean的作用域之間有什么區(qū)別谦趣?
Spring容器中的bean可以分為5個范圍疲吸。所有范圍的名稱都是自說明的,但是為了避免混淆蔚润,還是讓我們來解釋一下:
- singleton:這種bean范圍是默認(rèn)的磅氨,這種范圍確保不管接受到多少個請求尺栖,每個容器中只有一個bean的實例嫡纠,單例的模式由bean factory自身來維護(hù)。
- prototype:原形范圍與單例范圍相反延赌,為每一個bean請求提供一個實例除盏。
- request:在請求bean范圍內(nèi)會每一個來自客戶端的網(wǎng)絡(luò)請求創(chuàng)建一個實例,在請求完成以后挫以,bean會失效并被垃圾回收器回收者蠕。
- Session:與請求范圍類似,確保每個session中有一個bean的實例掐松,在session過期后踱侣,bean會隨之失效粪小。
- global- session:global-session和Portlet應(yīng)用相關(guān)。當(dāng)你的應(yīng)用部署在Portlet容器中工作時抡句,它包含很多portlet探膊。如果 你想要聲明讓所有的portlet共用全局的存儲變量的話,那么這全局變量需要存儲在global-session中待榔。
全局作用域與Servlet中的session作用域效果相同逞壁。
12、什么是Spring inner beans锐锣?
在Spring框架中腌闯,無論何時bean被使用時,當(dāng)僅被調(diào)用了一個屬性雕憔。一個明智的做法是將這個bean聲明為內(nèi)部bean姿骏。內(nèi)部bean可以用setter注入“屬性”和構(gòu)造方法注入“構(gòu)造參數(shù)”的方式來實現(xiàn)。
比如橘茉,在我們的應(yīng)用程序中工腋,一個Customer類引用了一個Person類,我們的要做的是創(chuàng)建一個Person的實例畅卓,然后在Customer內(nèi)部使用擅腰。
public class Customer{
private Person person;
//Setters and Getters
}
[圖片上傳失敗...(image-57dc83-1585553420742)]
public class Person{
private String name;
private String address;
private int age;
//Setters and Getters
}
[圖片上傳失敗...(image-2eef7f-1585553420742)]
內(nèi)部bean的聲明方式如下:
[圖片上傳失敗...(image-88de64-1585553420742)]
<bean id="CustomerBean" class="com.somnus.common.Customer">
<property name="person">
<bean class="com.howtodoinjava.common.Person">
<property name="name" value="lokesh" />
<property name="address" value="India" />
<property name="age" value="34" />
</bean>
</property>
</bean>
[圖片上傳失敗...(image-5f4bad-1585553420741)]
13、Spring框架中的單例Beans是線程安全的么翁潘?
Spring框架并沒有對單例bean進(jìn)行任何多線程的封裝處理趁冈。關(guān)于單例bean的線程安全和并發(fā)問題需要開發(fā)者自行去搞定。但實際上拜马,大部分的Spring bean并沒有可變的狀態(tài)(比如Serview類和DAO類)渗勘,所以在某種程度上說Spring的單例bean是線程安全的。如果你的bean有多種狀態(tài)的話(比如 View Model 對象)俩莽,就需要自行保證線程安全旺坠。 最淺顯的解決辦法就是將多態(tài)bean的作用域由“singleton”變更為“prototype”。
14扮超、請舉例說明如何在Spring中注入一個Java Collection取刃?
Spring提供了以下四種集合類的配置元素:
- <list> : 該標(biāo)簽用來裝配可重復(fù)的list值。
- <set> : 該標(biāo)簽用來裝配沒有重復(fù)的set值出刷。
- <map>: 該標(biāo)簽可用來注入鍵和值可以為任何類型的鍵值對璧疗。
- <props> : 該標(biāo)簽支持注入鍵和值都是字符串類型的鍵值對。
下面看一下具體的例子:
[圖片上傳失敗...(image-b21f0c-1585553420741)]
<beans>
<bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
<property name="customList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</list>
</property>
<property name="customSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>UK</value>
</set>
</property>
<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>
<property name="customProperies">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
</beans>
[圖片上傳失敗...(image-6affa4-1585553420740)]
15馁龟、如何向Spring Bean中注入一個Java.util.Properties崩侠?
第一種方法是使用如下面代碼所示的<props> 標(biāo)簽:
[圖片上傳失敗...(image-cf6a32-1585553420740)]
<bean id="adminUser" class="com.somnus.common.Customer">
<property name="emails">
<props>
<prop key="admin">admin@nospam.com</prop>
<prop key="support">support@nospam.com</prop>
</props>
</property>
</bean>
[圖片上傳失敗...(image-878f3f-1585553420739)]
也可用”util:”命名空間來從properties文件中創(chuàng)建出一個propertiesbean,然后利用setter方法注入bean的引用坷檩。
16却音、請解釋Spring Bean的自動裝配改抡?
在Spring框架中,在配置文件中設(shè)定bean的依賴關(guān)系是一個很好的機(jī)制系瓢,Spring容器還可以自動裝配合作關(guān)系bean之間的關(guān)聯(lián)關(guān)系雀摘。這意味著 Spring可以通過向Bean Factory中注入的方式自動搞定bean之間的依賴關(guān)系。自動裝配可以設(shè)置在每個bean上八拱,也可以設(shè)定在特定的bean上阵赠。
下面的XML配置文件表明了如何根據(jù)名稱將一個bean設(shè)置為自動裝配:
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了bean配置文件中提供的自動裝配模式,還可以使用@Autowired注解來自動裝配指定的bean肌稻。在使用@Autowired注解之前需要在按照如下的配置方式在Spring配置文件進(jìn)行配置才可以使用清蚀。
<context:annotation-config />
也可以通過在配置文件中配置AutowiredAnnotationBeanPostProcessor 達(dá)到相同的效果。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
配置好以后就可以使用@Autowired來標(biāo)注了爹谭。
@Autowired
public EmployeeDAOImpl ( EmployeeManager manager ) {
this.manager = manager;
}
17枷邪、請解釋自動裝配模式的區(qū)別?
在Spring框架中共有5種自動裝配诺凡,讓我們逐一分析东揣。
- no:這是Spring框架的默認(rèn)設(shè)置,在該設(shè)置下自動裝配是關(guān)閉的腹泌,開發(fā)者需要自行在bean定義中用標(biāo)簽明確的設(shè)置依賴關(guān)系嘶卧。
- byName:該選項可以根據(jù)bean名稱設(shè)置依賴關(guān)系。當(dāng)向一個bean中自動裝配一個屬性時凉袱,容器將根據(jù)bean的名稱自動在在配置文件中查詢一個匹配的bean芥吟。如果找到的話,就裝配這個屬性专甩,如果沒找到的話就報錯钟鸵。
- byType:該選項可以根據(jù)bean類型設(shè)置依賴關(guān)系。當(dāng)向一個bean中自動裝配一個屬性時涤躲,容器將根據(jù)bean的類型自動在在配置文件中查詢一個匹配的bean棺耍。如果找到的話,就裝配這個屬性种樱,如果沒找到的話就報錯蒙袍。
- constructor:造器的自動裝配和byType模式類似,但是僅僅適用于與有構(gòu)造器相同參數(shù)的bean缸托,如果在容器中沒有找到與構(gòu)造器參數(shù)類型一致的bean左敌,那么將會拋出異常瘾蛋。
- autodetect:該模式自動探測使用構(gòu)造器自動裝配或者byType自動裝配俐镐。首先,首先會嘗試找合適的帶參數(shù)的構(gòu)造器哺哼,如果找到的話就是用構(gòu)造器自動裝配佩抹,如果在bean內(nèi)部沒有找到相應(yīng)的構(gòu)造器或者是無參構(gòu)造器叼风,容器就會自動選擇byTpe的自動裝配方式。
18棍苹、如何開啟基于注解的自動裝配?
要使用 @Autowired,需要注冊 AutowiredAnnotationBeanPostProcessor涉枫,可以有以下兩種方式來實現(xiàn):
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注解彬碱?
在產(chǎn)品級別的應(yīng)用中,IoC容器可能聲明了數(shù)十萬了bean奥洼,bean與bean之間有著復(fù)雜的依賴關(guān)系巷疼。設(shè)值注解方法的短板之一就是驗證所有的屬性是否被注解是一項十分困難的操作×榻保可以通過在<bean>中設(shè)置“dependency-check”來解決這個問題嚼沿。
在應(yīng)用程序的生命周期中,你可能不大愿意花時間在驗證所有bean的屬性是否按照上下文文件正確配置瓷患÷饩。或者你寧可驗證某個bean的特定屬性是否被正確的設(shè)置。即使是用“dependency-check”屬性也不能很好的解決這個問題擅编,在這種情況下爆阶,你需要使用@Required 注解。
需要用如下的方式使用來標(biāo)明bean的設(shè)值方法沙咏。
[圖片上傳失敗...(image-4ddc3e-1585553420739)]
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
}
[圖片上傳失敗...(image-3342cd-1585553420739)]
RequiredAnnotationBeanPostProcessor是Spring中的后置處理用來驗證被@Required 注解的bean屬性是否被正確的設(shè)置了辨图。在使用RequiredAnnotationBeanPostProcesso來驗證bean屬性之前,首先要在IoC容器中對其進(jìn)行注冊:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
但是如果沒有屬性被用 @Required 注解過的話肢藐,后置處理器會拋出一個BeanInitializationException 異常故河。
20、請舉例解釋@Autowired注解吆豹?
@Autowired注解對自動裝配何時何處被實現(xiàn)提供了更多細(xì)粒度的控制鱼的。@Autowired注解可以像@Required注解、構(gòu)造器一樣被用于在bean的設(shè)值方法上自動裝配bean的屬性痘煤,一個參數(shù)或者帶有任意名稱或帶有多個參數(shù)的方法凑阶。
比如,可以在設(shè)值方法上使用@Autowired注解來替代配置文件中的 <property>元素衷快。當(dāng)Spring容器在setter方法上找到@Autowired注解時宙橱,會嘗試用byType 自動裝配。
當(dāng)然我們也可以在構(gòu)造方法上使用@Autowired 注解。帶有@Autowired 注解的構(gòu)造方法意味著在創(chuàng)建一個bean時將會被自動裝配师郑,即便在配置文件中使用<constructor-arg> 元素环葵。
[圖片上傳失敗...(image-278d29-1585553420739)]
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();
}
}
[圖片上傳失敗...(image-c607e2-1585553420738)]
下面是沒有構(gòu)造參數(shù)的配置方式:
[圖片上傳失敗...(image-578414-1585553420738)]
<beans>
<context:annotation-config/>
<bean id="textEditor" class="com.howtodoinjava.TextEditor"/>
<bean id="spellChecker" class="com.howtodoinjava.SpellChecker"/>
</beans>
[圖片上傳失敗...(image-d870b9-1585553420738)]
21、請舉例說明@Qualifier注解宝冕?
@Qualifier注解意味著可以在被標(biāo)注bean的字段上可以自動裝配张遭。Qualifier注解可以用來取消Spring不能取消的bean應(yīng)用。
下面的示例將會在Customer的person屬性中自動裝配person的值地梨。
public class Customer{
@Autowired
private Person person;
}
下面我們要在配置文件中來配置Person類菊卷。
[圖片上傳失敗...(image-c4173d-1585553420738)]
<bean id="customer" class="com.somnus.common.Customer" />
<bean id="personA" class="com.somnus.common.Person" >
<property name="name" value="lokesh" />
</bean>
<bean id="personB" class="com.somnus.common.Person" >
<property name="name" value="alex" />
</bean>
[圖片上傳失敗...(image-909aa2-1585553420738)]
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诈闺、構(gòu)造方法注入和設(shè)值注入有什么區(qū)別渴庆?
請注意以下明顯的區(qū)別:
- 在設(shè)值注入方法支持大部分的依賴注入,如果我們僅需 要注入int雅镊、string和long型的變量襟雷,我們不要用設(shè)值的方法注入。對于基本類型仁烹,如果我們沒有注入的話耸弄,可以為基本類型設(shè)置默認(rèn)值。在構(gòu)造方法 注入不支持大部分的依賴注入卓缰,因為在調(diào)用構(gòu)造方法中必須傳入正確的構(gòu)造參數(shù)计呈,否則的話為報錯。
- 設(shè)值注入不會重寫構(gòu)造方法的值征唬。如果我們對同一個變量同時使用了構(gòu)造方法注入又使用了設(shè)置方法注入的話捌显,那么構(gòu)造方法將不能覆蓋由設(shè)值方法注入的值。很明顯总寒,因為構(gòu)造方法盡在對象被創(chuàng)建時調(diào)用扶歪。
- 在使用設(shè)值注入時有可能還不能保證某種依賴是否已經(jīng)被注入,也就是說這時對象的依賴關(guān)系有可能是不完整的摄闸。而在另一種情況下善镰,構(gòu)造器注入則不允許生成依賴關(guān)系不完整的對象。
- 在設(shè)值注入時如果對象A和對象B互相依賴年枕,在創(chuàng)建對象A時Spring會拋出sObjectCurrentlyInCreationException異常炫欺,因為在B對象被創(chuàng)建之前A對象是不能被創(chuàng)建的,反之亦然熏兄。所以Spring用設(shè)值注入的方法解決了循環(huán)依賴的問題品洛,因?qū)ο蟮脑O(shè)值方法是在對象被創(chuàng)建之前被調(diào)用的树姨。
23、Spring框架中有哪些不同類型的事件毫别?
Spring的ApplicationContext 提供了支持事件和代碼中監(jiān)聽器的功能。
我們可以創(chuàng)建bean用來監(jiān)聽在ApplicationContext 中發(fā)布的事件典格。ApplicationEvent類和在ApplicationContext接口中處理的事件岛宦,如果一個bean實現(xiàn)了ApplicationListener接口,當(dāng)一個ApplicationEvent 被發(fā)布以后耍缴,bean會自動被通知砾肺。
[圖片上傳失敗...(image-82a2ff-1585553420737)]
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent >{
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent)
{
//process event
}
}
[圖片上傳失敗...(image-65a161-1585553420737)]
Spring 提供了以下5中標(biāo)準(zhǔn)的事件:
- 上下文更新事件(ContextRefreshedEvent):該事件會在ApplicationContext被初始化或者更新時發(fā)布。也可以在調(diào)用ConfigurableApplicationContext 接口中的refresh()方法時被觸發(fā)防嗡。
- 上下文開始事件(ContextStartedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開始/重新開始容器時觸發(fā)該事件变汪。
- 上下文停止事件(ContextStoppedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時觸發(fā)該事件。
- 上下文關(guān)閉事件(ContextClosedEvent):當(dāng)ApplicationContext被關(guān)閉時觸發(fā)該事件蚁趁。容器被關(guān)閉時裙盾,其管理的所有單例Bean都被銷毀。
- 請求處理事件(RequestHandledEvent):在Web應(yīng)用中他嫡,當(dāng)一個http請求(request)結(jié)束觸發(fā)該事件番官。
除了上面介紹的事件以外,還可以通過擴(kuò)展ApplicationEvent 類來開發(fā)自定義的事件钢属。
public class CustomApplicationEvent extends ApplicationEvent{
public CustomApplicationEvent ( Object source, final String msg ){
super(source);
System.out.println("Created a Custom event");
}
}
為了監(jiān)聽這個事件徘熔,還需要創(chuàng)建一個監(jiān)聽器:
public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >{
@Override
public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
//handle event
}
}
之后通過applicationContext接口的publishEvent()方法來發(fā)布自定義事件。
CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");
applicationContext.publishEvent(customEvent);
24淆党、FileSystemResource和ClassPathResource有何區(qū)別酷师?
在FileSystemResource 中需要給出spring-config.xml文件在你項目中的相對路徑或者絕對路徑。在ClassPathResource中spring會在ClassPath中自動搜尋配置文件染乌,所以要把ClassPathResource 文件放在ClassPath下山孔。
如果將spring-config.xml保存在了src文件夾下的話,只需給出配置文件的名稱即可荷憋,因為src文件夾是默認(rèn)饱须。
簡而言之,ClassPathResource在環(huán)境變量中讀取配置文件台谊,F(xiàn)ileSystemResource在配置文件中讀取配置文件蓉媳。
25、Spring 框架中都用到了哪些設(shè)計模式锅铅?
Spring框架中使用到了大量的設(shè)計模式酪呻,下面列舉了比較有代表性的:
- 代理模式—在AOP和remoting中被用的比較多。
- 單例模式—在spring配置文件中定義的bean默認(rèn)為單例模式盐须。
- 模板方法—用來解決代碼重復(fù)的問題玩荠。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 前端控制器—Spring提供了DispatcherServlet來對請求進(jìn)行分發(fā)。
- 視圖幫助(View Helper )—Spring提供了一系列的JSP標(biāo)簽阶冈,高效宏來輔助將分散的代碼整合在視圖里闷尿。
- 依賴注入—貫穿于BeanFactory / ApplicationContext接口的核心理念。
- 工廠模式—BeanFactory用來創(chuàng)建對象的實例
1. 開發(fā)中主要使用 Spring 的什么技術(shù) ?
①. IOC 容器管理各層的組件
②. 使用 AOP 配置聲明式事務(wù)
③. 整合其他框架.
2. 簡述 AOP 和 IOC 概念 AOP:
Aspect Oriented Program, 面向(方面)切面的編程;Filter(過濾器) 也是一種 AOP. AOP 是一種新的方法論, 是對傳統(tǒng) OOP(Object-Oriented Programming, 面向?qū)ο缶幊? 的補充. AOP 的主要編程對象是切面(aspect), 而切面模塊化橫切關(guān)注點.可以舉例通過事務(wù)說明.
IOC: Invert Of Control, 控制反轉(zhuǎn). 也成為 DI(依賴注入)其思想是反轉(zhuǎn) 資源獲取的方向. 傳統(tǒng)的資源查找方式要求組件向容器發(fā)起請求查找資源.作為 回應(yīng), 容器適時的返回資源. 而應(yīng)用了 IOC 之后, 則是容器主動地將資源推送 給它所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源. 這種行 為也被稱為查找的被動形式
3. 在 Spring 中如何配置 Bean ?
Bean 的配置方式: 通過全類名(反射)女坑、通過工廠方法(靜態(tài)工廠方法 & 實 例工廠方法)填具、FactoryBean
4. IOC 容器對 Bean 的生命周期:
①. 通過構(gòu)造器或工廠方法創(chuàng)建 Bean 實例
②. 為 Bean 的屬性設(shè)置值和對其他 Bean 的引用
③ . 將 Bean 實 例 傳 遞 給 Bean 后 置 處 理 器 的 postProcessBeforeInitialization 方法
④. 調(diào)用 Bean 的初始化方法(init-method)
⑤ . 將 Bean 實 例 傳 遞 給 Bean 后 置 處 理 器 的 postProcessAfterInitialization 方法
⑦. Bean 可以使用了
⑧. 當(dāng)容器關(guān)閉時, 調(diào)用 Bean 的銷毀方法(destroy-method)