Spring5新特性

Spring5新特性簡述

Spring5兼容Java 8和JDK 9,集成了反應式流,以方便后續提供一種顛覆性方法來實現端點和Web應用程序開發。
反應式編程不僅是此版本的主題,還是令許多程序員激動不已的重大特性。人們對能夠針對負載 波動進行無縫擴展的容災和響應式服務的需求在不斷增加,Spring 5 很好地滿足了這一需求。本文將介紹Java SE8和Java EE 7 API升級的
基本內容、Spring 5的新反應式編程模型、對HTTP/2支持,以及Spring通過Kotlin對函數式編程的全面支持。以及會介紹測試及性能增強和Spring 核心和容器的一些修訂。

升級到Java SE 8 和 Java EE 7

以前的 Spring Framework 中一直在支持一些棄用的 Java 版本,而 Spring 5 已從舊包袱中解放出 來。為了充分利用 Java 8 特性,它的代碼庫已進行了改進,而且該框架要求將 Java 8 作為最低的 JDK 版本。
在 API 級別上,Spring 5 兼容 Java EE 8 技術,滿足對 Servlet 4.0、Bean Validation 2.0 和全新 的 JSON Binding API 的需求。對 Java EE API 的最低要求為 V7,該版本引入了針對 Servlet、JPA 和 Bean Validation API 的次要版本。

反應式編程模型

Spring 5 最令人興奮的新特性是它的反應式編程模型。Spring 5 Framework 基于一種反應式基礎而構建,而且是完全異步和非阻塞的。只需少量的線程,新的事件循環執行模型就可以垂直擴展。
該框架采用反應式流來提供在反應式組件中傳播負壓的機制。負壓是一個確保來自多個生產者的數據不會讓使用者不堪重負的概念。
Spring WebFlux 是 Spring 5 的反應式核心,它為開發人員提供了兩種為 Spring Web 編程而設計 的編程模型:一種基于注解的模型和 Functional Web Framework (WebFlux.fn)。
基于注解的模型是 Spring WebMVC 的現代替代方案,該模型基于反應式基礎而構建,而 Functional Web Framework 是基于 @Controller 注解的編程模型的替代方案。這些模型都通過同一種反應式基 礎來運行,后者調整非阻塞 HTTP 來適應反應式流 API。

使用注解進行編程

Web MVC 程序員應該對 Spring 5 的基于注解的編程模型非常熟悉。Spring 5 調整了 Web MVC 的 @Controller 編程模型,采用了相同的注解。
在下面的代碼中 BookController 類提供了兩個方法,分別響應針對某個圖書列表的 HTTP 請求,以及針對具有給定 id 的圖書的 HTTP 請求。請注意 resource 方法返回的對象(Mono 和 Flux)。這些對象是實現反應式流規范中的 Publisher 接口的反應式類型。它們的職責是處理數據流。Mono 對象處理一個僅含 1 個元素的流,而 Flux 表示一個包含 N 個元素的流。

@RestController
public class BookController{
  @GetMapping("/book")
  Flux<Book> list(){
    return this.repository.findAll();
  }

  @GetMapping("/book/{id}") 
  Mono<Book> findById(@PathVariable String id) { 
    return this.repository.findOne(id);
  }
}

這是針對 Spring Web 編程的注解。現在我們使用函數式 Web 框架來解決同一個問題。

支持函數式編程

Spring 5 的新函數式方法將請求委托給處理函數,這些函數接受一個服務器請求實例并返回一種反應式類型。下面BookHandler 類,其中 listBook() 和 getBook() 方法相當于 Controller 中的功能:

public class BookHandler{
 public Mono<ServerResponse> listBooks(
   ServerRequest request) { 
     return ServerResponse.ok() 
                 .contentType(APPLICATION_JSON) 
                 .body(repository.allPeople(), Book.class);
    }

   public Mono<ServerResponse> getBook(ServerRequest request) { 
     return repository.getBook(request.pathVariable("id"))
               .then(book ->ServerResponse.ok()
               .contentType(APPLICATION_JSON)
               .body(fromObject(book)))               
               .otherwiseIfEmpty(ServerResponse.notFound().build())
}

通過路由函數來匹配 HTTP 請求參數與媒體類型,將客戶端請求路由到處理函數。

Bookhandler handler = new BookHndler();
RouterFunction<ServerResponse> personRoute = 
      route(
              GET("/books/{id}")
                    .and(accept(APPLICATION_JSON)), handler::getBook)
              .andRoute(
                     GET("/books")
                           .and(accept(APPLICATION_JSON)), handler::listBooks);

使用REST端點執行反應式編程
WebFlux模塊為RestTemplate提供四種完全非阻塞、反應式的替代方案,名為WebClient。下面創建一個 WebClient,并調用 books 端點來請求一本給定 id 為 1234 的圖書。 通過 WebClient 調用 REST 端點:

Mone<Book> book = WebClient.create("http://loclahost:8080")
                                .get()
                                .url("/book/{id}", 1234)
                                .accept(APPLICATION_JSON)
                                .exchange(request)
                                .then(response -> response.bodyToMono(Book.class));

對HTTP/2支持
HTTP/2原理:Spring Framework 5.0 提供專門的 HTTP/2 特性支持,還支持人們期望出現在 JDK 9 中的新 HTTP 客戶端。
Kotlin和Spring WenFlux
Kotlin 是一種來自 JetBrains 的面向對象的語言,它支持函數式編程。它的主要優勢之一是與 Java 有 非常高的互操作性。
Kotlin 的用于定義端點的路由 DSL:

@Bean
fun apiRouter() = router {
    (accept(APPLICATION_JSON) and "/api").nest {
        "/book".nest {
            GET("/", bookHandler::findAll) 
            GET("/{id}", bookHandler::findOne)
        }
        "/video".nest {
            GET("/", videoHandler::findAll)
            GET("/{genre}", videoHandler::findByGenre)
        }
    }
}

使用Lambda表達式注冊Bean
作為傳統 XML 和 JavaConfig 的替代方案,現在可以使用 lambda 表達式注冊 Spring bean,使 bean 可以實際注冊為提供者。下面代碼中使用 lambda 表達式注冊了一個 Book bean。

GenericApplicationContext context = new GenericApplicationContext();
    context.registerBean(Book.class,  ()-> new     Book(context.getBean(Auther.class))
);

Spring Web Mvc支持最新的API
使用JUnit5執行條件和并發測試
JUnit 和 Spring 5:Spring 5 全面接納了函數式范例,并支持 JUnit 5 及其新的函數式測試風格。還 提供了對 JUnit 4 的向后兼容性,以確保不會破壞舊代碼。
Spring 5 的測試套件通過多種方式得到了增強,但最明顯的是它對 JUnit 5 的支持。JUnit 5 全面接納了 Java 8 流和 lambda 表達式:

@Test
void givenStreamOfInts_SumShouldBeMoreThanFive(){
    assertTure(Stream.of(20, 40, 50)
      .stream()
      .mapToInt(i -> i)
      .sum() > 110, () -> "Total shoule be more than 100"
    );
}

Spring 5 繼承了 JUnit 5 在 Spring TestContext Framework 內實現多個擴展 API 的靈活性。舉例而言,開發人員可以使用 JUnit 5 的條件測試執行注解 @EnabledIf 和 @DisabledIf 來自動計算一 個 SpEL (Spring Expression Language) 表達式,并適當地啟用或禁用測試。借助這些注解,Spring 5 支持以前很難實現的復雜的條件測試方案。Spring TextContext Framework 現在能夠并發執行測試。

Spring中經典的高頻面試題

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

Spring 框架是一個為 Java 應用程序的開發提供了綜合、廣泛的基礎性支持的 Java 平臺。Spring 幫助 開發者解決了開發中基礎性的問題,使得開發人員可以專注于應用程序的開發,不必擔心 Spring 是如何 在后臺進行工作的。
Spring 框架至今已集成了 20 多個模塊。這些模塊主要被分核心容器、數據訪問/集成,、 Web、AOP(面向切面編程)、工具、消息和測試模塊。

2、使用 Spring 框架能帶來哪些好處?

1、Dependency Injection(DI) 方法使得構造器和 JavaBean properties 文件中的依賴關系一目了然。
2、與 EJB 容器相比較,IOC 容器更加趨向于輕量級。這樣一來 IOC 容器在有限的內存和 CPU 資源的情況下進行應用程序的開發和發布就變得十分有利。
3、Spring 框架是按照模塊的形式來組織的。由包和類的編號就可以看出其所屬的模塊,開發者僅僅需要選用他們需要的模塊即可。
4、要測試一項用 Spring 開發的應用程序十分簡單,因為測試相關的環境代碼都已經囊括在框架中了。
5、Spring 提供了一個便捷的事務管理接口,適用于小型的本地事務處理(比如在單 DB 的環境下)和 復雜的共同事務處理(比如利用 JTA 的復雜 DB 環境)。

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

在傳統的編程方式中,業務邏輯的流程是由應用程序中的早已設定好關聯關系的對象來決定的。在使用控制反轉的情況下,業務邏輯的流程是由對象關系圖來決定 的,該對象關系圖由裝配器負責實例化。而依賴注入是在編譯階段,還不知道所需的功能來自哪個類的情況下,將其他對象所依賴的功能對象實例化的模式。

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

1.構造器注入
2.Setter 方法注入
3.接口注入

5、BeanFactory 和 ApplicationContext 有什么區別?

BeanFactory 可以理解為含有 bean 集合的工廠類。包含個種 bean 的定義,以便在接收到客戶端請求時將對應的 bean 實例化。BeanFactory還能子在實例化對象的時候生成協作類之間的關系。將bean自己與bean客戶端的配置中釋放出來。BeanFactory還包含了bean生命周期的控制,調用客戶端的初始化(initlization Methods)和銷毀方法(destribution Methods)。
從表面上看,ApplicationContext和beanFactory一樣具有bean定義,bean關聯關系的設置,請求分發bean的功能,但applicationContext在此基礎上還提供:
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 的配置 :使用xml文件標簽化配置Bean的相關信息
引入pom及bean配置xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean id="service" class="com.wyh.spring.core.ServiceImpl"
          init-method="hello">
    </bean>
</beans>

使用XmlBeanFactory創建對象:

public class BeanFactoryDemo {
    public static void main(String[] args) {
        XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
        IService service = (IService) xmlBeanFactory.getBean("service");
        String hello = service.hello();
        System.out.println(hello);
    }
}

2.基于注解的配置
@Component 標識了一個被Spring管理的對象
@Respository 標識持久層對象
@Service 標識業務層對象
@Controller 標識表現層對象
3.基于 Java 的配置
使用configuration配置bean

@Configuration
public class Configuration {
    @Bean
    public User user() {
        return new User();
    }
}

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

在 Spring 框架中,依賴和服務需要在專門的配置文件來實現,我常用的是 XML 格式的配置文件。這些配置文件有一個通用的格式頭,然后是一系列的bean定義和專門的應用配置選項組成。
Spring 的 XML 配置方式是使用被 Spring 命名空間的所支持的一系列的 XML 標簽來實現的。比如::context、beans、jdbc、tx、aop、mvc 和 aso。

8、Spring 提供哪些配置形式?

Spring 對 Java 配置的支持是由@Configuration 注解和@Bean 注解來實現的。
@Bean 注解的方法將會實例化、配置和初始化一個新對象,由 Spring 的 IOC 容器來管理。@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.tc") 
public class AppConfig { 
}

在上面的例子中,com.tc包首先會被掃到,然后再容器內查找被@Component 聲明的類, 找到后將這些類按照 Spring bean 定義進行注冊。

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

Spring 在 2.5 版本以后開始支持用注解的方式來配置依賴注入。可以用注解的方式來替代 XML 方式的 bean 描述,可以將 bean 描述轉移到組件類的內部,只需要在相關類上、方法上或者字段聲明上使用注解即可。。注解注入將會被容器在 XML 注入之前被處理,所以后者會覆蓋掉前者對于同一個屬性的處理結果。
注解裝配在Spring 中是默認關閉的。所以需要在Spring文件中配置一下才能使用基于注解的裝配模式。
下面是幾種比較重要的注解類型:
1.@Required:該注解應用于設值方法。
2.@Autowired:該注解應用于有值設值方法、非設值方法、構造方法和變量。 3.@Qualifier:該注解和@Autowired 注解搭配使用,用于消除特定 bean 自動裝配的歧義。
4.JSR-250 Annotations:Spring 支持基于 JSR-250 注解的以下注解,@Resource、@PostConstruct 和 @PreDestroy

10、請解釋 Spring Bean 的生命周期?

在一個 bean 實例被初始化時,需要執行一系列的初始化操作以達 到可用的狀態。同樣的,當一個 bean 不在被調用時需要進行相關的析構操作,并從 bean 容器中移除。
Spring bean factory 負責管理在 spring 容器中被創建的 bean 的生命周期。Bean 的生命周期由兩組 回調(call back)方法組成。
1.初始化之后調用的回調方法。
2.銷毀之前調用的回調方法
Spring 框架提供了以下四種方式來管理 bean 的生命周期事件:
1、InitializingBean 和 DisposableBean 回調接口
2、針對特殊行為的其他 Aware 接口
3、Bean 配置文件中的 customInit()方法和 destroy()方法
4、@PostConstruct 和@PreDestroy 注解方式

11、Spring Bean 作用域之間的區別?

1、singleton:這種 bean 范圍是默認的,這種范圍確保不管接受到多少個請求,每個Ioc容器中只有一個 bean 的實例,單例的模式由 bean factory 自身來維護。(創建起容器時就同時自動創建了一個bean的對象,不管你是否使用,他都存在了,每次獲取到的對象都是同一個對象)
2、prototype:原形范圍與單例范圍相反,每次對該bean請求(將其注入到另一個bean中,或者調用容器的getBean()方法)時都會創建一個新的bean實例。它在我們創建容器的時候并沒有實例化,而是當我們獲取bean的時候才會去創建一個對象,而且我們每次獲取到的對象都不是同一個對象。
:對有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用singleton作用域。
3、request:在請求 bean 范圍內,每一個HTTP請求創建一個全新的實例,該實例僅在當前request內有效,可以根據需求更改實例的狀態而其他請求看不到。在請求完成以后,bean 會失效并被垃圾回收器回收
4、Session:與請求范圍類似,確保每個HTTP Session 中有一個 bean 的實例,僅在當前HTTP Session中有效。在 Session 過期后,bean 會 隨之失效。
5、global-session:global-session 和 Portlet 應用相關,它僅僅在基于portlet的web應用中才有意義。當你的應用部署在 Portlet 容器中工作時,它包含很多 portlet。如果你想要聲明讓所有的 portlet 共用全局的存儲變量的話,那么這全局變量需要存儲在 global-session 中。(Portlet是基于Java的Web組件,由Portlet容器管理,并由容器處理請求,生產動態內容)
自定義作用域:
1、首先需要實現自定義Scope類:接口中有兩個常用的方法,分別用于底層存儲機制獲取和刪除這個對象。
2、r使用registerScope方法在Spring容器中來注冊新的作用域:
void registerScope(String scopeName, Scope scope);
比如實現Scope接口的類為SimpleThreadScope,要實現的自定義的bean的作用域的名稱為“thread”,那就可以這么寫:

Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);

3.在實現和注冊自定義的scope類之后,就可以通過如下類似的Bean定義來使用自定義的Scope:

  <bean id="..." class="..." scope="thread">

12、什么是 Spring inner beans?

正如Java 內部類是在其他類的范圍內被定義的,同理,inner beans 是在其他 bean 的范圍內定義的 bean。因此在 bean元素內元素被稱為內部bean。

13、Spring 框架中的單例 Beans 是線程安全的么?

Spring 框架并沒有對單例 bean 進行任何多線程的封裝處理。關于單例 bean 的線程安全和并發問題需 要開發者自行去搞定。但實際上,大部分的 Spring bean 并沒有可變的狀態(比如 Service 類和 DAO類),所以在某種程度上說 Spring 的單例 bean 是線程安全的。如果你的 bean 有多種狀態的話(比如 View Model 對象),就需要自行保證線程安全。
最淺顯的解決辦法就是將多態 bean 的作用域由“singleton”變更為“prototype”。

14、請舉例說明如何在 Spring 中注入一個 Java 集合?

Spring 提供了以下四種集合類的配置元素:
1、 list: 該標簽用來裝配可重復的 list 值。

<property name="customList"> 
  <list>
    <value>INDIA</value>
    <value>Pakistan</value>
    <value>USA</value>
  </list>
</property>

2、 set: 該標簽用來裝配沒有重復的 set 值。

<property name="customSet">
  <set>
    <value>INDIA</value>
    <value>USA</value>
    <value>UK</value>
  </set>
</property>

3、map: 該標簽可用來注入鍵和值可以為任何類型的鍵值對。

<property name="customMap">
  <map>
    <entry key="1" value="INDIA"/>
    <entry key="3" value="USA"/>
    <entry key="4" value="UK"/>
  </map>
</property>

4、 props: 該標簽支持注入鍵和值都是字符串類型的鍵值對。

<property name="customProperies">
  <props>
    <prop key="admin">admin@gupaoedu.com</prop> 
    <prop key="support">support@gupaoedu.com</prop>
  </props>
</property>

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

第一種:

<property name="emails">
  <props>
    <prop key="admin">admin@gupaoedu.com</prop>
    <prop key="support">support@gupaoedu.com</prop>
  </props>
</property>

第二種:可用”util:”命名空間來從 properties 文件中創建出一個 properties bean,然后利用 setter 方法注 入 bean 的引用。

16、請解釋 Spring Bean 的自動裝配?

Spring利用依賴注入(DI),完成對IOC容器中中各個組件的依賴關系賦值;
在Spring框架中,在配置文件中可以設定bean的依賴關系,還可以自動裝配bean之間的關聯關系。這意味著 Spring 可以以向 Bean Factory 中注入的方式自動搞定 bean 之間的依賴關系。自動裝配可以設置在每個 bean 上,也可以設定在特定的 bean 上。
三種形式:
1:xml配置文件來將一個bean設置為自動裝配:

<bean id="employeeDao" class="com.tc.xxx" autowird="byName" />

2:使用Autowired注解來自動裝配指定的bean,使用之前,在配置文件進行相關配置:

<context:annotation-config>

也可以通過配置AutowiredAnnotationBeanPostProcessor:

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

它實現了BeanPostProcessor前置類在postProcessBeforeInitialization方法里調用invokeAwareInterfaces進行設置IOC容器。
配置好后,使用Autowired來標注:

@Autowired 
public EmployeeDAOImpl ( EmployeeManager manager ) { 
  this.manager = manager;
}

17、自動裝配有哪些局限性?

自動裝配有如下局限性:

  • 重寫:你仍然需要使用propertyconstructor-arg設置中的依賴,意味著總是要重寫自動裝配。
  • 原生數據類型:你不能自動裝配簡單的屬性,如原生類型int,long、字符串和類。
  • 模糊特性:自動裝配總是沒有自定義裝配或者直接裝配(explicit wiring)精確,因此,如果可能盡量使用自定義裝配。

18、各種自動裝配模式的區別?

在 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 的自動裝配方式。

19、請舉例解釋@Required Annotation?

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 屬性是否被正確的設置了。 屬性是否被正確的設置了。在使用 RequiredAnnotationBeanPostProcessor 來驗證 bean 屬性之 前,首先要在 IOC 容器中對其進行注冊:

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

但是如果沒有屬性被用 @Required 注解過的話,后置處理器會拋出一個 BeanInitializationException 異常。

20、請舉例說明@Qualifier 注解?

@Qualifier注解意味著在被標注的bean的字段上可以自動裝配。
Qualifier注解可以用來取消Spring不能取消的 bean 應用。解和@Autowired 注解搭配使用,用于消除特定 bean 自動裝配的歧義。

21、構造方法注入和設值注入有什么區別?

1.設值注入方法支持大部分的依賴注入,如果我們僅需要注入 int、string 和 long 型的變量,我們不要用設值的方法注入。因為對于基本類型,如果我們沒有注入的話,可以為基本類型設置默認值。而構造方法注入不支持大部分的依賴注入,因為在調用構造方法中必須傳入正確的構造參數,否則的話為報錯。
2.設值注入不會重寫構造方法的值。如果我們對同一個變量同時使用了構造方法注入又使用了設置方法 注入的話,那么構造方法將不能覆蓋由設值方法注入的值。很明顯,因為構造方法是在對象被創建時調用。
3.在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時對象的依賴關系有可能 是不完整的。而在另一種情況下,構造器注入則不允許生成依賴關系不完整的對象。
4.在 構造 注 入 時 如 果 對 象 A 和 對 象 B 互 相 依 賴 , 在 創 建 對 象 A 時 Spring 會 拋 出 sObjectCurrentlyInCreationException 異常,因為在 B 對象被創建之前 A 對象還沒有被創建的,反之亦然。所以 Spring 用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在對象被創建之前 被調用的。

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

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) { 
    } 
}

之后通過 applicationContext 接口的 publishEvent()方法來發布自定義事件:

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

23、FileSystemResource 和 ClassPathResource 有何區別?

在 FileSystemResource 中需要給出 spring-config.xml 文件在你項目中的相對路徑或者絕對路徑。在 ClassPathResource 中 spring 會在 ClassPath 中自動搜尋配置文件,所以要把 ClassPathResource 文 件放在 ClassPath 下。
如果將 spring-config.xml 保存在了 src 文件夾下的話,只需給出配置文件的名稱即可,因為 src 文件 夾是默認。
簡而言之,ClassPathResource在環境變量中讀取配置文件,FileSystemResource 在配置文件中讀取配置文件。

24、Spring 框架中都用到了哪些設計模式?

Spring 框架中使用到了大量的設計模式,下面列舉了比較有代表性的:
1、代理模式—在 AOP 和 remoting 中被用的比較多。
2、單例模式:在 spring 配置文件中定義的 bean 默認為單例模式。
3、模板模式:用來解決代碼重復的問題。 比如. RestTemplate, JmsTemplate, JpaTemplate。
4、委派模式:Srping 提供了 DispatcherServlet 來對請求進行分發。
5、工廠模式:BeanFactory 用來創建對象的實例,貫穿于 BeanFactory / ApplicationContext 接口的核心理念。
代理模式:AOP 思想的底層實現技術,Spring 中采用 JDK Proxy 和 CgLib 類庫。

25、請解釋下 Spring 框架中的 IOC 容器?

Spring 中的 org.springframework.beans 包和 org.springframework.context 包構成了 Spring 框架 IOC 容器的基礎。
BeanFactory 接口提供了一個先進的配置機制 ,使得任何類型的對象的配置成為可能 。
ApplicationContex 接口對 BeanFactory(是一個子接口)進行了擴展,在 BeanFactory 的基礎上添 加了其他功能,比如與 Spring 的 AOP 更容易集成,也提供了處理 message resource 的機制(用于國 際化)、事件傳播以及應用層的特別配置,比如針對 Web 應用的 WebApplicationContext。

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

可以

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。