2021-01-31 今日主題:Spring

今日主題:Spring

1 什么是Spring框架?Spring框架有哪些主要模塊?

Spring框架是一個(gè)為Java應(yīng)用程序開(kāi)發(fā)提供綜合、廣泛的基礎(chǔ)性支持的Java平臺(tái)。Spring幫助開(kāi)發(fā)者解決了開(kāi)發(fā)中基礎(chǔ)性的問(wèn)題,使得開(kāi)發(fā)人員可以專注于應(yīng)用程序的開(kāi)發(fā)。Spring框架本身也是按照設(shè)計(jì)模式精心打造,這使得我們可以在開(kāi)發(fā)環(huán)境中安心地集成Spring框架,不必?fù)?dān)心Spring是如何在后臺(tái)工作的。

Spring大約18個(gè)基本模塊,大致分為4類;分別是核心模塊、AOP、數(shù)據(jù)訪問(wèn)、Web模塊、測(cè)試模塊。

核心模塊包括:core、beans、context、context-support、expression共5個(gè)模塊;

AOP模塊包括:aop、aspects、instrument共3個(gè)模塊;

數(shù)據(jù)訪問(wèn)模塊包括:jdbc、tx、orm、oxm共4個(gè)模塊;

Web模塊包括:web、webmvc、websocket、webflux共4個(gè)模塊;

集成測(cè)試模塊:test模塊。

2 使用Spring框架能帶來(lái)哪些好處?

下面列舉了一些使用Spring框架帶來(lái)的主要好處。

(1)Dependency Injection(DI) 方法使得構(gòu)造器和JavaBean properties文件中的依賴關(guān)系一目了然。

(2)與EJB容器相比較,IOC容器更加趨向于輕量級(jí)。這樣一來(lái)IOC容器在有限的內(nèi)存和CPU資源的情況下進(jìn)行應(yīng)用程序的開(kāi)發(fā)和發(fā)布就變得十分有利。

(3)Spring并沒(méi)有閉門(mén)造車,Spring利用了已有的技術(shù),比如ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其他視圖技術(shù)。

(4)Spring框架是按照模塊的形式來(lái)組織的。由包和類的編號(hào)就可以看出其所屬的模塊,開(kāi)發(fā)者只需選用他們需要的模塊即可。

(5)要測(cè)試一項(xiàng)用Spring開(kāi)發(fā)的應(yīng)用程序十分簡(jiǎn)單,因?yàn)闇y(cè)試相關(guān)的環(huán)境代碼都已經(jīng)囊括在框架中了。更加簡(jiǎn)單的是,利用JavaBean形式的POJO類,可以很方便地利用依賴注入來(lái)寫(xiě)入測(cè)試數(shù)據(jù)。

(6)Spring的Web框架也是一個(gè)精心設(shè)計(jì)的Web MVC框架,為開(kāi)發(fā)者們?cè)赪eb框架的選擇上提供了一個(gè)除主流框架比如Struts、過(guò)度設(shè)計(jì)的、不流行Web框架以外的選擇。

(7)Spring提供了一個(gè)便捷的事務(wù)管理接口,適用于小型的本地事務(wù)處理(比如在單DB的環(huán)境下)和復(fù)雜的共

同事務(wù)處理(比如利用JTA的復(fù)雜DB環(huán)境)。

3 什么是控制反轉(zhuǎn)(IOC)?什么是依賴注入?

(1)控制反轉(zhuǎn)是應(yīng)用于軟件工程領(lǐng)域的,在運(yùn)行時(shí)被裝配器對(duì)象用來(lái)綁定耦合對(duì)象的一種編程技巧,對(duì)象之間的耦合關(guān)系在編譯時(shí)通常是未知的。在傳統(tǒng)的編程方式中,業(yè)務(wù)邏輯的流程是由應(yīng)用程序中早已被設(shè)定好關(guān)聯(lián)關(guān)系的對(duì)象來(lái)決定的。在使用控制反轉(zhuǎn)的情況下,業(yè)務(wù)邏輯的流程是由對(duì)象關(guān)系圖來(lái)決定的,該對(duì)象關(guān)系圖由裝配器負(fù)責(zé)實(shí)例化,這種實(shí)現(xiàn)方式還可以將對(duì)象之間的關(guān)聯(lián)關(guān)系的定義抽象化。綁定的過(guò)程是通過(guò)“依賴注入”實(shí)現(xiàn)的。

(2)控制反轉(zhuǎn)是一種以給予應(yīng)用程序中目標(biāo)組件更多控制為目的設(shè)計(jì)范式,并在我們的實(shí)際工作中起到了有效的作用。

(3)依賴注入是在編譯階段尚未知所需的功能是來(lái)自哪個(gè)的類的情況下,將其他對(duì)象所依賴的功能對(duì)象實(shí)例化的模式。這就需要一種機(jī)制用來(lái)激活相應(yīng)的組件以提供特定的功能,所以依賴注入是控制反轉(zhuǎn)的基礎(chǔ)。否則如果在組件不受框架控制的情況下,框架又怎么知道要?jiǎng)?chuàng)建哪個(gè)組件呢?

4 在Java中依賴注入有哪些方式?

(1)構(gòu)造器注入。

(2)Setter方法注入。

(3)接口注入。

5 BeanFactory和ApplicationContext有什么區(qū)別?

BeanFactory 可以理解為含有Bean集合的工廠類。BeanFactory 包含了bean的定義,以便在接收到客戶端請(qǐng)求時(shí)將對(duì)應(yīng)的Bean實(shí)例化。

BeanFactory還能在實(shí)例化對(duì)象時(shí)生成協(xié)作類之間的關(guān)系。此舉將Bean自身從Bean客戶端的配置中解放出來(lái)。BeanFactory還包含Bean生命周期的控制,調(diào)用客戶端的初始化方法(initialization Methods)和銷毀方法(destruction Methods)。

從表面上看,ApplicationContext如同Bean Factory一樣具有Bean定義、Bean關(guān)聯(lián)關(guān)系的設(shè)置,以及根據(jù)請(qǐng)求分發(fā)Bean的功能。但ApplicationContext在此基礎(chǔ)上還提供了其他功能。

(1)提供了支持國(guó)際化的文本消息。

(2)統(tǒng)一的資源文件讀取方式。

(3)已在監(jiān)聽(tīng)器中注冊(cè)的Bean的事件。

以下是三種較常見(jiàn)的 ApplicationContext 實(shí)現(xiàn)方式。

(1)ClassPathXmlApplicationContext:從classpath的XML配置文件中讀取上下文,并生成上下文定義。應(yīng)用程序上下文從程序環(huán)境變量中取得。

ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);

(2)FileSystemXmlApplicationContext :由文件系統(tǒng)中的XML配置文件讀取上下文。

ApplicationContext context = new FileSystemXmlApplicationContext(“application.xml”);

(3)XmlWebApplicationContext:由Web應(yīng)用的XML文件讀取上下文。

6 Spring提供幾種配置方式來(lái)設(shè)置元數(shù)據(jù)?

將Spring配置到應(yīng)用開(kāi)發(fā)中有以下三種方式:

(1)基于XML的配置。

(2)基于注解的配置。

(3)基于Java的配置。

7 如何使用XML配置的方式配置Spring?

在Spring框架中,依賴和服務(wù)需要專門(mén)的配置文件中實(shí)現(xiàn),我一般用XML格式的配置文件。這些配置文件的格式采用通公共的模板,由一系列的Bean定義和專門(mén)的應(yīng)用配置選項(xiàng)組成。

Spring XML配置的主要目的是使所有的Spring組件都可以用XML文件的形式來(lái)進(jìn)行配置。這意味著不會(huì)出現(xiàn)其他的Spring配置類型(比如聲明的方式或基于Java Class的配置方式)。

Spring的XML配置方式是使用被Spring命名空間所支持的一系列的XML標(biāo)簽來(lái)實(shí)現(xiàn)的。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>

下面這個(gè)web.xml僅配置了DispatcherServlet,這最簡(jiǎn)單的配置便能滿足應(yīng)用程序配置運(yùn)行時(shí)組件的需求。

<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 Spring提供哪些配置形式?

Spring對(duì)Java配置的支持是由@Configuration注解和@Bean注解來(lái)實(shí)現(xiàn)的。由@Bean注解的方法將會(huì)實(shí)例化、配置和初始化一個(gè)新對(duì)象,這個(gè)對(duì)象將由Spring的IOC容器來(lái)管理。@Bean聲明所起到的作用與元素類似。被@Configuration所注解的類則表示這個(gè)類的主要目的是作為Bean定義的資源。被@Configuration聲明的類可以通過(guò)在同一個(gè)類的內(nèi)部調(diào)用@bean方法來(lái)設(shè)置嵌入Bean的依賴關(guān)系。

最簡(jiǎn)單的@Configuration 聲明類請(qǐng)參考下面的代碼:

@Configuration

public class AppConfig{

  @Bean

  public MyService myService() {

   return new MyServiceImpl();

  }

}

與上面的@Beans配置文件相同的XML配置文件如下:

<beans>

  <bean id="myService" class="com.gupaoedu.services.MyServiceImpl"/>

</beans>

上述配置方式的實(shí)例化方式如下:

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.gupaoedu")

public class AppConfig {

}

在上面的例子中,com.gupaoedu包首先會(huì)被掃描到,然后在容器內(nèi)查找被@Component 聲明的類,找到后將這些類按照Spring Bean定義進(jìn)行注冊(cè)。

如果你要在Web應(yīng)用開(kāi)發(fā)中選用上述配置方式,需要用AnnotationConfigWebApplicationContext類來(lái)讀取配置文件,可以用來(lái)配置Spring的Servlet監(jiān)聽(tīng)器ContrextLoaderListener或者Spring MVC的DispatcherServlet。

<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.gupaoedu.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.gupaoedu.web.MVCConfig</param-value>

   </init-param>

  </servlet>

  <servlet-mapping>

   <servlet-name>dispatcher</servlet-name>

   <url-pattern>/web/*</url-pattern>

  </servlet-mapping>

</web-app>

9 怎樣用注解的方式配置Spring?

Spring在2.5版本以后開(kāi)始支持用注解的方式來(lái)配置依賴注入??梢杂米⒔獾姆绞絹?lái)替代XML方式的Bean描述,可以將Bean描述轉(zhuǎn)移到組件類的內(nèi)部,只需要在相關(guān)類上、方法上或者字段聲明上使用注解即可。注解注入將會(huì)被容器在XML注入之前處理,所以后者會(huì)覆蓋前者對(duì)于同一個(gè)屬性的處理結(jié)果。

注解裝配在Spring中是默認(rèn)關(guān)閉的,需要在Spring文件中配置一下才能使用基于注解的裝配模式。如果你想要在應(yīng)用程序中使用注解的方式,請(qǐng)參考如下配置:

<beans>

  <context:annotation-config/>

</beans>

標(biāo)簽配置完成以后,就可以用注解的方式在Spring中向?qū)傩?、方法和?gòu)造方法中自動(dòng)裝配變量。

下面是幾種比較重要的注解類型。

(1)@Required:該注解應(yīng)用于設(shè)值方法。

(2)@Autowired:該注解應(yīng)用于有值設(shè)值方法、非設(shè)值方法、構(gòu)造方法和變量。

(3)@Qualifier:該注解和@Autowired注解搭配使用,用于消除特定Bean自動(dòng)裝配的歧義。

(4)JSR-250 Annotations:Spring支持基于JSR-250 注解的注解,@Resource、@PostConstruct 和 @PreDestroy。

10 請(qǐng)解釋Spring Bean的生命周期?

Spring Bean的生命周期簡(jiǎn)單易懂。在一個(gè)Bean實(shí)例被初始化時(shí),需要執(zhí)行一系列初始化操作以達(dá)到可用的狀態(tài)。同樣,當(dāng)一個(gè)Bean不再被調(diào)用時(shí)需要進(jìn)行相關(guān)的析構(gòu)操作,并從Bean容器中移除。

Spring Bean Factory 負(fù)責(zé)管理在Spring容器中被創(chuàng)建的Bean的生命周期。Bean的生命周期由兩組回調(diào)方法組成。

(1)初始化之后調(diào)用的回調(diào)方法。

(2)銷毀之前調(diào)用的回調(diào)方法。

Spring框架提供了以下四種方式來(lái)管理Bean的生命周期事件:

(1)InitializingBean和DisposableBean回調(diào)接口。

(2)針對(duì)特殊行為的其他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作用域的區(qū)別是什么?

Spring容器中的Bean可以分為5個(gè)范圍。所有范圍的名稱都是自說(shuō)明的,但是為了避免混淆,還是讓我們來(lái)解釋一下。

(1)singleton:這種Bean范圍是默認(rèn)的,這種范圍確保不管接收到多少個(gè)請(qǐng)求,每個(gè)容器中只有一個(gè)Bean的實(shí)例,單例的模式由Bean Factory自身來(lái)維護(hù)。

(2)prototype:原形范圍與單例范圍相反,為每一個(gè)Bean請(qǐng)求提供一個(gè)實(shí)例。

(3)request:在請(qǐng)求Bean范圍內(nèi)為每一個(gè)來(lái)自客戶端的網(wǎng)絡(luò)請(qǐng)求創(chuàng)建一個(gè)實(shí)例,在請(qǐng)求完成以后,Bean會(huì)失效并被垃圾回收器回收。

(4)Session:與請(qǐng)求范圍類似,確保每個(gè)Session中有一個(gè)Bean的實(shí)例,在Session過(guò)期后,Bean會(huì)隨之失效。

(5)global-session:global-session和Portlet應(yīng)用相關(guān)。當(dāng)你的應(yīng)用部署在Portlet容器中時(shí),它包含很多portlet。如果你想要聲明讓所有的portlet共用全局的存儲(chǔ)變量,那么這個(gè)全局變量需要存儲(chǔ)在global-session中。全局作用域與Servlet中的Session作用域效果相同。

12 什么是Spring Inner Bean?

在Spring框架中,無(wú)論何時(shí)Bean被使用時(shí),當(dāng)僅被調(diào)用了一個(gè)屬性,一個(gè)明智的做法是將這個(gè)Bean聲明為內(nèi)部Bean。內(nèi)部Bean可以用setter注入“屬性”和用構(gòu)造方法注入“構(gòu)造參數(shù)”的方式來(lái)實(shí)現(xiàn)。

比如,在我們的應(yīng)用程序中,一個(gè)Customer類引用了一個(gè)Person類,我們要做的是創(chuàng)建一個(gè)Person的實(shí)例,然后在Customer內(nèi)部使用。

public class Customer{

  private Person person;

}

public class Person{

  private String name;

  private String address;

  private int age;

}

內(nèi)部Bean的聲明方式如下:

<bean id="CustomerBean" class="com.gupaoedu.common.Customer">

  <property name="person">

   <bean class="com.gupaoedu.common.Person">

          <property name="name" value="lokesh" />

      <property name="address" value="India" />

      <property name="age" value="34" />

   </bean>

  </property>

</bean>

13 Spring框架中的單例Bean是線程安全的嗎?

Spring框架并沒(méi)有對(duì)單例Bean進(jìn)行任何多線程的封裝處理。關(guān)于單例Bean的線程安全和并發(fā)問(wèn)題需要開(kāi)發(fā)者自行搞定。但實(shí)際上,大部分Spring Bean并沒(méi)有可變的狀態(tài)(比如Serview類和DAO類),所以在某種程度上說(shuō),Spring的單例Bean是線程安全的。如果你的Bean有多種狀態(tài)(比如View Model對(duì)象),就需要自行保證線程安全。

最淺顯的解決辦法就是將多態(tài)Bean的作用域由“singleton”變更為“prototype”。

14 請(qǐng)舉例說(shuō)明如何在Spring中注入一個(gè)Java集合?

Spring提供了以下四種集合類的配置元素:

(1)<list>標(biāo)簽用來(lái)裝配可重復(fù)的list值。

(2)<set>標(biāo)簽用來(lái)裝配沒(méi)有重復(fù)的set值。

(3)<map>標(biāo)簽可用來(lái)注入鍵和值,可以為任何類型的鍵值對(duì)。

(4)<props>標(biāo)簽支持注入鍵和值都是字符串類型的鍵值對(duì)。

下面看一下具體的例子:

<beans>

  <bean id="javaCollection" class="com.gupaoedu.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@gupaoedu.com</prop>

      <prop key="support">support@gupaoedu.com</prop>

     </props>

   </property>

  </bean>

</beans>

15 如何向Spring Bean中注入java.util.Properties?

第一種方法是使用如下面代碼所示的標(biāo)簽:

<bean id="adminUser" class="com.gupaoedu.common.Customer">

  <property name="emails">

   <props>

     <prop key="admin">admin@gupaoedu.com</prop>

     <prop key="support">support@gupaoedu.com</prop>

   </props>

  </property>

</bean>

也可用“util:”命名空間來(lái)從properties文件中創(chuàng)建一個(gè)propertiesbean,然后利用setter方法注入Bean的引用。

16 請(qǐng)解釋Spring Bean的自動(dòng)裝配?

在Spring框架中,在配置文件中設(shè)定Bean的依賴關(guān)系是一個(gè)很好的機(jī)制,Spring容器還可以自動(dòng)裝配合作關(guān)系Bean之間的關(guān)聯(lián)關(guān)系。這意味著Spring可以通過(guò)向Bean Factory中注入的方式自動(dòng)搞定Bean之間的依賴關(guān)系。自動(dòng)裝配可以設(shè)置在每個(gè)Bean上,也可以設(shè)定在特定的Bean上。

下面的XML配置文件表明了如何根據(jù)名稱將一個(gè)Bean設(shè)置為自動(dòng)裝配:

<bean id="employeeDAO" class="com.gupaoedu.EmployeeDAOImpl" autowire="byName" />

除了Bean配置文件中提供的自動(dòng)裝配模式,還可以使用@Autowired注解來(lái)自動(dòng)裝配指定的Bean。在使用@Autowired注解之前需要按照如下的配置方式在Spring配置文件中進(jìn)行配置。

<context:annotation-config />

也可以通過(guò)在配置文件中配置AutowiredAnnotationBeanPostProcessor 達(dá)到相同的效果。

<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

配置好以后就可以使用@Autowired來(lái)標(biāo)注了。

@Autowired

public EmployeeDAOImpl ( EmployeeManager manager ) {

   this.manager = manager;

}

17 自動(dòng)裝配有哪些局限性?

自動(dòng)裝配有如下局限性。

  • 重寫(xiě):你仍然需要使用和< property>設(shè)置指明依賴,這意味著總要重寫(xiě)自動(dòng)裝配。
  • 原生數(shù)據(jù)類型:你不能自動(dòng)裝配簡(jiǎn)單的屬性,如原生類型、字符串和類。
  • 模糊特性:自動(dòng)裝配總是沒(méi)有自定義裝配精確,因此如果可能盡量使用自定義裝配。

18 請(qǐng)解釋各種自動(dòng)裝配模式的區(qū)別?

在Spring框架中共有5種自動(dòng)裝配,讓我們逐一分析。

(1)no:這是Spring框架的默認(rèn)設(shè)置,在該設(shè)置下自動(dòng)裝配是關(guān)閉的,開(kāi)發(fā)者需要自行在Bean定義中用標(biāo)簽明確地設(shè)置依賴關(guān)系。

(2)byName:該選項(xiàng)可以根據(jù)Bean名稱設(shè)置依賴關(guān)系。當(dāng)向一個(gè)Bean中自動(dòng)裝配一個(gè)屬性時(shí),容器將根據(jù)Bean的名稱自動(dòng)在配置文件中查詢一個(gè)匹配的Bean。如果找到就裝配這個(gè)屬性,如果沒(méi)找到就報(bào)錯(cuò)。

(3)byType:該選項(xiàng)可以根據(jù)Bean類型設(shè)置依賴關(guān)系。當(dāng)向一個(gè)Bean中自動(dòng)裝配一個(gè)屬性時(shí),容器將根據(jù)Bean的類型自動(dòng)在配置文件中查詢一個(gè)匹配的Bean。如果找到就裝配這個(gè)屬性,如果沒(méi)找到就報(bào)錯(cuò)。

(4)constructor:它的自動(dòng)裝配和byType模式類似,但是僅適用于有與構(gòu)造器相同參數(shù)的Bean,如果在容器中沒(méi)有找到與構(gòu)造器參數(shù)類型一致的Bean,那么將會(huì)拋出異常。

(5)autodetect:該模式自動(dòng)探測(cè)使用構(gòu)造器自動(dòng)裝配或者byType自動(dòng)裝配。首先會(huì)嘗試找合適的帶參數(shù)的構(gòu)造器,如果找到就是用構(gòu)造器自動(dòng)裝配,如果在Bean內(nèi)部沒(méi)有找到相應(yīng)的構(gòu)造器或者是無(wú)參構(gòu)造器,容器就會(huì)自動(dòng)選擇byTpe的自動(dòng)裝配方式。

19 請(qǐng)舉例解釋@Required Annotation?

在產(chǎn)品級(jí)別的應(yīng)用中,IOC容器可能聲明了數(shù)十萬(wàn)了Bean,Bean與Bean之間有著復(fù)雜的依賴關(guān)系。設(shè)值注解方法的短板之一就是驗(yàn)證所有的屬性是否被注解是一項(xiàng)十分困難的操作??梢酝ㄟ^(guò)設(shè)置“dependency-check”來(lái)解決這個(gè)問(wèn)題。

在應(yīng)用程序的生命周期中,你可能不大愿意花時(shí)間驗(yàn)證所有Bean的屬性是否按照上下文文件正確配置?;蛘吣銓幙沈?yàn)證某個(gè)Bean的特定屬性是否被正確設(shè)置。即使用“dependency-check”屬性也不能很好地解決這個(gè)問(wèn)題,在這種情況下你需要使用@Required 注解。

需要用如下的方式使用來(lái)標(biāo)明Bean的設(shè)值方法。

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中的后置處理器,用來(lái)驗(yàn)證被@Required 注解的Bean屬性是否被正確設(shè)置了。在使用RequiredAnnotationBeanPostProcesso驗(yàn)證Bean屬性之前,要在IOC容器中對(duì)其進(jìn)行注冊(cè):

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />

但是如果沒(méi)有屬性被用@Required注解過(guò),后置處理器會(huì)拋出一個(gè)BeanInitializationException異常。

20 請(qǐng)舉例說(shuō)明@Qualifier注解?

@Qualifier注解意味著可以在被標(biāo)注Bean的字段上自動(dòng)裝配。Qualifier注解可以用來(lái)取消Spring不能取消的Bean應(yīng)用。

21 構(gòu)造方法注入和設(shè)值注入有什么區(qū)別?

請(qǐng)注意以下明顯的區(qū)別:

(1)設(shè)值注入方法支持大部分的依賴注入,如果我們僅需要注入int、string和long型的變量,不要用設(shè)值的方法注入。對(duì)于基本類型,如果我們沒(méi)有注入,可以為基本類型設(shè)置默認(rèn)值。構(gòu)造方法注入不支持大部分依賴注入,因?yàn)樵谡{(diào)用構(gòu)造方法時(shí)必須傳入正確的構(gòu)造參數(shù),否則會(huì)報(bào)錯(cuò)。

(2)設(shè)值注入不會(huì)重寫(xiě)構(gòu)造方法的值。如果我們對(duì)同一個(gè)變量同時(shí)使用了構(gòu)造方法注入和設(shè)值方法注入,那么構(gòu)造方法將不能覆蓋由設(shè)值方法注入的值。很明顯,因?yàn)闃?gòu)造方法只在對(duì)象被創(chuàng)建時(shí)調(diào)用。

(3)在使用設(shè)值注入時(shí)有可能還不能保證某種依賴是否已經(jīng)被注入,也就是說(shuō),這時(shí)對(duì)象的依賴關(guān)系有可能是不完整的。而在另一種情況下,構(gòu)造器注入則不允許生成依賴關(guān)系不完整的對(duì)象。

(4)在設(shè)值注入時(shí)如果對(duì)象A和對(duì)象B互相依賴,在創(chuàng)建對(duì)象A時(shí)Spring會(huì)拋出sObjectCurrentlyInCreationException異常,因?yàn)樵趯?duì)象B被創(chuàng)建之前對(duì)象A是不能被創(chuàng)建的,反之亦然。Spring用設(shè)值注入的方法解決了循環(huán)依賴的問(wèn)題,因?yàn)閷?duì)象的設(shè)值方法是在對(duì)象被創(chuàng)建之前被調(diào)用的。

22 Spring框架中有哪些不同類型的事件?

Spring的ApplicationContext 提供了支持事件和代碼中監(jiān)聽(tīng)器的功能。

我們可以創(chuàng)建Bean來(lái)監(jiān)聽(tīng)在ApplicationContext 中發(fā)布的事件。ApplicationEvent類和在ApplicationContext接口中處理的事件,如果一個(gè)Bean實(shí)現(xiàn)了ApplicationListener接口,當(dāng)一個(gè)ApplicationEvent 被發(fā)布以后,Bean會(huì)自動(dòng)被通知。

public class AllApplicationEventListener implements ApplicationListener<ApplicationEvent> {

  @Override

  public void onApplicationEvent(ApplicationEvent applicationEvent) {

   //process event

  }

}

Spring 提供了以下5種標(biāo)準(zhǔn)的事件:

(1)上下文更新事件(ContextRefreshedEvent):該事件會(huì)在ApplicationContext被初始化或者更新時(shí)發(fā)布。也可以在調(diào)用ConfigurableApplicationContext 接口中的refresh()方法時(shí)被觸發(fā)。

(2)上下文開(kāi)始事件(ContextStartedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開(kāi)始/重新開(kāi)始容器時(shí)觸發(fā)該事件。

(3)上下文停止事件(ContextStoppedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時(shí)觸發(fā)該事件。

(4)上下文關(guān)閉事件(ContextClosedEvent):當(dāng)ApplicationContext被關(guān)閉時(shí)觸發(fā)該事件。容器被關(guān)閉時(shí),其管理的所有單例Bean都被銷毀。

(5)請(qǐng)求處理事件(RequestHandledEvent):在Web應(yīng)用中,當(dāng)一個(gè)HTTP請(qǐng)求(Request)結(jié)束時(shí)觸發(fā)該事件。

除了上面介紹的事件,還可以通過(guò)擴(kuò)展ApplicationEvent 類來(lái)開(kāi)發(fā)自定義的事件。

public class CustomApplicationEvent extends ApplicationEvent {

  public CustomApplicationEvent ( Object source, final String msg ){

   super(source);

   System.out.println("Created a Custom event");

  }

}

為了監(jiān)聽(tīng)這個(gè)事件,還需要?jiǎng)?chuàng)建一個(gè)監(jiān)聽(tīng)器:

public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >{

  @Override

  public void onApplicationEvent(CustomApplicationEvent applicationEvent) {

  }

}

之后通過(guò)applicationContext接口的publishEvent()方法來(lái)發(fā)布自定義事件:

CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, “Test message”);

applicationContext.publishEvent(customEvent);

23 FileSystemResource和ClassPathResource有何區(qū)別?

在FileSystemResource 中需要給出spring-config.xml文件在項(xiàng)目中的相對(duì)路徑或者絕對(duì)路徑。在ClassPathResource中Spring會(huì)在ClassPath中自動(dòng)搜尋配置文件,所以要把ClassPathResource 文件放在ClassPath下。

如果將spring-config.xml保存在了src文件夾下,只需給出配置文件的名稱即可,因?yàn)閟rc文件夾是默認(rèn)的。

簡(jiǎn)而言之,ClassPathResource在環(huán)境變量中讀取配置文件,F(xiàn)ileSystemResource在配置文件中讀取配置文件。

24 Spring 框架中都用到了哪些設(shè)計(jì)模式?

Spring框架中使用了大量的設(shè)計(jì)模式,下面列舉了比較有代表性的:

(1)代理模式:在AOP和remoting中被用得比較多。

(2)單例模式:在Spring配置文件中定義的Bean默認(rèn)為單例模式。

(3)模板模式:用來(lái)解決代碼重復(fù)的問(wèn)題。比如RestTemplate、JmsTemplate、JpaTemplate。

(4)委派模式:Srping提供了DispatcherServlet來(lái)對(duì)請(qǐng)求進(jìn)行分發(fā)。

(5)工廠模式:BeanFactory用來(lái)創(chuàng)建對(duì)象的實(shí)例,貫穿于BeanFactory / ApplicationContext接口的核心理念。

(6)代理模式:AOP思想的底層實(shí)現(xiàn)技術(shù),Spring中采用JDK Proxy和CgLib類庫(kù)。

25 在Spring框架中如何更有效地使用JDBC?

使用Spring JDBC框架,資源管理及錯(cuò)誤處理的代價(jià)都會(huì)減輕。開(kāi)發(fā)人員只需通過(guò)statements和queries語(yǔ)句從數(shù)據(jù)庫(kù)中存取數(shù)據(jù)。Spring通過(guò)使用模板類能更有效地使用JDBC,也就是所謂的JdbcTemplate。

26 請(qǐng)解釋下Spring框架中的IOC容器

Spring中的org.springframework.beans包和org.springframework.context包構(gòu)成了Spring框架IOC容器的基礎(chǔ)。

BeanFactory接口提供了一個(gè)先進(jìn)的配置機(jī)制,使得任何類型的對(duì)象的配置都成為可能。ApplicationContex接口對(duì)BeanFactory(是一個(gè)子接口)進(jìn)行了擴(kuò)展,在BeanFactory的基礎(chǔ)上添加了其他功能,比如與Spring的AOP更容易集成,也提供了處理Message Resource的機(jī)制(用于國(guó)際化)、事件傳播及應(yīng)用層的特別配置,比如針對(duì)Web應(yīng)用的WebApplicationContext。

27 在Spring中可以注入null或空字符串嗎?

完全可以。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring概述(10) 什么是spring? Spring是一個(gè)輕量級(jí)Java開(kāi)發(fā)框架,最早有Rod Johns...
    老pao說(shuō)Java閱讀 839評(píng)論 0 1
  • 前言 作為應(yīng)屆生,處于找工作中。今年2月份剛剛整理出來(lái)的Spring面試題,時(shí)間比較趕就沒(méi)有按照Spring的模塊...
    一個(gè)巨大的怪獸閱讀 24,476評(píng)論 0 15
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來(lái)的情緒。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了,難過(guò)就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,841評(píng)論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn),也就放棄了無(wú)數(shù)的可能。 ...
    yichen大刀閱讀 8,097評(píng)論 0 4

友情鏈接更多精彩內(nèi)容