3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring —— IoC 容器详解

發布時間:2025/3/12 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring —— IoC 容器详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

本篇博客總結自官網的《The IoC Container》,其中會結合王富強老師的《Spring揭秘》融入自己的語言和理解,爭取通過這一篇文章徹底掃除spring IOC的盲區。

本文介紹什么是 IoC 容器,什么是 Bean,依賴,Bean Definition,Bean Factory 等概念知識。

文中會大量出現 xml 的容器配置文件,雖然由于目前 Spring Boot 項目的流行,人們已經很少使用 xml 配置,而且更喜好 Java Config 的配置,但配置只是形式的不同,其內部邏輯都是共通的!

一、什么是 Spring IoC 容器?什么是 Bean?

IoC 也可以理解為依賴注入(dependency injection)(參考《控制反轉 IOC 與依賴注入 DI》),它是一個只通過構造函數參數、工廠方法參數、或通過屬性賦值等方式去定義它們的依賴的一個過程,簡言之,就是屬性對象賦值。

【《Spring揭秘》:在Spring中,存在三種依賴注入的方式接口注入、構造器注入、setter注入

1、接口注入:要求實現某個接口才能完成依賴注入,本身帶有很強的侵入性,目前已經“退役”

2、構造方法注入:優點是對象在構造完成之后,即已進入就緒狀態,可以馬上使用。缺點是,當依賴對象比較多的時候,構造方法的參數列表會比較長。而通過反射構造對象的時候,對相同類型的參數的處理會比較困難,維護和使用上也比較麻煩。而且在Java中,構造方法無法被繼承,無法設置默認值。

3、setter方法注入:setter方法描述性更強,可以被繼承,允許設置默認值。缺點是對象無法在構造完成后馬上進入就緒狀態。

用一句話概括IOC可以給我們帶來什么?IOC是一種可以幫助我們解耦各業務對象間依賴關系的對象綁定方式。——《Spring解密》

IoC容器會在創建對象的時候注入這些依賴,這基本上是 bean 自己去控制實例化的一個反向,因此叫 Inversion of control 控制反轉。

org.springframework.beans 和 org.springframework.context 包是 Spring IoC 容器的基礎。BeanFactory 接口提供了一種高級的配置機制,使得 Spring 有能力去管理對象的類型。

ApplicationContext 是 BeanFactory 的一個子接口,它添加了一些額外的特性:

1、更簡單的 Spring AOP 特性的集成

2、信息資源處理(用于國際化)

3、事件發布

4、應用程序層面的特定上下文,例如 WebApplicationContext 之于 Web 項目。

簡而言之,BeanFactory 提供了配置框架和基本功能,ApplicationContext 加入更適合企業級特性的功能。

【《Spring揭秘》:

兩種容器類型的基本區別:

1、BeanFactory:基礎類型IOC容器。默認采用延遲初始化策略(lazy-load)(受管對象直到客戶端請求時才進行初始化及依賴注入)。容器啟動速度較快,所需資源有限。

2、ApplicationContext:繼承自BeanFactory,擁有BeanFactory的所有支持,并擴展了高級特性。該類型容器啟動后,默認對受管對象全部初始化并綁定完成容器啟動速度較慢,所需資源更多。

對容器的比喻(如何看待bean工廠的存在?):

BeanFactory就像一個汽車生產廠。你將汽車零件送入這個汽車生產廠,最后,只需要從生產線的終點取得成品汽車就可以了。】

在 Spring 中,組成應用主干并且由 Spring IoC 容器管理的對象被稱為 Bean。bean 是一個由 spring IoC 容器實例化、裝配和管理的對象。否則,bean 就是一個應用程序中許許多多對象中的一個普通一員。Bean 和它的依賴都通過IoC容器使用的配置文件來描述。

org.springframework.context.ApplicationContext 接口就代表 Spring 的 IoC 容器,它的職責就是 實例化、配置、裝配各種 bean。容器通過讀取配置文件獲得實例化、配置、裝配什么對象的指令。配置信息可以使用 xml、Java 注解、或者 Java 代碼來描述。

Spring 已經提供了一些 ApplicationContext 接口的實現。在單體應用中,通常會創建 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的實例對象。

在更多數的應用場景中,不需要顯式的用戶代碼來實例化一個或多個 Spring IoC 容器。下面的圖解展示了 Spring 是如何工作的:

二、用于描述 IoC 容器的配置信息

如前面圖解所示,spring IoC 容器需要使用一些配置信息。這些配置信息表示你將要告訴 IoC 容器如何去實例化、配置、裝配應用程序中的對象。

配置信息通常以簡單直觀的XML格式提供,本文也會以這種配置形式來講解關鍵概念和 IoC 容器的特性。

提示:xml 并不是唯一的配置形式。不同的配置形式與 Spring 框架本身完全解耦,目前,很多開發者更偏好使用基于Java? Config 的配置形式。?

1、基于注解(如@Service、@Component等)的配置,是 Spring 2.5 引入的支持以注解形式描述配置信息的一種方式。

2、基于Java 的配置,從 Spring 3.0 開始,JavaConfig 提供的許多特性已經變成 Spring Framework 的核心。這樣,你可以通過 Java 而不是 xml 文件來定義應用程序中的各種類。例如 @Configuration、@Bean、@Import 和 @DependsOn 等。

Spring 容器的配置由至少一個 bean 組成。xml 形式的配置以<bean/> 標簽來描述這些 bean 定義,并以頂級標簽<beans/> 來包裹他們。JavaConfig 形式的配置則需要在一個標記了@Configuration 的類中的 bean定義的方法上標記@Bean。

這些 bean 定義直接對應著組成你的應用程序的真正的對象。最典型的,就是定義 Service 層對象、DAO對象(data access objects),基礎設施對象如Hibernate 的 SessionFactories,JMS 的 Queues 等等。通常,并不需要配置細粒度的域對象(domain objects 即實體類對象),因為創建和加載它們通常是 DAO 和業務邏輯的職責。

下面的例子展示了 XML 結構的配置(id 屬性是?bean 的唯一標識,class 屬性以全類名定義 bean的類型。):

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="..." class="..."> <!-- 內部配置協作者和配置信息 --></bean><bean id="..." class="..."><!-- 內部配置協作者和配置信息 --></bean><!-- 更多的bean配置 --> </beans>

三、容器的應用

3.1 實例化一個容器

ApplicationContext 構造函數允許傳入配置信息的位置路徑,可以是系統路徑,也可以是項目的 classpath 下。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

提示:Spring Resource 抽象提供了一種更便捷的機制,允許從一個 URI 定位信息中以 InputStream 來讀取資源。更多描述參考:Application Contexts and Resource Paths

services.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!-- services --><bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"><property name="accountDao" ref="accountDao"/><property name="itemDao" ref="itemDao"/><!-- additional collaborators and configuration for this bean go here --></bean><!-- more bean definitions for services go here --></beans>

daos.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="accountDao"class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao"><!-- additional collaborators and configuration for this bean go here --></bean><bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao"><!-- additional collaborators and configuration for this bean go here --></bean><!-- more bean definitions for data access objects go here --></beans>

bean 的定義可以跨越多個配置文件。如上所示,services.xml 中定義的 “petStore” 依賴了 daos.xml 中定義的 “accountDao ”和 “itemDao”。通常,每個單獨的 XML? 配置文件都代表一個邏輯層或者應用架構中的一個模塊

可以使用應用程序上下文構造器來加載所有這些 xml 片段中的 bean 定義。這些構造器可接收多個 Resource 位置,如:

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

或者,使用 <import/> 來加載其他文件中的 bean 定義。例如:

<beans><import resource="services.xml"/><import resource="resources/messageSource.xml"/><import resource="/resources/themeSource.xml"/><bean id="bean1" class="..."/><bean id="bean2" class="..."/> </beans>

上例中,外部的 bean 定義會從三個文件中加載過來:services.xml、messageSource.xml、themeSource.xml。所有的位置路徑都是執行導入操作文件(以下簡稱“執行 import 文件”)的相對路徑,所以 services.xml 必須和執行 import 文件在相同的文件夾,messageSource.xml 和 themeSource.xml 必須在執行 import 文件所在路徑下的 resources 文件夾中。?如你所見,開頭的斜杠可以忽略。但是給定的路徑一定是相對路徑,所以最好的形式就是使用不帶斜杠的形式。包括頂層<beans>標簽一起都會導入進來,要求被導入的一定要是有效的 xml bean 定義文件。

提示:如果想引用一個父文件夾中的文件,使用 “../” 的形式是可以的,但并不推薦。因為這么做會創建一個相對于當前應用程序之外的文件依賴。尤其不推薦引用路徑相對于 classpath: URL(例如:classpath:../services.xml),這樣會讓運行時解析程序既要選擇“最近的” classpath 根路徑,還要去它的父路徑中檢查。類路徑配置更改可能導致選擇不同的、不正確的目錄。

你也可以使用絕對路徑,例如,file:C:/config/services.xml 或者 classpath:/config/services.xml。但是,你要知道這么做會讓你的應用程序配置和特殊的絕對路徑耦合

3.2 使用 IoC 容器(updated on 2020-10-14)

【《Spring揭秘》BeanFactory的對象注冊與依賴綁定方式:

相關接口:

BeanFactory接口定義了最基本的獲取bean的方法,包括各種方式的getBean,以及對bean的一些判斷,包括isSingletoncontainsBean

BeanDefinitionRegistry接口定義了基本的管理bean的方法,包括注冊、移除等,從名字可以看出,這個接口針對的都是BeanDefinition類型,這也是bean在容器中的信息模板對象。

DefaultListableBeanFactory類是默認的通用bean工廠,(間接)實現了前面兩個接口,具有了獲取bean和注冊bean的能力。

如何理解BeanFactory和BeanDefinitionRegistry的關系?

打個比方,BeanDefinitionRegistry就像圖書館的書架,所有的書都放在書架上,借書還書都是跟圖書館(BeanFactory)打交道,但書架才是圖書館存放書籍的地方,即:BeanDefinitionRegistry就是BeanFactory的書架

(BeanFactory只是一個接口,我們最終需要一個該接口的實現來進行實際的bean管理,DefaultListableBeanFactory就是這樣一個比較通用的BeanFactory實現類。它除了間接實現了BeanFactory接口,還實現了BeanDefinitionRegistry接口,該接口才是在BeanFactory的實現中擔當bean注冊管理的角色。

基本上,BeanFactory接口只定義如何訪問容器內管理的bean的方法,各個BeanFactory的具體實現類負責具體bean的注冊以及管理工作。BeanDefinitionRegistry接口定義抽象了bean的注冊邏輯。通常情況下,具體的BeanFactory實現類會實現這個接口來管理bean的注冊)】

ApplicationContext 是一個接口,是一個更高級的對象工廠(advanced factory),可以維護各種 bean 和它們的依賴。使用 getBean(String name, Class<T> requiredType)方法,你可以拿到你已經定義好的 bean。ApplicationContext 允許你讀取 bean 定義和訪問他們。例如:

// create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");// retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class);// use configured instance List<String> userList = service.getUsernameList();

你可以使用 getBean 來取得 bean 的實例。ApplicationContext 接口有一些其他方法來取得 bean ,但是,理想狀態下,你的應用程序代碼永遠也不應該使用這些方法。是的,你的應用程序根本不應該使用 getBean() 方法,這樣就不會耦合 Spring API。例如,Spring 集成了 web 框架,提供了各種 web 框架組件的依賴注入,例如 controller 和 JSF-managed bean,允許你通過元數據(如自動注入注解 @Autowired)來聲明一個特殊的bean。

四、Bean 概述

4.1 什么是 Bean Definition?(updated on 2020-10-14)

一個 IoC 容器管理一個或多個 bean。這些 bean 由你提供給容器的配置信息創建(例如,在 xml 中由 <bean/> 定義)。

在容器內部,這些 bean 的定義被描述為 BeanDefinition 實例(RootBeanDefinition和ChildBeanDefinition是BeanDefinition的兩個主要實現類,包含以下這些元數據(部分):

1、一個全類名。通常是定義的 bean 的實際實現類

2、Bean 的行為配置元素,聲明bean在容器中的狀態行為(作用域、生命周期回調,等等)。

3、對bean執行其工作所需的其他bean的引用。這些引用也稱為協作者或依賴項

4、其他配置,例如,池的大小限制或在管理連接池的bean中使用的連接數。

這些元數據被轉換為一系列的組成 BeanDefinition 的屬性。下表描述了這些屬性信息:

屬性名詳細描述鏈接

Class

Instantiating Beans

Name

Naming Beans

Scope

Bean Scopes

Constructor arguments

Dependency Injection

Properties

Dependency Injection

Autowiring mode

Autowiring Collaborators

Lazy initialization mode

Lazy-initialized Beans

Initialization method

Initialization Callbacks

Destruction method

Destruction Callbacks

除了 bean definition 這種包含了如何創建一個具體對象的 bean 定義之外,ApplicationContext 的實現也允許容器之外的已存在的對象注冊進來。只需要使用 ApplicationContext 的 BeanFactory——getBeanFactory() 方法。這個方法會返回 DefaultListableBeanFactory 對象,它是 BeanFactory的實現類。DefaultListableBeanFactory 中的 registerSingleton(..) 和 registerBeanDefinition(..) 方法支持這種容器外注冊操作。然而,典型的應用程序僅使用通過常規bean定義元數據定義的bean。

提示:bean 的元數據和手動提供的單例實例需要盡早注冊,這是為了容器能夠在自動裝配和其他自省步驟中正確地對它們進行推理。雖然在某種程度上支持覆蓋存在的元數據和存在的單例對象,但在運行時(并發地實時訪問工廠)注冊新的 bean不受官方支持,并可能導致并發訪問異常,或容器中 bean 的狀態不一致,或者兩者都有可能。

4.2 Bean 的命名(updated on 2020-10-14)

每個 bean 都有一個或多個標識(identifiers)。這些標識在 bean 定義的所屬容器中必須是唯一的。一個 bean 通常只有一個 標識,但是,如果它需要更多的標識,其他的可視為別名。

在 xml 配置中,你可以使用 id 屬性 和 name 屬性,或者同時使用。id 屬性代表唯一 id 。按照慣例,這些名稱是字母數字('myBean'、'someService'等),但它們也可以包含特殊字符。如果你想為這些 bean 引入其他別名,也可以指定 name 屬性,以逗號、分號 或空白字符間隔即可。但不建議指定過多的別名,這會造成一定的兼容問題。

其實你并不需要為 bean 指定 name 或 id ,容器會自動為這些 bean 生成一個唯一名稱。但是如果你想通過名稱來引用另一個 bean,可以使用 ref 或 Service Locator 風格查找,就必須為 bean 指定一個名稱。不提供名稱往往和使用內部 bean(inner bean) 和自動裝配協作者(autowiring collaborators)有關。

Bean 的命名約定

bean 命名約定遵循標準的 Java 對實例屬性名稱的命名慣例。也就是,bean 的名稱以小寫字母開頭配合駝峰命名法。例如:accountManager、accountService、userDao、loginController 等等。

一致的 bean 命名風格可以讓你的配置更容易閱讀和理解。同樣,如果你使用 Spring?AOP,這樣的命名在將通知應用到一組名稱相關的 bean 時很有幫助。

提示:通過類路徑(classpath)掃描,Spring 會為未命名的組件生成一個名字。遵從的規則就是前面的規則 :取得類名,然后把首字母變成小寫。但是如果一些特殊情況,比如,有一個以上的字符,且第一個和第二個字符都是大寫,那么會保留原始大小寫。這個規則和 java.beans.Introspector.decapitalize 的規則一致。

Java Config 配置 Bean 的名稱

?如果使用 Java Config 配置 bean,可以使用 @Bean 注解的 name 屬性,支持傳入多個別名:

public @interface Bean {@AliasFor("name")String[] value() default {};@AliasFor("value")String[] name() default {};// initMethod()、destroyMethod() ... }

如果只有一個名稱,可以像這樣配置:@Bean("accountService")。

4.3 Bean 的實例化(updated on 2020-10-14)

一個 bean 定義本質上就是一個創建一個或多個對象的“配方”(recipe,或食譜)。當被請求時,容器查看已命名bean的“配方”,并使用該 bean 定義封裝的配置元數據來創建(或獲取)實際對象。

<bean>標簽的 class 屬性表示該 bean 的類型,這個屬性是必須的。在 BeanDefinition 內部,就是 Class 屬性。你可以使用下面兩種方式其一來使用 Class 屬性。

1、大多數情況,容器通過反射調用對象的構造器來創建 bean ,class 用于指定一個構造類型,有點類似于 new 操作。

2、指定一個包含靜態工廠方法的類,這個靜態工廠方法會創建對象,這中情況不多見。從靜態工廠方法返回的對象類型,可以是本類,也可以完全是另一個類。

內部類名稱

如果你想為一個靜態內部類(static nested class)配置一個 bean,那必須使用該內部類的二進制名稱(the binary name of the nested class)?。

例如,如果你有一個類叫做 SomeThing ,包名是 com.example,而且這個 SomeThing 類有一個靜態內部類叫做 OtherThing,那么 bean 定義的 class 屬性就應該是:com.example.SomeThing$OtherThing。

注意 $ 符號的使用,它將內部類的名稱與外部類的名稱分隔開。

4.3.1 使用構造器實例化 bean

Spring 極大的兼容了這種創建 bean 的方式,也就是說,被實例化的類不需要實現任何特定的接口或以特殊的方式進行編碼。簡單地指定聲明 bean 的類型就足夠。但是,視創建指定bean 的?IOC 容器的類型而定,你可能會需要一個默認 bean 構造器。

Spring IoC容器實際上可以管理你希望它管理的任何類。而不限于 JavaBean。絕大多數 Spring 用戶更喜歡實際的 JavaBean,它只有一個默認的(無參數的)構造器和適當的setter和getter方法,這些方法是根據容器中的屬性建模的。你還可以在容器中使用更多奇異的非bean樣式的類。例如,你需要使用絕對不符合JavaBean規范的遺留的連接池,Spring也可以管理它。

以 xml 的形式,你可以像下面這樣:

<bean id="exampleBean" class="examples.ExampleBean"/> <bean name="anotherExample" class="examples.ExampleBeanTwo"/>

更多關于如何向構造器提供參數(如果需要的話)和對象構造結束后為對象賦值的機制,參考:Injecting Dependencies。?

4.3.2 使用靜態工廠方法實例化 bean

當定義一個使用靜態工廠方法創建的 bean 時,使用 class 屬性指定包含了靜態工廠方法的類,然后再使用 factory-method 屬性來指定工廠方法的名字。如下所示:

<bean id="clientService"class="examples.ClientService"factory-method="createInstance"/>

而這個靜態方法應該是真實可被調用的:

public class ClientService {private static ClientService clientService = new ClientService();private ClientService() {}public static ClientService createInstance() {return clientService;} }

更多有關向工廠方法提供參數和返回對象后如何賦值的機制,參考:?Dependencies and Configuration in Detail。?

4.3.3?使用實例工廠方法實例化 bean

還有一種方法是通過實例工廠方法創建 bean。和靜態工廠方法類似,使用實例工廠方法進行實例化會調用一個“非靜態”的已存在容器內的bean的方法來創建對象。

使用這種機制時,class 屬性為空即可,factory-bean 屬性指定一個在當前(或父或祖先)容器內的 bean 名稱,這個 bean 需要包含一個可以被用于創建對象的工廠方法。剩下的,就和靜態工廠的配置差不多了:

<!-- the factory bean, which contains a method called createInstance() --> <bean id="serviceLocator" class="examples.DefaultServiceLocator"><!-- inject any dependencies required by this locator bean --> </bean><!-- the bean to be created via the factory bean --> <bean id="clientService"factory-bean="serviceLocator"factory-method="createClientServiceInstance"/> public class DefaultServiceLocator {private static ClientService clientService = new ClientServiceImpl();public ClientService createClientServiceInstance() {return clientService;} }

另外,一個工廠類可以被多個工廠方法依賴:

<bean id="serviceLocator" class="examples.DefaultServiceLocator"><!-- inject any dependencies required by this locator bean --> </bean><bean id="clientService"factory-bean="serviceLocator"factory-method="createClientServiceInstance"/><bean id="accountService"factory-bean="serviceLocator"factory-method="createAccountServiceInstance"/>

對應的類:

public class DefaultServiceLocator {private static ClientService clientService = new ClientServiceImpl();private static AccountService accountService = new AccountServiceImpl();public ClientService createClientServiceInstance() {return clientService;}public AccountService createAccountServiceInstance() {return accountService;} }

?在 Spring 文檔中,“factory bean” 指的是在 Spring 容器中配置的可以通過實例工廠或靜態工廠方法創建對象的一種 bean。相對的,FactoryBean(注意大小寫)指的是 Spring 框架特有的 FactoryBean 接口及實現類。

?【《Spring揭秘》關于FactoryBean:

當某些對象的實例化過程過于繁瑣,通過xml配置過于復雜,就可以實現FactoryBean接口,給出對象實例化邏輯代碼。FactoryBean是Spring提供的對付這種情況的“制式裝備”(正規軍)。

FactoryBean的三個抽象方法

1、getObject()方法會返回該FactoryBean“生產”的對象實例,我們需要實現這個方法以給出自己的對象實例化邏輯。

2、getObjectType()方法返回對象的類型,如果預先無法確定,則返回null。

3、isSingleton()方法用于表明getObject()返回的對象是否以singleton形式存在。

案例:

public class NextDayDateFactoryBean implements FactoryBean{ public Object getObject() throws Exception{return new DateTime().plusDays(1); } public Class getObjectType(){ return DateTime.class; }public boolean isSingleton(){ return false; } } <bean id=”displayer” class=”...Displayer”><property name=”nextDay”><ref bean=”nextDayDate”></property> </bean> <bean id=”nextDayDate” class=”...NextDayDateFactoryBean”> </bean> public class Displayer {private DateTime nextDay;// ... }

提示:FactoryBean類型的bean定義,通過正常的 id 引用,容器返回的是FactoryBean所“生產”的對象類型,而非FactoryBean類型本身】

4.4 判斷 Bean 的運行時類型(updated on 2020-10-14)

具體 bean 的運行時類型并不容易確定。bean 定義中指定的 class 只不過是一個初始類型參考,可能潛在綁定了一個聲明的工廠方法,或者作為一個可能會導致一個不同運行時 bean 類型的?FactoryBean,或在實例工廠方法中根本不設置(如前所述)。此外,AOP的代理可能會使用基于接口的代理對象包裹 bean 實例,這也會限制目標 bean 的真實類型的暴露。

找出指定 bean 的真實運行時類型的方法,推薦使用 BeanFactory.getType 方法,使用 bean 的名稱作為參數。上述所有情況都包括在內,這個方法可以返回相同 bean 名稱的對象的類型。

五、依賴

5.1 Dependency Injection 依賴注入

依賴注入是一個只通過構造函數參數、工廠方法參數、或通過屬性賦值等方式去定義它們的依賴的一個過程,簡言之,就是屬性賦值。

容器會在創建 bean 的時候注入那些它需要的依賴。這基本是由對象自己控制實例化的反向操作,因此得名控制反轉。

使用 DI 原則會讓代碼更加整潔,而且,當對象被它們的依賴所提供時,也可以更好的解耦。對象不再需要去查找它的依賴,也不需要知道這些依賴的位置和類型信息。因此,你的類就會更容易的去做測試。

DI 存在兩種主要的變體:構造器依賴注入Setter 依賴注入

構造器依賴注入通過容器調用一定數量參數的構造來完成,每一個參數都代表一個依賴項。調用靜態工廠方法,傳入指定參數來構造 Bean 的形式和這差不多。下面代碼展示了只能用構造器注入的依賴注入模式:

public class SimpleMovieLister {// the SimpleMovieLister has a dependency on a MovieFinderprivate MovieFinder movieFinder;// a constructor so that the Spring container can inject a MovieFinderpublic SimpleMovieLister(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// business logic that actually uses the injected MovieFinder is omitted... }

注意,上述代碼并沒有任何特別之處。這就是一個 POJO ,沒有依賴容器的任何特定接口、基礎類或注解。

使用參數類型就會觸發構造器參數類型解析匹配。如果bean定義的構造函數參數中不存在潛在的歧義,那么構造函數參數在bean定義中定義的順序就是實例化bean時將這些參數提供給適當的構造函數的順序。考慮以下類:

public class ThingOne {public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {// ...} }

假設 ThingTwo 和 ThingThree 類沒有繼承關系,沒有潛在的歧義存在。這樣,下面的配置就可以很好的工作,你不需要在<constructor-args/>標簽中顯式地指定構造器參數下標或類型。

<beans><bean id="beanOne" class="x.y.ThingOne"><constructor-arg ref="beanTwo"/><constructor-arg ref="beanThree"/></bean><bean id="beanTwo" class="x.y.ThingTwo"/><bean id="beanThree" class="x.y.ThingThree"/> </beans>

當另一個 bean 被引入,且類型已知,那么就會匹配到。當用到一個簡單類型,如<value>true</value>,Spring 無法判斷值的類型,也因此無法自主匹配。如下所示:

public class ExampleBean {// Number of years to calculate the Ultimate Answerprivate int years;// The Answer to Life, the Universe, and Everythingprivate String ultimateAnswer;public ExampleBean(int years, String ultimateAnswer) {this.years = years;this.ultimateAnswer = ultimateAnswer;} }

這種情況,如果希望容器成功完成類型匹配,就需要我們顯式指定類型信息,使用 type 屬性即可。這適用于使用簡單類型作為構造器參數的情況,如下所示:

<bean id="exampleBean" class="examples.ExampleBean"><constructor-arg type="int" value="7500000"/><constructor-arg type="java.lang.String" value="42"/> </bean>

同時也可以使用 index 屬性來顯式指定構造器參數的下標,注意下標從 0 開始。如下所示:

<bean id="exampleBean" class="examples.ExampleBean"><constructor-arg index="0" value="7500000"/><constructor-arg index="1" value="42"/> </bean>

下標有時還可解決構造器具有相同簡單類型時出現的歧義問題。

也可以使用參數名稱來消除歧義:

<bean id="exampleBean" class="examples.ExampleBean"><constructor-arg name="years" value="7500000"/><constructor-arg name="ultimateAnswer" value="42"/> </bean>

注意,這種方式需要配合 debug 標志,以便 Spring 可以找到構造器的參數名,你可以使用 @ConstructorProperties JDK注解來顯式地命名你的構造器參數,如下所示:

public class ExampleBean {@ConstructorProperties({"years", "ultimateAnswer"})public ExampleBean(int years, String ultimateAnswer) {this.years = years;this.ultimateAnswer = ultimateAnswer;} }

Setter 依賴注入,通過容器調用無參構造或無參靜態工廠方法實例化 bean 之后調用 setter 方法來完成。

下面的 demo 展示只能通過純 setter 方法實現依賴注入的方式:

public class SimpleMovieLister {// the SimpleMovieLister has a dependency on the MovieFinderprivate MovieFinder movieFinder;// a setter method so that the Spring container can inject a MovieFinderpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;}// business logic that actually uses the injected MovieFinder is omitted... }

ApplicationContext 支持基于構造器和基于 Setter 方法來對它所管理的 bean 進行依賴注入,同時也支持兩種混合使用。

你可以BeanDefinition的形式配置依賴,結合 PropertyEditor 實例,將屬性從一種形式轉化為另一種形式。然而,絕大多數 Spring 用戶并不會以編程的方式直接使用這些類,而是使用 XML 的bean definition、注解式組件(即 @Component、@Controller等等)、或在@Configuration 標記的類中使用 @Bean 的形式(即 Java Config)。這些元信息依然會在內部轉化為 BeanDefinition 實例,并且被用于加載整個 Spring IOC 容器實例。

選擇構造器 DI 還是 Setter DI?

由于可以混合使用基于構造器和基于setter的DI,對于強制依賴項使用構造器,而對于可選依賴項使用setter方法或配置方法,這是一個很好的經驗法則。請注意,在setter方法上使用@Required注釋可以使屬性成為必需的依賴項,但是,更好的方式是使用構造器然后對參數進行編程驗證。

Spring 團隊更提倡使用構造器注入,因為這樣可以將應用程序組件實現為不可變對象,并確保所需的依賴項不為空。此外,構造器注入的組件總是會返回完全初始化的狀態給調用代碼。另外提一句,根據馬丁福勒的重構原理,攜帶大量參數的構造器是一種“壞味道”,這意味著類可能有太多的職責,應當適當進行重構,分離一部分依賴。

Setter注入應該主要用于可選的依賴項,這些依賴項可以在類中分配合理的默認值。否則,必須在代碼使用依賴項的任何地方執行非空檢查。setter注入的一個好處是,setter方法使該類的對象易于稍后重新配置或重新注入。

5.2 依賴解析處理

容器會以下面的方式執行 bean 依賴解析操作:

1、ApplicationContext 通過使用 bean 配置信息(可以是 XML、注解、Java Config)進行創建和初始化。

2、對于每一個 bean ,它的依賴描述為屬性、構造器函數參數、或者靜態工廠方法中的其中一種形式。這些依賴會當 bean 真正創建的時候提供給 bean。

3、每個屬性或構造函數參數都是要設置的值的實際定義,或者是對容器中另一個bean的引用。

4、作為值的每個屬性或構造函數參數都從其指定的格式轉換為該屬性或構造函數參數的實際類型。默認情況下,Spring可以將字符串格式提供的值轉換為所有內置類型,比如int、long、string、boolean等等。

Spring 容器會在創建時驗證每個 bean 的配置。但只有在真正實例化 bean 的時候才會為這些 bean 屬性賦值。容器在創建之初,會將 bean 創建為 單例(singleton-scoped)且設置為“預實例化”(默認)。Scope 被定義在 Bean Scopes。否則,bean 只有在被請求時才會創建。創建 bean 可能會導致一系列的 bean 都被創建,因為bean 本身需要依賴,而依賴也需要依賴。這些依賴項的解析工作可能會在其后發生,即第一次創建受影響的 bean 時。(Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late?—?that is, on first creation of the affected bean.)

循環依賴

如果你使用顯式構造器注入,可能會出現無法解析的循環依賴問題。

例如,A 對象需要通過構造器注入一個 B 對象,并且 B 也需要通過構造器注入一個 A 對象。如果使用 spring 容器配置 A 和 B 注入彼此,那么 IOC 容器會在運行時檢測到這樣的循環引用,并拋出 BeanCurrentlyInCreationException。

一個可能的解決方案是編輯源碼,將構造器注入改為 setter。要么,避免使用構造器注入,只允許使用 setter 注入。換句話說,盡管并不推薦 setter 注入,但 setter 注入卻可以解決循環依賴問題。

和典型的應用場景不同,循環依賴問題描述的是 bean A 和 bean B 之間,強制其中一個要在完全初始化之前注入到另一個對象中(這是典型的先有雞還是先有蛋的問題)。

Spring 容器可以在加載時檢測配置問題,例如引用了不存在的 bean 和循環依賴問題。當 bean 被真正創建之時,Spring 會盡可能晚的為屬性賦值和解析依賴。也就是說,當你請求一個對象時,如果創建該對象或其依賴發生了問題,Spring 容器會晚一點產生一個異常,例如一個找不到或無效的屬性,就會拋出一個異常。這些都是一些潛在的延遲問題,這也是為什么 ApplicationContext 實現要默認采用預實例化單例 bean 的原因。在實際需要之前創建這些bean需要花費一些前期時間和內存,但可以在創建 ApplicationContext 之時發現配置問題,而不是稍后發現。但也可以覆蓋這個默認行為,以便單例 bean 可以惰性地初始化,而不是預先實例化。

如果不存在循環依賴關系,那么當一個或多個協作bean被注入到依賴bean中時,每個協作bean在被注入到依賴bean之前都已被完全配置。也就是說,如果bean A依賴于bean B,那么容器會在調用bean A上的setter方法之前完全配置bean B。換句話說,這個 bean B 會被實例化(如果它不是預實例化的),它的依賴會設置完畢,它的相關生命周期回調方法(例如配置的init 方法或 InitializingBean 回調方法)都會被調用執行。

以下代碼是使用 xml 描述的 setter 注入:

<bean id="exampleBean" class="examples.ExampleBean"><!-- setter injection using the nested ref element --><property name="beanOne"><ref bean="anotherExampleBean"/></property><!-- setter injection using the neater ref attribute --><property name="beanTwo" ref="yetAnotherBean"/><property name="integerProperty" value="1"/> </bean><bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/> public class ExampleBean {// a private constructorprivate ExampleBean(...) {...}// a static factory method; the arguments to this method can be// considered the dependencies of the bean that is returned,// regardless of how those arguments are actually used.public static ExampleBean createInstance (AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {ExampleBean eb = new ExampleBean (...);// some other operations...return eb;} }

5.3 depends-on

如果一個 bean 是另一個 bean 的依賴,通常意味著這個 bean 需要作為一個屬性設置到 另一個 bean 中。一般你可以使用 <ref> 標簽配置這樣的信息。但是,有時候 bean 之間的依賴關系并不那么直接。例如,當一個靜態初始化器需要注冊時,例如 數據庫驅動注冊。那么 depends-on 屬性就可以顯式地強制在初始化使用此元素的bean之前初始化一個或多個bean。如下所示:

<bean id="beanOne" class="ExampleBean" depends-on="manager"/> <bean id="manager" class="ManagerBean" />

當需要描述多個依賴時,可以這樣寫:

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"><property name="manager" ref="manager" /> </bean><bean id="manager" class="ManagerBean" /> <bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

提示:depends-on屬性既可以指定初始化階段依賴項,也可以指定對應的銷毀階段依賴項(僅在單例bean中)。在銷毀給定bean本身之前,首先銷毀與給定bean定義依賴關系的依賴bean。因此,依賴還可以控制關機順序。

5.4 懶加載 Bean

默認情況,作為初始化過程的一部分,ApplicationContext 的實現會餓漢式創建和配置所有單例 bean。通常,這種預實例化的操作是好的,因為這樣可以立刻發現配置中或者環境中的問題和錯誤,而不是幾小時甚至幾天后。當不適合用這種方式時,你可以將 bean definition 設置為懶加載來避免預實例化。一個懶加載 bean 會告訴 IOC 容器,只在第一次請求對象的時候創建對象,而不是一啟動的時候。如下設置:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/> <bean name="not.lazy" class="com.something.AnotherBean"/>

但是注意,如果懶加載 bean 恰好是非懶加載 bean 的依賴時,那么IOC 容器會忽略懶加載屬性,而直接在啟動時創建這個懶加載 bean,因為它必須滿足作為一個依賴的身份。

也就是說,延遲初始化設置會由于被其他非延遲初始化bean依賴而失效!

另外還可以通過使用<beans/>元素的 default-lazy-init 屬性來控制容器級別的延遲初始化,如下面的示例所示:

<beans default-lazy-init="true"><!-- no beans will be pre-instantiated... --> </beans>

5.5 自動裝配依賴

Spring 容器可以自動裝配協作者之間的關系。自動裝配有以下優點:

1、自動裝配可以顯著減少指定屬性或構造函數參數的需要。

2、自動裝配可以隨著對象的發展更新配置。例如,如果需要向類添加依賴項,則無需修改配置即可自動滿足該依賴項。因此,自動裝配在開發過程中特別有用。

5.6 方法注入(Method Injection)

大多數應用場景,容器中的 bean 都是單例的。當一個單例 bean 需要和另一個單例 bean 協同工作,或一個非單例 bean 需要和另一個非單例bean 協同工作,你一般會將依賴定義為另一個 bean 的屬性。

但當 bean 的生命周期不同時,就會出現問題。

假設單例對象 A 需要使用非單例(原型)對象 B,可能在 A 的每個方法調用上。容器只會創建 A 一次,這樣也就只會有一次機會為屬性賦值。那么容器無法每次在 A 需要使用 B 的時候都實例化一個 B 提供給 A。

一種解決方法是,放棄一定的控制反轉。你可以令 A 實現ApplicationContextAware 接口來讓 A 知曉容器的存在,并且在每次 A 需要使用 B 的時候,通過 getBean("B") 來請求一個新的 B 對象。如下所示:

public class CommandManager implements ApplicationContextAware {private ApplicationContext applicationContext;public Object process(Map commandState) {// grab a new instance of the appropriate CommandCommand command = createCommand();// set the state on the (hopefully brand new) Command instancecommand.setState(commandState);return command.execute();}protected Command createCommand() {// notice the Spring API dependency!return this.applicationContext.getBean("command", Command.class);}public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;} }

這種方式并不可取,因為業務代碼知道了 Spring 框架,并與之耦合。方法注入是一個IOC 容器的高級特性,可以讓你干凈利落的處理這樣的情況。

【《Spring揭秘》bean的scope使用陷阱:

依賴于“prototype”對象的客戶端對象第一次從容器中取得該prototype對象后,會一直持有該對象引用。因此需要注意,后續從客戶端對象中使用的該“prototype”對象總是同一個,即prototype只針對每次從容器中取得才可返回新對象

方法注入(Method Injection)的含義是,容器通過指定的方法將bean注入

普通的getBean方法會使容器帶有侵入性,因此,當我們獲取prototype對象時,往往會結合方法注入來使用,指定某個方法代替getBean從容器中取得prototype對象。

其底層邏輯是Spring會通過Cglib動態代理該類并重寫該注入方法,因此,Spring要求聲明的注入方法需要符合固定格式:

<public|protected> [abstract] <return-type> injectMethodName(no-args);

對于一般的getter方法,就符合這樣的格式。因此,可以通過<lookup-method>標簽告知Spring容器,使用getXxx()方法完成指定bean對象的注入:

<bean id=”b” class=”...B” singleton=”false”></bean> <bean id=”a” class=”...A”><lookup-method name=”getB” bean=”b”/> </bean>

lookup-method標簽的name屬性指定需要注入的方法名,bean屬性指定需要注入的對象。這樣,在每次調用a.getB()的時候,程序都會向容器請求一個新的B對象并返回。

六、Bean Scope 作用域

scope用來描述容器中的對象的限定場景或存活時間

打個比方:我們都處于社會(容器)中,如果把中學教師作為一個類定義,那么當容器初始化這些類之后,中學教師只能局限在中學這樣的場景中。中學,就可以看做中學教師的scope。——《Spring揭秘》

當你創建一個 bean definition ,你實際上是創建了一個用于實例化的食譜(或處方)。這個“食譜”的思想很重要,因為這意味著,就像類一樣,你可以從一個單獨的食譜中創建許多對象

Spring 中支持 6 種scope,singleton和prototype是Spring最開始最遲的兩種scope類型,在Spring2.0 之后又加入了另外四種只在支持 web 的ApplicationContext中使用的scope類型。你也可以自定義 scope:

Scope描述

singleton

(默認) Scopes a single bean definition to a single object instance for each Spring IoC container.

prototype

Scopes a single bean definition to any number of object instances.

request

Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring?ApplicationContext.

session

Scopes a single bean definition to the lifecycle of an HTTP?Session. Only valid in the context of a web-aware Spring?ApplicationContext.

application

Scopes a single bean definition to the lifecycle of a?ServletContext. Only valid in the context of a web-aware Spring?ApplicationContext.

websocket

Scopes a single bean definition to the lifecycle of a?WebSocket. Only valid in the context of a web-aware Spring?ApplicationContext.

【《Spring揭秘》以下給出部分關鍵scope類型的精簡說明:

1、singleton:首先,同一個IOC容器只存在一個singleton的bean。其次,容器啟動時創建,第一次請求時初始化,容器不退出,對象就就一直存在。

2、prototype:每次重新生成一個新的對象給請求方。實例化、屬性設置等工作由容器負責,返回后,容器不再擁有該對象的引用,請求方需自行負責后續(如銷毀)生命周期活動。通常,聲明為prototype的bean都含有一些可變狀態。

3、request:WebApplicationContext會為每個http請求創建一個scope為request的對象,請求結束,對象的生命周期也將結束。從不嚴格的意義上說,request可以看做是prototype的一種特例,除了場景更加具體,語義上差不多。

4、session:容器會為每個會話創建scope為session的實例。與request相比,除了更長的存活時間,其他方面沒什么差別。】?

6.1 單例作用域

單例很好理解,即只有一個實例對象,spring 容器在每次請求該 bean 的時候都只返回同一個對象。

換句話說,當你定義了一個 bean ,且它的 scope 屬性是 singleton,那么 IOC 容器只會為其創建一個實例。這個實例被存儲在一個用于存儲這種單例 bean 的緩存區,后續所有的請求或引用,都會返回已緩存的單例對象。下圖展示了單例作用域的工作模式:

Spring 中的單例 bean 的概念與GoF的單例模式有些不同。GoF 單例對對象的作用域進行硬編碼,這樣每個類加載器都會創建一個且只有一個特定類的實例。Spring單例的作用域最好描述為每個容器和每個bean。這意味著,如果你在單個Spring容器中為特定類定義了一個bean,那么Spring容器將創建由該 bean 定義的類的一個且僅一個實例。

<bean id="accountService" class="com.something.DefaultAccountService"/><!-- the following is equivalent, though redundant (singleton scope is the default) --> <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

6.2 原型作用域

原型作用域的 bean 會在每次請求后返回一個新的 bean 實例。你應該對所有有狀態的 bean 使用原型作用域,對無狀態的 bean 使用單例作用域。下圖展示了原型作用域:

數據訪問對象(DAO)通常不配置為原型,因為典型的DAO不持有任何會話狀態。

與其他作用域相比,Spring不管理原型bean的完整生命周期。容器實例化、配置和組裝原型對象并將其交給客戶端,而不進一步記錄該原型實例。因此,盡管初始化的回調方法在所有對象上都被調用,但在原型的情況下,配置的銷毀回調不會被調用。為了讓 Spring 容器釋放被原型 bean 所持有的資源,請使用自定義bean的后置處理器(bean post-processor),它持有一個需要被清理的 bean的引用。

在一些方面,Spring 容器的原型bean 被視為 Java new 操作符的替代品。

6.3 單例bean依賴原型bean

當使用原型 bean 作為單例 bean 的依賴項時,請注意,依賴關系是在實例化時解析的。因此,如果你將一個原型 bean 依賴式地注入到一個 單例 bean 中,那么就會創建一個新的原型 bean 然后注入到單例 bean中。原型實例是提供給單例 bean的唯一實例。

但是,假設你想讓單例 bean 在運行時反復依賴原型 bean ,你不能依賴式地注入原型 bean,因為注入只會發生一次,即只會在IOC 容器實例化該單例 bean 并解析、注入它的依賴時。如果想在運行時多次請求原型 bean ,請使用方法注入(前面有介紹)。

6.4 Request、Session、Application? 和 WebSocket 作用域

參考:Request, Session, Application, and WebSocket Scopes

6.5 自定義作用域

bean 的 Scope 機制是可擴展的。你可以定義你自己的作用域,或重新定義現有的作用域,但是后者并不推薦。而且,你無法重寫內建的 singleton 和 prototype 作用域。

為了能夠將你自定義的 scope 整合到 IOC 容器,你必須實現 org.springframework.beans.factory.config.Scope 接口。

Scope 接口包含 4 個方法,可以從作用域中獲取對象,從作用域中移除對象,也可以銷毀他們。

以 Session 作用域的實現為例,會返回一個 session 作用域的 bean(如果它不存在,方法就會返回一個新的 bean 實例,然后將它綁定到 session 上,以便后續訪問)。

Object get(String name, ObjectFactory<?> objectFactory)

更多內容參考:Custom Scopes

七、Bean 的生命周期與 Aware

Spring 提供了一些接口用來幫助開發者自定義 bean 的一些性質。這一節主要講解:

生命周期回調;ApplicationContextAware 和 BeanNameAware;以及其他的 Aware 接口。

7.1 生命周期回調

要與容器對 bean 的生命周期管理交互,你需要實現 InitializingBean 接口和?DisposableBean 接口。容器對前者調用afterPropertiesSet(),對后者調用destroy(),讓bean在初始化和銷毀bean時執行某些操作。

在內部,Spring框架使用BeanPostProcessor處理任何回調接口的實現,它可以找到并調用適當的方法。如果你需要定制特性或Spring默認不提供的其他生命周期行為,可以自己實現BeanPostProcessor。除了初始化和銷毀回調之外,spring管理的對象還可以實現生命周期接口,以便這些對象可以參與啟動和關閉過程,這是由容器自己的生命周期驅動的。

初始化回調

org.springframework.beans.factory.InitializingBean 接口在容器設置了bean的所有必要屬性之后,讓bean執行初始化工作。該接口只有一個方法:

void afterPropertiesSet() throws Exception;

我們不建議你使用 InitializingBean 接口,因為它令業務代碼與 Spring 框架建立了不必要的耦合。還有另一種方式,我們更建議使用 @PostConstruct 注解或指定一個POJO 初始化方法。在 xml 形式的配置中,你可以使用 init-method 屬性來指定該方法的名稱,該方法需要具備無返回值(void)、無參數(no-arguments)的特點。如果使用 JavaConfig ,你可以使用 @Bean 中的 initMethod 屬性。

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> public class ExampleBean {public void init() {// do some initialization work} }

上面的例子和下面的例子效果完全相同,以下是實現 InitializingBean 接口的版本:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/> public class AnotherExampleBean implements InitializingBean {@Overridepublic void afterPropertiesSet() {// do some initialization work} }

但是,更推薦第一個例子,因為更解耦。

銷毀回調

和初始化回調類似,Spring 同樣提供了兩種實現方式,既可以實現?DisposableBean 接口,也可以直接在 配置中指定 destroy-method 屬性。以下片段分別是實現?DisposableBean 接口和 destroy-method 屬性配置兩種不同方式,請任選其一:

---XML配置: <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> ---Java 代碼: public class AnotherExampleBean implements DisposableBean {@Overridepublic void destroy() {// do some destruction work (like releasing pooled connections)} } ---XML配置: <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> ---Java 代碼: public class ExampleBean {public void cleanup() {// do some destruction work (like releasing pooled connections)} }

默認的初始化和銷毀方法

不需要實現 InitializingBean 接口,也不需要指定 init-method 屬性,Spring 提供了以約定命名為基礎的初始化和銷毀回調方法。

只需要在 bean 中加入 init()、destroy() 方法,Spring 就會自動查找并執行對應生命周期的回調。例如 init() 方法:

public class DefaultBlogService implements BlogService {private BlogDao blogDao;public void setBlogDao(BlogDao blogDao) {this.blogDao = blogDao;}// this is (unsurprisingly) the initialization callback methodpublic void init() {if (this.blogDao == null) {throw new IllegalStateException("The [blogDao] property must be set.");}} }

那么在配置中就不需要顯式聲明任何初始化回調方法:

<bean id="blogService" class="com.something.DefaultBlogService"><property name="blogDao" ref="blogDao" /> </bean>

Spring 容器保證在 bean 配置完全部依賴后,會立即執行配置好的初始化回調方法。因此,初始化回調是在原始 bean 上調用的,這意味著 AOP 攔截器等還沒有使用到 bean 。

混合使用生命周期機制

Spring 2.5 之后,你有三種選擇來控制 bean 生命周期行為:

1、InitializingBean 和 DisposableBean 回調接口

2、自定義 init() 和 destroy() 方法

3、@PostConstruct 和 @PreDestroy 注解。你可以混合這些機制來控制一個給定的 bean 。

如果 bean 配置了使用不同的初始化方法的多個生命周期機制,它們會以下面的順序調用:

1、@PostConstruct 注解標記的方法

2、InitializingBean回調接口定義的afterPropertiesSet()

3、自定義的 init() 方法

銷毀方法以下面的順序執行:

1、@PreDestroy 注解標記的方法

2、DisposableBean 回調接口定義的 destroy()

3、自定義的 destroy() 方法

啟動和關閉回調

Lifecycle 接口為任何具有它們自己的生命周期需求的對象定義了一些基本方法(例如啟動或停止一些后臺處理):

public interface Lifecycle {void start();void stop();boolean isRunning(); }

任何由Spring 管理的對象都可以實現 Lifecycle 接口。當 ApplicationContext 接收到開始或停止信息時(例如,在運行過程中的 stop/restart 場景),就會將這些請求串聯到對應上下文中定義的 Lifecycle 實現上。這是通過探測 LifecycleProcessor 來實現的,如下所示:

public interface LifecycleProcessor extends Lifecycle {void onRefresh();void onClose(); }

啟動的調用順序和關閉的調用順序可能很重要。如果兩個對象之間存在依賴關系,依賴端要在依賴項之后開始,在依賴項之前停止。然而,有時候這種直接的依賴關系并不清晰。你可能只知道某個對象應該在另一個對象之前啟動。這種情況下, SmartLifecycle 接口就派上用場了,它是 Phased 接口的子接口:

public interface Phased {int getPhase(); }public interface SmartLifecycle extends Lifecycle, Phased {boolean isAutoStartup();void stop(Runnable callback); }

當啟動時,具有最低相位的對象先開始。當停止時,順序則反過來。因此,如果一個對象實現了 SmartLifecycle 并且它的 getPhase() 方法返回一個 Integer.MIN_VALUE ,那么它就會第一個啟動,最后一個停止。相反的,如果 getPhase() 的值返回Integer.MAX_VALUE ,則表明這個對象應該最后一個啟動,并且第一個停止。當考慮phase值時,同樣重要的是要知道對于任何沒有實現SmartLifecycle的“正常”生命周期對象,其默認的phase是0。因此,任何負相位值都表示一個對象應該在那些標準組件之前開始(并在它們之后停止)。對于任何正相位值,情況正好相反。

7.2 ApplicationContextAware 和 BeanNameAware

當 ApplicationContext 創建了一個實現了 ApplicationContextAware 接口的 bean 實例,那么該實例同樣也會拿到一個 ApplicationContext 的引用。以下是 ApplicationContextAware 接口:

public interface ApplicationContextAware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }

這樣, bean 就可以通過 ApplicationContext 接口或將引用轉化為它的已知子類(如ConfigurableApplicationContext)以編程的方式來操作創建它們的 ApplicationContext 對象。

當 ApplicationContext 創建了一個實現了 BeanNameAware 接口的 bean 實例,那么該實例也可以拿到一個由關聯的 bean definition 定義的 bean name。下面代碼片段是 BeanNameAware 接口:

public interface BeanNameAware {void setBeanName(String name) throws BeansException; }

這個回調方法會在填充普通bean屬性之后,在初始化回調(如InitializingBean、afterPropertiesSet或自定義初始化方法)之前調用執行。

7.3 其他的 Aware 接口

除了 ApplicationContextAware 和 BeanNameAware,Spring 提供了廣泛的感知回調接口,好讓 bean 能夠指示容器,它們需要一個基礎設施依賴。作為一般規則,名稱表示依賴類型。下表總結了最有用的 Aware 接口:

名稱注入的依賴詳細描述

ApplicationContextAware

Declaring?ApplicationContext.

ApplicationContextAware?and?BeanNameAware

ApplicationEventPublisherAware

Event publisher of the enclosing?ApplicationContext.

Additional Capabilities of the?ApplicationContext

BeanClassLoaderAware

Class loader used to load the bean classes.

Instantiating Beans

BeanFactoryAware

Declaring?BeanFactory.

ApplicationContextAware?and?BeanNameAware

BeanNameAware

Name of the declaring bean. bean 的名稱

ApplicationContextAware?and?BeanNameAware

BootstrapContextAware

Resource adapter?BootstrapContext?the container runs in. Typically available only in JCA-aware?ApplicationContext?instances.

JCA CCI

LoadTimeWeaverAware

Defined weaver for processing class definition at load time.

Load-time Weaving with AspectJ in the Spring Framework

MessageSourceAware

Configured strategy for resolving messages (with support for parametrization and internationalization).

Additional Capabilities of the?ApplicationContext

NotificationPublisherAware

Spring JMX notification publisher.

Notifications

ResourceLoaderAware

Configured loader for low-level access to resources.

Resources

ServletConfigAware

Current?ServletConfig?the container runs in. Valid only in a web-aware Spring?ApplicationContext.

Spring MVC

ServletContextAware

Current?ServletContext?the container runs in. Valid only in a web-aware Spring?ApplicationContext.

Spring MVC

注意,使用這些接口會將你的代碼與 spring api 進行耦合,且不符合控制反轉的風格。因此,我們建議將它們用于需要對容器進行編程訪問的基礎設施bean。

八、容器擴展性指導

一般,應用開發者不需要繼承 ApplicationContext 的實現類。而是通過插入特殊的繼承接口來擴展IOC 容器。

8.1 使用 BeanPostProcessor 來自定義 Bean

BeanPostProcessor,Bean 的后置處理器接口定義了回調方法,你可以實現該接口并提供你的初始化 bean 的邏輯(也可以重寫容器的默認實現)、依賴解析邏輯等等。如果你想在 容器完成實例化、裝配、初始化 bean 之后實現一些自定義邏輯,你可以插入一個或多個自定義的 BeanPostProcessor 實現。

你可以配置多個 BeanPostProcessor 實例,并且通過設置 order 屬性來控制這些實例的執行順序。只有當 BeanPostProcessor 實現了 Ordered 接口才可以設置該屬性。如果你需要自定義 BeanPostProcessor,你就也需要考慮實現 Ordered 接口。

BeanPostProcessor 實例基于 bean 實例執行操作。也就是說,IOC 容器實例化一個 bean ,然后 BeanPostProcessor 才能工作。

如果在一個容器中定義BeanPostProcessor,那么它只對該容器中的bean進行后處理,也就是說,BeanPostProcessor 的作用域是單獨的容器。

BeanPostProcessor 接口由兩個回調方法構成。當一個類在容器中注冊為一個 post-processor ,那么它的每一個實例,在容器初始化方法之前和 bean 初始化回調之后,都會從容器獲得一個回調。后置處理器可以對bean實例采取任何操作,包括完全忽略回調。bean 后置處理器通常檢查回調接口,或者用代理包裝bean。為了提供代理包裝邏輯,一些Spring AOP基礎設施類被實現為bean 后置處理器。

ApplicationContext 會自動檢測到 bean 中實現了 BeanPostProcessor 接口。ApplicationContext 會將這些 bean 注冊為 post-processor,以便后面在 bean 創建的時候進行調用。bean 的后置處理器可以像其他 bean 一樣部署在容器中。

注意,當使用 @Bean 聲明了一個 BeanPostProcessor,返回值類型應該是后置處理器的實現類,至少也應該是 BeanPostProcessor 接口類型,清楚地表明該 bean 的后置處理器特性。否則, ApplicationContext 無法自動檢測到它。由于BeanPostProcessor需要盡早實例化,以便應用于上下文中其他bean的初始化,因此這種早期類型檢測非常關鍵

編程式注冊 BeanPostProcessor?

雖然推薦的 BeanPostProcessor 注冊方式是通過 ApplicationContext 自動檢測,但你依然可以通過一個 ConfigurableBeanFactory的 addBeanPostProcessor() 方法以編程的方式注冊后置處理器。當你需要在注冊前計算條件邏輯,或在跨層次結構的上下文復制后置處理器時,這可能非常有用。但是注意,以編程方式注冊后置處理器不遵從 Ordered 接口。那么注冊順序就決定了執行順序。而且也要注意,編程式注冊的后置處理器永遠在自動檢測注冊的后置處理器之前執行,會忽略任何顯式的順序聲明。

BeanPostProcessor 實例和 AOP 自動代理

實現了 BeanPostProcessor 接口的類會被容器特殊對待。所有的 BeanPostProcessor 實例和直接引用的 bean,都會在容器啟動時實例化,并作為 ApplicationContext 啟動階段的一個特殊部分。

Next, all?BeanPostProcessor?instances are registered in a sorted fashion and applied to all further beans in the container. Because AOP auto-proxying is implemented as a?BeanPostProcessor?itself, neither?BeanPostProcessor?instances nor the beans they directly reference are eligible for auto-proxying and, thus, do not have aspects woven into them.

For any such bean, you should see an informational log message:?Bean someBean is not eligible for getting processed by all BeanPostProcessor interfaces (for example: not eligible for auto-proxying).

If you have beans wired into your?BeanPostProcessor?by using autowiring or?@Resource?(which may fall back to autowiring), Spring might access unexpected beans when searching for type-matching dependency candidates and, therefore, make them ineligible for auto-proxying or other kinds of bean post-processing. For example, if you have a dependency annotated with?@Resource?where the field or setter name does not directly correspond to the declared name of a bean and no name attribute is used, Spring accesses other beans for matching them by type.

8.2 使用 BeanFactoryPostProcessor 來自定義配置數據

在語義上,BeanFactoryPostProcessor 和 BeanPostProcessor 相似,只有一個不同點,那就是 BeanFactoryPostProcessor 在 bean 的配置數據上進行操作。也就是說,Spring IOC 容器允許 BeanFactoryPostProcessor 讀取配置數據,并在容器實例化任何 bean (除了BeanFactoryPostProcessor實例)之前改變配置。

你可以配置多個 BeanFactoryPostProcessor 實例,也設置 order 屬性來可以控制運行順序,但也必須要實現 Ordered 接口才可以。

如果你想改變實際的 bean 實例,那么你需要使用 BeanPostProcessor(如前所述)。雖然在BeanFactoryPostProcessor中使用bean實例在技術上是可行的(例如,通過使用BeanFactory.getBean()),但是這樣做會導致過早的bean實例化,違反標準的容器生命周期。這可能會導致負面的副作用,比如繞過bean的后處理。

另外,BeanFactoryPostProcessor實例的作用域為每個容器。這只有在使用容器層次結構時才有用。如果您在一個容器中定義了BeanFactoryPostProcessor,那么它只應用于該容器中的bean定義。一個容器中的Bean定義不會被另一個容器中的BeanFactoryPostProcessor實例進行后處理,即使這兩個容器屬于同一層次結構。

當Bean 工廠后置處理器在 ApplicationContext 中聲明,它將自動執行,以便對定義容器的配置數據執行更改。Spring包括許多預定義的bean工廠后處理器,如 PropertyOverrideConfigurer 和 PropertySourcesPlaceholderConfigurer。當然也可以自定義。

ApplicationContext自動檢測部署到其中實現BeanFactoryPostProcessor接口的任何bean。在適當的時候,它將這些bean用作bean工廠的后置處理器。可以像部署任何其他bean一樣部署這些后處理bean。

九、注解式容器配置

注解要比XML更適合配置Spring嗎?

簡單的回答是:看情況。詳細的回答是,每種方式都有其利弊,通常,這取決于開發者覺得那種方式更適合。

由于其定義方式,注解在其聲明中提供了大量上下文,從而使配置更短、更簡潔。但是,XML擅長在不改動源代碼或重新編譯組件的情況下連接組件。有些開發者喜歡將配置貼近源碼,但也有一些人認為這樣帶注解的類已不再是 POJO ,而且配置也會變得更分散,難以控制。

但不論那種方式,Spring 都可以適應,甚至是混用。值得說明的是,通過 Java Config 的引入,Spring 可以讓注解以一種非侵入式的方式進行配置,不需要接觸目標組件。

注解式配置為 xml 配置提供了另一種選擇。與 xml 不同,開發者可以將配置以注解的方式放到組件類上、方法上、域上。例如 Spring 2.0 引入了 @Required 注解,這讓配置必須屬性成為可能。Spring 2.5 使遵循相同的通用方法來驅動依賴注入成為可能。從本質上,@Autowired注解提供了與Autowiring協作器中描述的相同的功能,但是擁有更細粒度的控制和更廣泛的適用性。Spring 2.5 也增加了對 JSR-250 注解的支持,如 @PostConstruct 和 @PreDestroy。Spring 3.0 增加了對 JSR-330(Java 依賴注入)的支持,包含了 javax.inject 包,如 @Inject 和 @Named。

提示:注釋注入在XML注入之前執行。這樣,xml 配置就可以對同時使用這兩種方式的屬性覆蓋掉注解配置。

和往常一樣,你可以單獨地注冊 bean 定義,但也可以通過通過下面的標簽隱式地注冊到基于 xml 配置的Spring 容器中(注意包含的 context 命名空間)。

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/></beans>

(隱式注冊的后置處理器包括 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、和前面提到的 RequiredAnnotationBeanPostProcessor)

提示:<context:annotation-config/> 只查找定義在同一個應用程序 context 上下文的 bean 上的注解。也就是說,如果你為DispatcherServlet 在 WebApplicationContext 中配置了<context:annotation-config>標簽,那么它只檢查你的 controller 中 @Autowired 的 bean,而不會檢查 service。

9.1 @Required

@Required 注解可以放在 setter 方法上,例如:

public class SimpleMovieLister {private MovieFinder movieFinder;@Requiredpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;} }

這個注解表示必須在配置時填充受影響的bean屬性,要么通過顯式地 bean definition 要么通過 自動注入。如果 bean 屬性沒有成功注入,那么容器就會拋出一個異常。這種餓漢式明確的失敗,避免了空指針的發生。我們仍然建議將斷言放到bean類本身中(例如,放到init方法中)。這樣做會強制執行那些必需的引用和值,即使你在容器之外使用該類。

提示: @Required 注解在 Spring 5.1 被正式廢棄,我們更支持使用構造器注入必需配置(或者自定義實現 InitializingBean.afterPropertiesSet() 和 setter 方法)

9.2 使用 @Autowired

你可以在構造器上使用 @Autowired,例如:

public class MovieRecommender {private final CustomerPreferenceDao customerPreferenceDao;@Autowiredpublic MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {this.customerPreferenceDao = customerPreferenceDao;} }

提示:從Spring 4.3 開始,如果目標 bean 只定義了一個構造器,就沒必要將@Autowired 注解標記在這樣的構造器上。然而,如果有兩個或多個構造器,且沒有默認構造器,那么至少要在一個構造器上標記該注解,以便告訴容器要使用哪個。

你也可以將@Autowired 注解使用在 setter 方法上:

public class SimpleMovieLister {private MovieFinder movieFinder;@Autowiredpublic void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;} }

也可以將@Autowired 注解放在任意方法名的多參方法上:

public class MovieRecommender {private MovieCatalog movieCatalog;private CustomerPreferenceDao customerPreferenceDao;@Autowiredpublic void prepare(MovieCatalog movieCatalog,CustomerPreferenceDao customerPreferenceDao) {this.movieCatalog = movieCatalog;this.customerPreferenceDao = customerPreferenceDao;} }

你可以可以將@Autowired 放在域上,甚至是混用在構造器上:

public class MovieRecommender {private final CustomerPreferenceDao customerPreferenceDao;@Autowiredprivate MovieCatalog movieCatalog;@Autowiredpublic MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {this.customerPreferenceDao = customerPreferenceDao;} }

你可以通過向需要該類型數組的字段或方法添加@Autowired注解來指示Spring從ApplicationContext中提供所有特定類型的bean:

public class MovieRecommender {@Autowiredprivate MovieCatalog[] movieCatalogs; }

類型集合也可以:

public class MovieRecommender {private Set<MovieCatalog> movieCatalogs;@Autowiredpublic void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {this.movieCatalogs = movieCatalogs;}}

提示:如果想讓數組或集合中的bean 有序,你可以讓目標 bean 實現 Ordered 接口或使用 @Order 注解或使用 標準的@Priority 注解。否則,只能以注冊時的順序來排序這些 bean。

你可以在目標類型上指定 @Order 注解,或者 @Bean 方法上。 @Order 注解的 value 可能影響注入點的優先級,但不能影響單例的啟動順序,單例的啟動順序是由依賴關系和@DependsOn 決定的。

注意,標準 @Priority 注解不能使用在 @Bean 級別上,因為它無法聲明在方法上。

Map 的實例也可以自動注入,只要key 類型是 String。Map 的key 應該保存對應 bean 的名字,如下所示:

public class MovieRecommender {private Map<String, MovieCatalog> movieCatalogs;@Autowiredpublic void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {this.movieCatalogs = movieCatalogs;} }

默認情況,如果在注入點沒有匹配的候選 bean 可用,那么自動注入就會失敗。聲明的如果是數組、集合或 Map,至少需要有一個匹配的 bean 元素。

默認標記 @Autowired 注入的依賴是必需項。你可以改變這種默認設置,使框架跳過非必需依賴注入,如下所示:

public class SimpleMovieLister {private MovieFinder movieFinder;@Autowired(required = false)public void setMovieFinder(MovieFinder movieFinder) {this.movieFinder = movieFinder;} }

如果依賴項不可用,或其中一個依賴項的 setter 方法有多個參數,那么非必需方法將根本不會被調用。在這種情況下,將根本不填充非必需字段,保留其默認值。

從 5.0 開始,你也可以使用 @Nullable 注解:

public class SimpleMovieLister {@Autowiredpublic void setMovieFinder(@Nullable MovieFinder movieFinder) {...} }

你也可以使用 @Autowired 注解注入這些已知的框架相關依賴:BeanFactory、ApplicationContext、Environment、ResourceLoader、ApplicationEventPublisher,和 MessageSource。這些接口及其子接口,例如ConfigurableApplicationContext 或 ResourcePatternResolver,已經自動解析完畢,不需要特殊的設置:

public class MovieRecommender {@Autowiredprivate ApplicationContext context;public MovieRecommender() {} }

提示:@Autowired、@Inject、@Value? 和 @Resource 注解,都會被 Spring 自己的 BeanPostProcessor 實現來處理。也就是說,你無法在自己的BeanPostProcessor或BeanFactoryPostProcessor類型(如果有的話)中應用這些注釋。這些類型必須通過使用XML或Spring @Bean方法顯式地“連接起來”。

9.3 使用 @Primary 來微調基于注解的自動注入(updated on 2020-10-11)

因為通過類型來完成自動注入可能會有多個“候選項”(注:如接口類型可能會有多個實現子類),因此也就有必要有更多的控制手段。一種方法是通過 @Primary 注解來完成此項操作。@Primary 表示當單值依賴(single-valued dependency)注入時有多個候選項,那么應該只提供一個特定的 bean 引用如果這些候選項中有一個確定的“主要的”(primary)bean ,那么它就會是那個被注入的值。

考慮下面的用例:

@Configuration public class MovieConfiguration {@Bean@Primarypublic MovieCatalog firstMovieCatalog() { ... }@Beanpublic MovieCatalog secondMovieCatalog() { ... }}

基于上面的配置用例,下面的 MovieRecommender 電影推薦類就會注入 firstMovieCatalog 類型的 bean:

public class MovieRecommender {@Autowiredprivate MovieCatalog movieCatalog; }

對應的 bean 定義如下:

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><bean class="example.SimpleMovieCatalog" primary="true"><!-- inject any dependencies required by this bean --></bean><bean class="example.SimpleMovieCatalog"><!-- inject any dependencies required by this bean --></bean><bean id="movieRecommender" class="example.MovieRecommender"/></beans>

9.4 使用 @Qualifier 微調基于注解的自動注入(updated on 2020-10-11)

@Primary 是一種可以處理通過類型判斷自動注入時多個候選項只注入主要候選項的有效方式(或者可以描述為默認候選項注入)。當你需要更有控制力的方式來影響注入 bean 的匹配過程時,可以使用 Spring 提供的 @Qualifier 注解。你可以為 @Qualifier 的 value 屬性指定特殊的值,從而縮小類型匹配的范圍,以便為每個參數選擇特定的bean。例如下面用例:

public class MovieRecommender {@Autowired@Qualifier("main")private MovieCatalog movieCatalog;}

或者用在構造器上,指定注入的參數類型:

public class MovieRecommender {private MovieCatalog movieCatalog;private CustomerPreferenceDao customerPreferenceDao;@Autowiredpublic void prepare(@Qualifier("main") MovieCatalog movieCatalog,CustomerPreferenceDao customerPreferenceDao) {// ...} }

對應的 bean 定義如下:

<?xml version="1.0" encoding="UTF-8"?> <beans ... ><context:annotation-config/><bean class="example.SimpleMovieCatalog"><qualifier value="main"/><!-- inject any dependencies required by this bean --></bean><bean class="example.SimpleMovieCatalog"><qualifier value="action"/> <!-- inject any dependencies required by this bean --></bean><bean id="movieRecommender" class="example.MovieRecommender"/></beans>

對于降級匹配(fallback match),bean 的名稱被視為一個默認的限定值(qualifier value)。這樣,你可以將 bean 的 id 屬性定義為 “main” 而不是使用內嵌的<qualifier> 標簽,來達到同樣的匹配效果。

然而,雖然你可以使用這種約定,通過名稱來引入一個特定的 bean,但 @Autowired 基本上還是一個以類型驅動(type-driven)的注入方式,只是帶有可選的語義限定符(optional semantic qualifier)。這也就是說,限定值即使帶有名稱降級匹配,但也總是在類型匹配集中具有收縮語義(narrowing semantics)。它們在語義上并不表達唯一的 bean 的 id。

好的限定值是 main、EMEA、或 persistent,表示獨立于bean id 的特定組件的特征,在匿名bean定義(如前面示例中的bean定義)的情況下,可以自動生成。

@Qualifier 同樣可以用于類型化集合的注入情況。例如, Set<MovieCatalog>。在這種情況下,所有匹配的 bean,根據聲明的限定值,都會被注入到集合中。這也就是說,限定值不必唯一,它們組成了某個過濾條件。例如,你可以定義多個 MovieCatalog 類的 bean,使用相同的限定值“action”,那么所有這些 bean 都會被注入到聲明了 @Qualifier("action") 的 Set<MoiveCatalog> 集合中。

提示:在類型匹配候選中選擇指定名稱的?bean,不需要在注入點使用 @Qualifier 注解。如果沒有其他解析指示器(例如 @Qualifier 或 @Primary),對于非唯一依賴情況,Spring將注入點名稱(即字段名稱或參數名稱)與目標 bean 名稱匹配,并選擇同名的候選對象,也就是說字段名稱本身就默認是一種限定值

也就是說,如果你打算通過名稱來表示注解注入,不要都用 @Autowired,雖然它的確可以在類型匹配的候選中選擇指定名稱的 bean。相反地,應該使用 JSR-250 標準的 @Resource 注解,這個注解在語義上定義為通過惟一名稱標識特定的目標組件,聲明的類型與匹配過程無關。@Autowired 注解有著相當不同的語義:在類型匹配結束后,指定的 String 類型限定符值只會在類型匹配的候選項中選擇。

對于定義為集合、Map 或 數組類型的 bean,@Resource 是一個很好的解決方式,通過唯一的名稱引入集合或數組 bean。也就是說,從 Spring 4.3 開始,你依然可以使用 @Autowired 的類型匹配算法來匹配集合、Map 和 數組類型,只要元素類型信息保存在@Bean返回類型簽名或集合繼承層次結構中。這種情況下,你可以使用限定符在相同類型的集合中進行選擇,如前一段所述。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的Spring —— IoC 容器详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲一区av无码专区在线观看 | 国产亚洲精品久久久久久久 | 国产亚av手机在线观看 | 中文字幕 亚洲精品 第1页 | 国内揄拍国内精品人妻 | 亚洲成a人片在线观看无码3d | 久久久精品456亚洲影院 | 成人aaa片一区国产精品 | 国产精品久久国产精品99 | 亚洲区小说区激情区图片区 | 波多野结衣一区二区三区av免费 | 毛片内射-百度 | 玩弄人妻少妇500系列视频 | 欧洲极品少妇 | 日韩精品无码一区二区中文字幕 | 欧美日本免费一区二区三区 | 亚洲精品成a人在线观看 | 亚洲成av人片在线观看无码不卡 | 日韩亚洲欧美精品综合 | 欧洲vodafone精品性 | 青青草原综合久久大伊人精品 | 99久久婷婷国产综合精品青草免费 | 人妻熟女一区 | 熟妇人妻激情偷爽文 | 激情内射日本一区二区三区 | 国产激情一区二区三区 | www国产亚洲精品久久久日本 | 亚洲最大成人网站 | 99久久精品午夜一区二区 | 久久精品无码一区二区三区 | 波多野结衣av在线观看 | 狠狠cao日日穞夜夜穞av | 天堂无码人妻精品一区二区三区 | 成人性做爰aaa片免费看不忠 | 无码播放一区二区三区 | 午夜性刺激在线视频免费 | 亚洲精品国产a久久久久久 | 亚洲熟妇色xxxxx欧美老妇y | 在线视频网站www色 | 成人亚洲精品久久久久 | 亚洲精品中文字幕久久久久 | 老头边吃奶边弄进去呻吟 | 亚洲s码欧洲m码国产av | 亚洲自偷自偷在线制服 | 欧美人与禽zoz0性伦交 | 亚洲欧美国产精品专区久久 | 99视频精品全部免费免费观看 | 无码精品人妻一区二区三区av | 精品一区二区三区波多野结衣 | 国产精品久久久久久久9999 | 人人妻人人澡人人爽人人精品 | 日本护士xxxxhd少妇 | 久久综合九色综合97网 | 人妻少妇精品无码专区动漫 | 午夜精品一区二区三区的区别 | 色综合久久中文娱乐网 | 高清无码午夜福利视频 | 欧美刺激性大交 | 理论片87福利理论电影 | 国产精品沙发午睡系列 | 美女扒开屁股让男人桶 | 国产精品无码久久av | 亚洲国产成人av在线观看 | 男人和女人高潮免费网站 | 亚洲一区二区三区国产精华液 | 东京无码熟妇人妻av在线网址 | 日日噜噜噜噜夜夜爽亚洲精品 | 欧美国产日韩久久mv | 日本乱偷人妻中文字幕 | 欧美xxxx黑人又粗又长 | 无码吃奶揉捏奶头高潮视频 | 丰满少妇高潮惨叫视频 | 性做久久久久久久免费看 | 国产色在线 | 国产 | 日本一本二本三区免费 | 男女爱爱好爽视频免费看 | 18精品久久久无码午夜福利 | 久久精品99久久香蕉国产色戒 | 久久久久久国产精品无码下载 | 熟妇女人妻丰满少妇中文字幕 | 高清国产亚洲精品自在久久 | 人人妻人人澡人人爽人人精品 | 成人亚洲精品久久久久 | 久久久亚洲欧洲日产国码αv | 国产精品无码一区二区三区不卡 | 国产亚洲欧美在线专区 | 精品偷自拍另类在线观看 | 色婷婷欧美在线播放内射 | 日韩精品无码一区二区中文字幕 | 性生交大片免费看l | 又色又爽又黄的美女裸体网站 | 人妻插b视频一区二区三区 | 国产成人亚洲综合无码 | 日本在线高清不卡免费播放 | 亚洲中文字幕乱码av波多ji | 欧美性生交活xxxxxdddd | 大色综合色综合网站 | 国产三级久久久精品麻豆三级 | 狠狠躁日日躁夜夜躁2020 | 欧美熟妇另类久久久久久多毛 | 人人超人人超碰超国产 | 亚洲中文字幕久久无码 | 久激情内射婷内射蜜桃人妖 | 久久久中文字幕日本无吗 | 日日橹狠狠爱欧美视频 | 精品无人国产偷自产在线 | 思思久久99热只有频精品66 | 国产精品亚洲专区无码不卡 | 国产激情无码一区二区 | 亚洲人交乣女bbw | 色一情一乱一伦一视频免费看 | 国产精品丝袜黑色高跟鞋 | 一区二区传媒有限公司 | 中文字幕av日韩精品一区二区 | av香港经典三级级 在线 | a在线观看免费网站大全 | 亚洲一区二区三区国产精华液 | 国产两女互慰高潮视频在线观看 | 麻豆国产人妻欲求不满 | 亚洲一区二区三区在线观看网站 | 国产精品久久久 | 日本大乳高潮视频在线观看 | 国产精品久久久久7777 | 乱人伦中文视频在线观看 | 97无码免费人妻超级碰碰夜夜 | 一本久久a久久精品vr综合 | 久久熟妇人妻午夜寂寞影院 | 国产亚洲欧美日韩亚洲中文色 | 日本高清一区免费中文视频 | 日日鲁鲁鲁夜夜爽爽狠狠 | 欧美人与禽zoz0性伦交 | 2020最新国产自产精品 | 亚洲自偷自偷在线制服 | 欧美三级不卡在线观看 | 在线播放免费人成毛片乱码 | 特大黑人娇小亚洲女 | 伊人久久婷婷五月综合97色 | 红桃av一区二区三区在线无码av | 国产精品久久久一区二区三区 | 秋霞特色aa大片 | 妺妺窝人体色www在线小说 | 内射后入在线观看一区 | 97无码免费人妻超级碰碰夜夜 | 小泽玛莉亚一区二区视频在线 | 国产午夜精品一区二区三区嫩草 | 性色欲网站人妻丰满中文久久不卡 | 日本丰满护士爆乳xxxx | 男女作爱免费网站 | 国内少妇偷人精品视频免费 | 99久久无码一区人妻 | 亚洲性无码av中文字幕 | 人人妻人人澡人人爽欧美精品 | 国产精品高潮呻吟av久久 | 中文字幕无码人妻少妇免费 | 乱码av麻豆丝袜熟女系列 | 三级4级全黄60分钟 | 精品国产av色一区二区深夜久久 | 无遮挡啪啪摇乳动态图 | 中文久久乱码一区二区 | 午夜精品一区二区三区的区别 | 激情五月综合色婷婷一区二区 | 一本加勒比波多野结衣 | 一二三四社区在线中文视频 | 黑人玩弄人妻中文在线 | 久久精品女人天堂av免费观看 | 欧美人与牲动交xxxx | 久久99精品国产麻豆蜜芽 | 天天综合网天天综合色 | 中文字幕无码av激情不卡 | 99久久人妻精品免费一区 | 国产精品无码永久免费888 | 欧美精品一区二区精品久久 | 久久国产精品偷任你爽任你 | 狠狠躁日日躁夜夜躁2020 | 午夜丰满少妇性开放视频 | 久久99精品久久久久婷婷 | 天天躁夜夜躁狠狠是什么心态 | 中文字幕av无码一区二区三区电影 | 国产麻豆精品精东影业av网站 | 5858s亚洲色大成网站www | 亚洲国精产品一二二线 | a片免费视频在线观看 | 亚洲精品久久久久久一区二区 | 国产av一区二区精品久久凹凸 | 久久久成人毛片无码 | 狠狠色噜噜狠狠狠狠7777米奇 | 成人试看120秒体验区 | 国产精品爱久久久久久久 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 日日摸夜夜摸狠狠摸婷婷 | 国产精华av午夜在线观看 | 久在线观看福利视频 | 蜜桃av抽搐高潮一区二区 | 欧美放荡的少妇 | 熟妇人妻无码xxx视频 | 欧美真人作爱免费视频 | 国产乱子伦视频在线播放 | www成人国产高清内射 | 老司机亚洲精品影院 | 亚洲中文字幕在线观看 | 久久亚洲国产成人精品性色 | 亚洲人成影院在线观看 | 俄罗斯老熟妇色xxxx | 久久午夜夜伦鲁鲁片无码免费 | 欧美freesex黑人又粗又大 | 免费网站看v片在线18禁无码 | 网友自拍区视频精品 | 亚洲色www成人永久网址 | 色老头在线一区二区三区 | 在线亚洲高清揄拍自拍一品区 | 亚洲s色大片在线观看 | 99久久无码一区人妻 | 成人女人看片免费视频放人 | 成人欧美一区二区三区 | 无码国产激情在线观看 | 国产精品美女久久久网av | a国产一区二区免费入口 | 国产成人午夜福利在线播放 | 国内精品人妻无码久久久影院 | 亚洲国产欧美日韩精品一区二区三区 | 玩弄少妇高潮ⅹxxxyw | 国产黑色丝袜在线播放 | 国产无遮挡又黄又爽又色 | 亚洲男女内射在线播放 | 兔费看少妇性l交大片免费 | 4hu四虎永久在线观看 | 国产精华av午夜在线观看 | 成人aaa片一区国产精品 | 国产两女互慰高潮视频在线观看 | 午夜免费福利小电影 | 青草视频在线播放 | 久热国产vs视频在线观看 | 人人妻人人澡人人爽欧美精品 | 日本xxxx色视频在线观看免费 | 亚洲一区二区三区国产精华液 | 成人亚洲精品久久久久 | 好男人www社区 | 高潮喷水的毛片 | 国产凸凹视频一区二区 | 丁香花在线影院观看在线播放 | 国产成人精品三级麻豆 | 久久亚洲精品中文字幕无男同 | 国色天香社区在线视频 | 成熟女人特级毛片www免费 | 日日天干夜夜狠狠爱 | 2020最新国产自产精品 | 国产精品久久久 | 天堂亚洲2017在线观看 | 无码成人精品区在线观看 | 成人无码影片精品久久久 | 99久久人妻精品免费二区 | 国产一区二区三区四区五区加勒比 | 免费无码午夜福利片69 | 成人性做爰aaa片免费看 | 性欧美牲交xxxxx视频 | 国产精品久久久久久亚洲影视内衣 | 中文无码伦av中文字幕 | 内射爽无广熟女亚洲 | 台湾无码一区二区 | 国产综合在线观看 | 国产亚洲人成a在线v网站 | 国产亚洲视频中文字幕97精品 | 久久无码专区国产精品s | 老熟女重囗味hdxx69 | 极品尤物被啪到呻吟喷水 | 精品国产aⅴ无码一区二区 | 99久久久无码国产aaa精品 | 精品人人妻人人澡人人爽人人 | 久久99精品国产麻豆蜜芽 | 亚洲精品美女久久久久久久 | 亚洲精品国偷拍自产在线麻豆 | 一本色道久久综合亚洲精品不卡 | 国产色在线 | 国产 | 日产精品99久久久久久 | 丰满人妻被黑人猛烈进入 | 红桃av一区二区三区在线无码av | 亚洲国产一区二区三区在线观看 | 亚洲中文字幕无码中文字在线 | 国产成人精品久久亚洲高清不卡 | 真人与拘做受免费视频一 | 中文亚洲成a人片在线观看 | 国产精品igao视频网 | 国产国产精品人在线视 | 一二三四社区在线中文视频 | 国内丰满熟女出轨videos | 国产综合色产在线精品 | 精品偷自拍另类在线观看 | 成人无码影片精品久久久 | 日本欧美一区二区三区乱码 | 黑人巨大精品欧美一区二区 | 久久精品国产99精品亚洲 | 女人被男人爽到呻吟的视频 | www成人国产高清内射 | 给我免费的视频在线观看 | 99久久婷婷国产综合精品青草免费 | 久久国语露脸国产精品电影 | 亚洲成av人影院在线观看 | 亚洲性无码av中文字幕 | 清纯唯美经典一区二区 | 色欲人妻aaaaaaa无码 | 狠狠噜狠狠狠狠丁香五月 | 国产精品久久国产精品99 | 国产亚洲精品久久久久久 | 亚洲国产精品一区二区第一页 | 丰满人妻精品国产99aⅴ | 精品午夜福利在线观看 | 精品无码国产一区二区三区av | 一本久久伊人热热精品中文字幕 | 对白脏话肉麻粗话av | 女人高潮内射99精品 | 伊人久久大香线蕉亚洲 | 欧洲精品码一区二区三区免费看 | 国产精品-区区久久久狼 | 99精品国产综合久久久久五月天 | 精品国产aⅴ无码一区二区 | 国产人妻人伦精品1国产丝袜 | 澳门永久av免费网站 | 丰满少妇弄高潮了www | 国内揄拍国内精品人妻 | 荫蒂被男人添的好舒服爽免费视频 | 欧美丰满老熟妇xxxxx性 | 久久人人爽人人爽人人片av高清 | 成熟女人特级毛片www免费 | 18无码粉嫩小泬无套在线观看 | 扒开双腿疯狂进出爽爽爽视频 | 丰满少妇人妻久久久久久 | 中文字幕乱码人妻二区三区 | 亚洲经典千人经典日产 | 国产精品高潮呻吟av久久4虎 | 六月丁香婷婷色狠狠久久 | 白嫩日本少妇做爰 | 俺去俺来也在线www色官网 | 国产xxx69麻豆国语对白 | 久久国产36精品色熟妇 | 超碰97人人射妻 | 激情内射日本一区二区三区 | 亚洲欧美中文字幕5发布 | 中文无码成人免费视频在线观看 | 婷婷色婷婷开心五月四房播播 | 中文字幕无码av波多野吉衣 | 久久久国产精品无码免费专区 | 思思久久99热只有频精品66 | 欧美亚洲国产一区二区三区 | 亚洲小说春色综合另类 | 色婷婷综合激情综在线播放 | 中文无码伦av中文字幕 | 久久综合网欧美色妞网 | 中文亚洲成a人片在线观看 | 免费观看又污又黄的网站 | 日本在线高清不卡免费播放 | 亚洲自偷自偷在线制服 | 无码人妻久久一区二区三区不卡 | 亚洲国产日韩a在线播放 | 亚洲国产高清在线观看视频 | 99精品国产综合久久久久五月天 | 人妻体内射精一区二区三四 | 精品成在人线av无码免费看 | 少妇人妻大乳在线视频 | 亚洲国产高清在线观看视频 | 亚洲人成影院在线无码按摩店 | 中文字幕无码乱人伦 | 伊人久久大香线蕉av一区二区 | 久在线观看福利视频 | 久久99精品久久久久婷婷 | 日韩欧美中文字幕在线三区 | 无码人妻出轨黑人中文字幕 | a国产一区二区免费入口 | 午夜熟女插插xx免费视频 | 蜜臀av在线播放 久久综合激激的五月天 | 97久久超碰中文字幕 | 麻豆国产97在线 | 欧洲 | 日韩成人一区二区三区在线观看 | 免费观看又污又黄的网站 | 亚洲人成网站色7799 | 一区二区三区乱码在线 | 欧洲 | 国产偷自视频区视频 | 久久精品国产99久久6动漫 | 亚洲毛片av日韩av无码 | 色一情一乱一伦一视频免费看 | 中文字幕日韩精品一区二区三区 | 99久久久无码国产精品免费 | 国产后入清纯学生妹 | 亚洲国产日韩a在线播放 | 国产人妻久久精品二区三区老狼 | 亚洲精品国产a久久久久久 | 国产午夜精品一区二区三区嫩草 | 国产午夜无码精品免费看 | 国产又爽又黄又刺激的视频 | 国产精品99爱免费视频 | 人人澡人人透人人爽 | 黑人粗大猛烈进出高潮视频 | 天天躁夜夜躁狠狠是什么心态 | av香港经典三级级 在线 | 亚洲 日韩 欧美 成人 在线观看 | 欧美国产日韩亚洲中文 | 东京一本一道一二三区 | 国产午夜精品一区二区三区嫩草 | 亚洲自偷自拍另类第1页 | 久久国语露脸国产精品电影 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 97久久国产亚洲精品超碰热 | 久久久久久国产精品无码下载 | 成 人 免费观看网站 | 国产亚洲精品久久久久久久久动漫 | 国产亚洲tv在线观看 | 天天拍夜夜添久久精品 | 久久精品中文字幕大胸 | 东京一本一道一二三区 | 东京热一精品无码av | 国产亚洲视频中文字幕97精品 | 国产精品无套呻吟在线 | 国产精品久久国产三级国 | 骚片av蜜桃精品一区 | 色五月五月丁香亚洲综合网 | 国产成人综合色在线观看网站 | 在线视频网站www色 | 久久天天躁夜夜躁狠狠 | 亚洲日韩一区二区 | 成人aaa片一区国产精品 | 国内揄拍国内精品少妇国语 | 国产真实伦对白全集 | 中文字幕无码av波多野吉衣 | 国产激情无码一区二区app | 无码国模国产在线观看 | 亚洲精品久久久久avwww潮水 | 成人三级无码视频在线观看 | 欧美黑人性暴力猛交喷水 | 55夜色66夜色国产精品视频 | 国产成人无码av一区二区 | 天堂а√在线中文在线 | 国产办公室秘书无码精品99 | 精品日本一区二区三区在线观看 | 成人一区二区免费视频 | 国产在线精品一区二区高清不卡 | 亚洲人成网站色7799 | 国产精品永久免费视频 | 无遮挡国产高潮视频免费观看 | 亚洲精品成人福利网站 | 少妇人妻av毛片在线看 | 亚洲国产av精品一区二区蜜芽 | 国产精品久久久久9999小说 | 在教室伦流澡到高潮hnp视频 | 纯爱无遮挡h肉动漫在线播放 | 女人被男人爽到呻吟的视频 | 国产人妻精品一区二区三区不卡 | 好爽又高潮了毛片免费下载 | 在线精品国产一区二区三区 | 日韩精品a片一区二区三区妖精 | 精品国产麻豆免费人成网站 | 免费国产黄网站在线观看 | 亚洲人成影院在线无码按摩店 | 欧美zoozzooz性欧美 | 日本精品人妻无码免费大全 | 色综合久久久无码中文字幕 | 精品国精品国产自在久国产87 | 三级4级全黄60分钟 | 国产国产精品人在线视 | 日韩精品成人一区二区三区 | 天堂久久天堂av色综合 | 婷婷色婷婷开心五月四房播播 | 色婷婷av一区二区三区之红樱桃 | 色综合久久88色综合天天 | 天天摸天天透天天添 | 日韩av激情在线观看 | 激情内射亚州一区二区三区爱妻 | 亚洲无人区一区二区三区 | 国产又粗又硬又大爽黄老大爷视 | 鲁一鲁av2019在线 | 久久99精品国产.久久久久 | 精品国精品国产自在久国产87 | 国内精品久久久久久中文字幕 | 2020最新国产自产精品 | 99久久久国产精品无码免费 | 国产成人无码午夜视频在线观看 | 国产精品美女久久久久av爽李琼 | 欧美精品一区二区精品久久 | 中文字幕亚洲情99在线 | 欧美精品免费观看二区 | 免费播放一区二区三区 | 国产美女精品一区二区三区 | 久久久久久av无码免费看大片 | 疯狂三人交性欧美 | 久久99久久99精品中文字幕 | 久久人妻内射无码一区三区 | 国产精品永久免费视频 | 在线成人www免费观看视频 | 国产亚洲视频中文字幕97精品 | 中文字幕乱码人妻二区三区 | 久久久精品456亚洲影院 | 精品国产一区二区三区四区 | 久久久久成人精品免费播放动漫 | 欧美变态另类xxxx | 久久精品女人天堂av免费观看 | 精品亚洲韩国一区二区三区 | 日本精品久久久久中文字幕 | 亚洲日韩中文字幕在线播放 | 纯爱无遮挡h肉动漫在线播放 | 亚洲熟妇自偷自拍另类 | 亚洲 a v无 码免 费 成 人 a v | 国产真实伦对白全集 | 欧美日本免费一区二区三区 | 午夜福利试看120秒体验区 | 国精品人妻无码一区二区三区蜜柚 | 日韩成人一区二区三区在线观看 | 国产香蕉97碰碰久久人人 | 国产无遮挡又黄又爽又色 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 国产另类ts人妖一区二区 | 中文字幕乱码中文乱码51精品 | 成人亚洲精品久久久久软件 | 国产欧美熟妇另类久久久 | 无码av免费一区二区三区试看 | 亚洲欧美日韩成人高清在线一区 | 男人扒开女人内裤强吻桶进去 | 丰满人妻一区二区三区免费视频 | 76少妇精品导航 | 美女毛片一区二区三区四区 | 国产成人一区二区三区别 | 国产欧美精品一区二区三区 | 精品久久久久久亚洲精品 | 狠狠综合久久久久综合网 | 亚洲熟悉妇女xxx妇女av | 精品国产青草久久久久福利 | 亚洲国产精华液网站w | 99国产精品白浆在线观看免费 | 国产麻豆精品一区二区三区v视界 | 一区二区三区乱码在线 | 欧洲 | 午夜男女很黄的视频 | 婷婷综合久久中文字幕蜜桃三电影 | 在线 国产 欧美 亚洲 天堂 | 老太婆性杂交欧美肥老太 | 国产一区二区三区精品视频 | 亚洲中文字幕va福利 | 日韩欧美成人免费观看 | 强辱丰满人妻hd中文字幕 | 久久婷婷五月综合色国产香蕉 | 老司机亚洲精品影院无码 | 成在人线av无码免费 | 久久久精品国产sm最大网站 | 国产亚洲人成a在线v网站 | 亚洲一区二区三区国产精华液 | 伦伦影院午夜理论片 | 国产精品va在线播放 | 久久久精品欧美一区二区免费 | 妺妺窝人体色www在线小说 | 麻豆国产人妻欲求不满谁演的 | 久久人人爽人人爽人人片ⅴ | 7777奇米四色成人眼影 | 老太婆性杂交欧美肥老太 | 亚洲欧美精品伊人久久 | 日本一卡2卡3卡四卡精品网站 | 无套内谢老熟女 | 欧美精品无码一区二区三区 | 少妇人妻大乳在线视频 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久久精品国产sm最大网站 | 日本大乳高潮视频在线观看 | 草草网站影院白丝内射 | 装睡被陌生人摸出水好爽 | 日本一区二区三区免费高清 | 97久久国产亚洲精品超碰热 | 在线播放无码字幕亚洲 | 国精产品一品二品国精品69xx | 人人妻人人澡人人爽人人精品浪潮 | 久久精品中文闷骚内射 | 久久精品国产精品国产精品污 | v一区无码内射国产 | 亚洲日韩av一区二区三区中文 | 清纯唯美经典一区二区 | 久久久久人妻一区精品色欧美 | 欧美亚洲日韩国产人成在线播放 | 女人被男人爽到呻吟的视频 | 久久久久久a亚洲欧洲av冫 | 无码人妻少妇伦在线电影 | 亚洲综合无码一区二区三区 | 精品无码国产一区二区三区av | 国产欧美亚洲精品a | 熟女少妇在线视频播放 | 好爽又高潮了毛片免费下载 | 欧美肥老太牲交大战 | 无码帝国www无码专区色综合 | 欧美真人作爱免费视频 | 精品国产一区二区三区av 性色 | 六十路熟妇乱子伦 | 国产乡下妇女做爰 | 精品人妻av区 | 欧美自拍另类欧美综合图片区 | 亚洲熟妇色xxxxx欧美老妇y | 人妻少妇被猛烈进入中文字幕 | 夜夜躁日日躁狠狠久久av | 亚洲日韩乱码中文无码蜜桃臀网站 | 中文字幕中文有码在线 | 亚洲国产精品一区二区美利坚 | 国产内射爽爽大片视频社区在线 | 久久精品女人天堂av免费观看 | 伊人久久大香线焦av综合影院 | 日日干夜夜干 | 久久久久免费看成人影片 | 粗大的内捧猛烈进出视频 | 亚洲一区二区三区香蕉 | 久久精品国产精品国产精品污 | 国产精品久久国产精品99 | 天天躁夜夜躁狠狠是什么心态 | 中文字幕乱妇无码av在线 | 最近的中文字幕在线看视频 | 中文字幕亚洲情99在线 | 麻花豆传媒剧国产免费mv在线 | 国产福利视频一区二区 | 久久精品国产99久久6动漫 | 国产情侣作爱视频免费观看 | 欧美国产日韩亚洲中文 | 一本色道久久综合亚洲精品不卡 | 无码中文字幕色专区 | 国产精品丝袜黑色高跟鞋 | 久久99精品国产麻豆 | 丰满少妇人妻久久久久久 | 欧美人与善在线com | 精品国产一区av天美传媒 | 免费无码肉片在线观看 | 国产精品人人爽人人做我的可爱 | 欧美日韩人成综合在线播放 | 亚洲欧美国产精品专区久久 | 成人影院yy111111在线观看 | 国产性生大片免费观看性 | 无码av中文字幕免费放 | 亚洲成a人片在线观看日本 | 国产成人无码一二三区视频 | 波多野结衣高清一区二区三区 | www国产精品内射老师 | 强开小婷嫩苞又嫩又紧视频 | 国产高潮视频在线观看 | 日本大香伊一区二区三区 | www国产亚洲精品久久网站 | 秋霞特色aa大片 | 国产香蕉尹人综合在线观看 | 蜜桃臀无码内射一区二区三区 | 强辱丰满人妻hd中文字幕 | 久久精品人人做人人综合试看 | 麻豆精品国产精华精华液好用吗 | 国产成人综合在线女婷五月99播放 | 麻花豆传媒剧国产免费mv在线 | 99视频精品全部免费免费观看 | 丰满人妻一区二区三区免费视频 | 特级做a爰片毛片免费69 | 久久精品国产99久久6动漫 | 99er热精品视频 | 久久 国产 尿 小便 嘘嘘 | 丰满少妇人妻久久久久久 | 成熟妇人a片免费看网站 | 日本一卡2卡3卡四卡精品网站 | 精品少妇爆乳无码av无码专区 | 国产精品福利视频导航 | 色老头在线一区二区三区 | 欧美激情综合亚洲一二区 | 久久午夜无码鲁丝片午夜精品 | 中国女人内谢69xxxxxa片 | 国产免费久久精品国产传媒 | 国精品人妻无码一区二区三区蜜柚 | 特级做a爰片毛片免费69 | 国产三级精品三级男人的天堂 | 亚洲春色在线视频 | 国产麻豆精品一区二区三区v视界 | 日本www一道久久久免费榴莲 | 日本精品高清一区二区 | 国产无遮挡又黄又爽免费视频 | 99精品久久毛片a片 | 久久亚洲国产成人精品性色 | 日日躁夜夜躁狠狠躁 | 伊人久久大香线焦av综合影院 | 无码免费一区二区三区 | 少妇无套内谢久久久久 | 欧洲欧美人成视频在线 | 色窝窝无码一区二区三区色欲 | 在线播放亚洲第一字幕 | 激情爆乳一区二区三区 | 乱人伦人妻中文字幕无码 | 亚洲天堂2017无码中文 | 国内揄拍国内精品人妻 | 中文字幕乱码亚洲无线三区 | 伊人久久大香线蕉午夜 | 波多野结衣一区二区三区av免费 | 东北女人啪啪对白 | 97无码免费人妻超级碰碰夜夜 | 全球成人中文在线 | 精品 日韩 国产 欧美 视频 | 欧美xxxx黑人又粗又长 | 亚洲精品欧美二区三区中文字幕 | 国产精品怡红院永久免费 | 亚洲国产精品毛片av不卡在线 | 国产精品高潮呻吟av久久4虎 | 国产网红无码精品视频 | 亚洲娇小与黑人巨大交 | 久久99精品国产.久久久久 | 麻豆国产人妻欲求不满 | 精品熟女少妇av免费观看 | 国产乱码精品一品二品 | 国产激情无码一区二区 | 精品人妻中文字幕有码在线 | 国产人妻大战黑人第1集 | 撕开奶罩揉吮奶头视频 | 久久久国产一区二区三区 | 樱花草在线社区www | 又黄又爽又色的视频 | 欧美性黑人极品hd | 国产精品无码成人午夜电影 | 网友自拍区视频精品 | 亚洲精品综合五月久久小说 | 男女下面进入的视频免费午夜 | 澳门永久av免费网站 | 亚洲日本一区二区三区在线 | 久在线观看福利视频 | 国产成人无码一二三区视频 | 亚洲色无码一区二区三区 | 蜜臀av无码人妻精品 | 亚洲日韩一区二区三区 | 理论片87福利理论电影 | 精品人人妻人人澡人人爽人人 | 久久久精品欧美一区二区免费 | 7777奇米四色成人眼影 | 最近的中文字幕在线看视频 | 亚洲精品中文字幕乱码 | 国产深夜福利视频在线 | 久久久亚洲欧洲日产国码αv | 成人免费视频一区二区 | 性欧美熟妇videofreesex | 少妇人妻av毛片在线看 | 兔费看少妇性l交大片免费 | 99久久精品日本一区二区免费 | 55夜色66夜色国产精品视频 | 精品人人妻人人澡人人爽人人 | 亚洲а∨天堂久久精品2021 | 亚洲一区二区三区无码久久 | 亚洲毛片av日韩av无码 | 欧美成人高清在线播放 | 一本久久伊人热热精品中文字幕 | 日本在线高清不卡免费播放 | 东京热男人av天堂 | 亚洲精品国产精品乱码视色 | 国产亚洲精品久久久久久久 | 国产精品丝袜黑色高跟鞋 | 丝袜美腿亚洲一区二区 | 女人被爽到呻吟gif动态图视看 | 亚洲天堂2017无码中文 | 好男人www社区 | 人人澡人摸人人添 | 对白脏话肉麻粗话av | 亚洲一区二区三区在线观看网站 | 人妻中文无码久热丝袜 | 18禁黄网站男男禁片免费观看 | 中文字幕无码乱人伦 | 性生交大片免费看女人按摩摩 | 久久久久成人精品免费播放动漫 | 2019午夜福利不卡片在线 | 国产av一区二区精品久久凹凸 | 亚洲伊人久久精品影院 | 亚洲热妇无码av在线播放 | 国产乱码精品一品二品 | 亚洲综合无码久久精品综合 | 日本精品少妇一区二区三区 | 乱人伦人妻中文字幕无码 | 在线欧美精品一区二区三区 | 97精品国产97久久久久久免费 | 大乳丰满人妻中文字幕日本 | 色一情一乱一伦一区二区三欧美 | 日产精品99久久久久久 | 中文字幕无码热在线视频 | 丁香啪啪综合成人亚洲 | 精品aⅴ一区二区三区 | 亚洲色欲久久久综合网东京热 | 成人片黄网站色大片免费观看 | 国产精品亚洲а∨无码播放麻豆 | 天天躁日日躁狠狠躁免费麻豆 | 18禁黄网站男男禁片免费观看 | av无码电影一区二区三区 | 久久久www成人免费毛片 | 国产精品国产三级国产专播 | 久久精品国产日本波多野结衣 | 国语自产偷拍精品视频偷 | 欧美黑人性暴力猛交喷水 | 国产精品久久久久无码av色戒 | 成人aaa片一区国产精品 | 一本色道久久综合狠狠躁 | 红桃av一区二区三区在线无码av | 爱做久久久久久 | 国产香蕉97碰碰久久人人 | 无码国产激情在线观看 | 青青青手机频在线观看 | 青青青手机频在线观看 | 成人av无码一区二区三区 | 久久99精品国产.久久久久 | 奇米影视888欧美在线观看 | 国产真实伦对白全集 | www一区二区www免费 | 国产电影无码午夜在线播放 | 成人无码影片精品久久久 | 最近免费中文字幕中文高清百度 | 成 人 网 站国产免费观看 | 亚洲性无码av中文字幕 | 成在人线av无码免观看麻豆 | 欧美日韩综合一区二区三区 | 天海翼激烈高潮到腰振不止 | 狠狠色噜噜狠狠狠7777奇米 | 国产午夜精品一区二区三区嫩草 | 欧美亚洲国产一区二区三区 | 狠狠亚洲超碰狼人久久 | 中文字幕无码日韩专区 | 国产成人精品久久亚洲高清不卡 | 国产又爽又猛又粗的视频a片 | 国内精品一区二区三区不卡 | 嫩b人妻精品一区二区三区 | 精品久久久无码中文字幕 | 日本精品高清一区二区 | 高潮毛片无遮挡高清免费视频 | 亚洲第一无码av无码专区 | 欧美人妻一区二区三区 | 精品无码国产一区二区三区av | 日韩视频 中文字幕 视频一区 | 丰满肥臀大屁股熟妇激情视频 | 人人妻人人澡人人爽欧美精品 | 双乳奶水饱满少妇呻吟 | 国精品人妻无码一区二区三区蜜柚 | 国产电影无码午夜在线播放 | 性生交片免费无码看人 | 成人无码视频在线观看网站 | av在线亚洲欧洲日产一区二区 | 无码任你躁久久久久久久 | 国产精品久久久久9999小说 | 欧美激情内射喷水高潮 | 无码av免费一区二区三区试看 | 内射巨臀欧美在线视频 | 天天做天天爱天天爽综合网 | 国产婷婷色一区二区三区在线 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 狠狠噜狠狠狠狠丁香五月 | 成年美女黄网站色大免费视频 | 欧美三级a做爰在线观看 | 精品国产精品久久一区免费式 | 未满小14洗澡无码视频网站 | 国产精品毛片一区二区 | 欧洲精品码一区二区三区免费看 | 强辱丰满人妻hd中文字幕 | 久久99精品国产麻豆蜜芽 | 六月丁香婷婷色狠狠久久 | 国产 精品 自在自线 | 国产精品a成v人在线播放 | 国产极品美女高潮无套在线观看 | 国产区女主播在线观看 | 色 综合 欧美 亚洲 国产 | 亚洲精品久久久久中文第一幕 | 偷窥村妇洗澡毛毛多 | 狠狠综合久久久久综合网 | 97色伦图片97综合影院 | 亚洲狠狠色丁香婷婷综合 | 99久久亚洲精品无码毛片 | 精品国产国产综合精品 | 国产精品人人妻人人爽 | 嫩b人妻精品一区二区三区 | 久久99热只有频精品8 | 永久免费观看国产裸体美女 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 国产免费无码一区二区视频 | 国产高潮视频在线观看 | 亚洲男人av香蕉爽爽爽爽 | 成年美女黄网站色大免费全看 | 久久久精品欧美一区二区免费 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲精品久久久久avwww潮水 | 女人被男人躁得好爽免费视频 | 日本又色又爽又黄的a片18禁 | 红桃av一区二区三区在线无码av | 国产av人人夜夜澡人人爽麻豆 | 日韩在线不卡免费视频一区 | 久久zyz资源站无码中文动漫 | 国产成人精品视频ⅴa片软件竹菊 | 国产精品无码成人午夜电影 | 国产97色在线 | 免 | 国产亚洲日韩欧美另类第八页 | 欧美国产亚洲日韩在线二区 | 国产9 9在线 | 中文 | 久久99精品国产麻豆蜜芽 | 色婷婷综合激情综在线播放 | 精品夜夜澡人妻无码av蜜桃 | 亚洲欧美日韩国产精品一区二区 | 永久免费精品精品永久-夜色 | 男人扒开女人内裤强吻桶进去 | 国产成人无码区免费内射一片色欲 | 亚洲の无码国产の无码步美 | 狂野欧美性猛xxxx乱大交 | 男女下面进入的视频免费午夜 | 在线精品亚洲一区二区 | 国产后入清纯学生妹 | 色综合久久网 | 国产激情综合五月久久 | 高潮毛片无遮挡高清免费视频 | 捆绑白丝粉色jk震动捧喷白浆 | 欧美老熟妇乱xxxxx | 一本久道久久综合狠狠爱 | 国产人妻精品一区二区三区不卡 | 人人妻人人澡人人爽人人精品 | 伊在人天堂亚洲香蕉精品区 | 全黄性性激高免费视频 | 无码播放一区二区三区 | 亚洲综合无码久久精品综合 | 久久婷婷五月综合色国产香蕉 | 欧美日韩一区二区免费视频 | 色一情一乱一伦一视频免费看 | 人妻少妇精品无码专区动漫 | 一二三四在线观看免费视频 | 丰满少妇弄高潮了www | 国内少妇偷人精品视频免费 | 亚洲 激情 小说 另类 欧美 | 一个人看的视频www在线 | 亚洲 激情 小说 另类 欧美 | 特大黑人娇小亚洲女 | 福利一区二区三区视频在线观看 | 精品偷拍一区二区三区在线看 | 波多野结衣一区二区三区av免费 | 亚洲精品无码国产 | 久久精品国产99久久6动漫 | 老头边吃奶边弄进去呻吟 | 乌克兰少妇性做爰 | 97无码免费人妻超级碰碰夜夜 | 亚洲 日韩 欧美 成人 在线观看 | 在线天堂新版最新版在线8 | 国产精品久久久久影院嫩草 | 免费观看的无遮挡av | 国产成人久久精品流白浆 | 日韩精品乱码av一区二区 | 中文字幕久久久久人妻 | 无码人妻精品一区二区三区不卡 | 亚洲人成网站免费播放 | 亚洲自偷精品视频自拍 | 人妻少妇精品无码专区动漫 | 久久久无码中文字幕久... | 97精品国产97久久久久久免费 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产精品99久久精品爆乳 | 清纯唯美经典一区二区 | 久久精品一区二区三区四区 | 日本熟妇乱子伦xxxx | 久久99精品国产.久久久久 | 国产欧美精品一区二区三区 | 性欧美牲交在线视频 | 久青草影院在线观看国产 | 超碰97人人做人人爱少妇 | 在教室伦流澡到高潮hnp视频 | 国产猛烈高潮尖叫视频免费 | 无码人妻av免费一区二区三区 | 丰满诱人的人妻3 | 学生妹亚洲一区二区 | 国产人妻久久精品二区三区老狼 | 成人免费视频视频在线观看 免费 | 国产成人无码a区在线观看视频app | 成人免费无码大片a毛片 | 欧美国产日韩久久mv | 中文字幕乱码亚洲无线三区 | 国产精品自产拍在线观看 | 国产 精品 自在自线 | 精品无码国产一区二区三区av | 人妻中文无码久热丝袜 | 奇米影视888欧美在线观看 | a在线亚洲男人的天堂 | 亚洲日韩一区二区三区 | 性啪啪chinese东北女人 | 亚洲国产精品毛片av不卡在线 | 无码国模国产在线观看 | 狠狠噜狠狠狠狠丁香五月 | 97久久国产亚洲精品超碰热 | 国产亚洲精品久久久闺蜜 | 成人无码精品一区二区三区 | 色婷婷av一区二区三区之红樱桃 | 亚洲成熟女人毛毛耸耸多 | 伊人久久大香线焦av综合影院 | 日本一卡二卡不卡视频查询 | 双乳奶水饱满少妇呻吟 | 在线天堂新版最新版在线8 | 人妻无码αv中文字幕久久琪琪布 | 亚洲日本va午夜在线电影 | 久久久久亚洲精品男人的天堂 | 九月婷婷人人澡人人添人人爽 | 亚洲男女内射在线播放 | 色婷婷久久一区二区三区麻豆 | 欧美性生交xxxxx久久久 | 扒开双腿吃奶呻吟做受视频 | 久激情内射婷内射蜜桃人妖 | a国产一区二区免费入口 | 午夜福利一区二区三区在线观看 | 天天躁日日躁狠狠躁免费麻豆 | 精品国精品国产自在久国产87 | 少妇无码av无码专区在线观看 | 玩弄人妻少妇500系列视频 | 亚洲精品成a人在线观看 | 在线精品亚洲一区二区 | 日韩av无码中文无码电影 | www成人国产高清内射 | 中文字幕av无码一区二区三区电影 | 一本无码人妻在中文字幕免费 | 狂野欧美激情性xxxx | 丰腴饱满的极品熟妇 | 中国女人内谢69xxxxxa片 | 亚洲成a人片在线观看无码 | 天海翼激烈高潮到腰振不止 | 国产在线精品一区二区高清不卡 | 永久免费观看美女裸体的网站 | 天天摸天天碰天天添 | 99久久精品午夜一区二区 | 5858s亚洲色大成网站www | 亚洲精品国偷拍自产在线观看蜜桃 | 亚洲熟妇自偷自拍另类 | 狂野欧美激情性xxxx | 久久久久亚洲精品男人的天堂 | 伊人色综合久久天天小片 | 精品国产青草久久久久福利 | 无码人妻丰满熟妇区五十路百度 | 国产麻豆精品精东影业av网站 | 免费观看的无遮挡av | 欧美一区二区三区视频在线观看 | 亚洲国产精品美女久久久久 | 99久久99久久免费精品蜜桃 | 国产偷抇久久精品a片69 | 成人影院yy111111在线观看 | 无码精品人妻一区二区三区av | 香蕉久久久久久av成人 | 中文字幕久久久久人妻 | 无码乱肉视频免费大全合集 | 小sao货水好多真紧h无码视频 | 亚洲热妇无码av在线播放 | 国产猛烈高潮尖叫视频免费 | 国产亲子乱弄免费视频 | 少妇人妻大乳在线视频 | 久久亚洲精品中文字幕无男同 | 性生交大片免费看女人按摩摩 | 久久亚洲中文字幕精品一区 | 国内综合精品午夜久久资源 | 国产色视频一区二区三区 | 国产成人av免费观看 | 又大又紧又粉嫩18p少妇 | 久久精品国产一区二区三区肥胖 | 高清无码午夜福利视频 | 国产精品理论片在线观看 | 装睡被陌生人摸出水好爽 | 精品国产麻豆免费人成网站 | 一个人看的www免费视频在线观看 | 99麻豆久久久国产精品免费 | 亚洲高清偷拍一区二区三区 | 国产成人av免费观看 | 日日麻批免费40分钟无码 | 又大又硬又爽免费视频 | 亚洲精品国产品国语在线观看 | 任你躁在线精品免费 | 免费看男女做好爽好硬视频 | 精品亚洲成av人在线观看 | 欧美第一黄网免费网站 | 99国产精品白浆在线观看免费 | 国产精品久久久 | 日日橹狠狠爱欧美视频 | 亚洲成av人片在线观看无码不卡 | 红桃av一区二区三区在线无码av | 亚洲国产成人a精品不卡在线 | 国产人妖乱国产精品人妖 | 国产精品久久久久7777 | 日产精品高潮呻吟av久久 | 四虎4hu永久免费 | 爱做久久久久久 | 欧美大屁股xxxxhd黑色 | 精品厕所偷拍各类美女tp嘘嘘 | 中文字幕中文有码在线 | 无码国产乱人伦偷精品视频 | www国产亚洲精品久久久日本 | 国产精品高潮呻吟av久久 | 亚洲精品一区二区三区在线观看 | 又色又爽又黄的美女裸体网站 | 中文字幕无码视频专区 | 国产免费久久久久久无码 | 精品亚洲成av人在线观看 | 欧美日韩一区二区免费视频 | 午夜熟女插插xx免费视频 | 国产成人精品久久亚洲高清不卡 | 精品亚洲韩国一区二区三区 | 亚洲色偷偷偷综合网 | 久久天天躁狠狠躁夜夜免费观看 | 丰满护士巨好爽好大乳 | 色噜噜亚洲男人的天堂 | 蜜桃无码一区二区三区 | 俄罗斯老熟妇色xxxx | 色欲综合久久中文字幕网 | 又大又黄又粗又爽的免费视频 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产在线aaa片一区二区99 | 国产偷自视频区视频 | а天堂中文在线官网 | 九九在线中文字幕无码 | 中文字幕人妻丝袜二区 | 国产成人综合色在线观看网站 | 欧美变态另类xxxx | 熟妇女人妻丰满少妇中文字幕 | 亚洲精品久久久久avwww潮水 | 极品尤物被啪到呻吟喷水 | 一本色道久久综合狠狠躁 | 日日摸夜夜摸狠狠摸婷婷 | 国产深夜福利视频在线 | 真人与拘做受免费视频 | 国产人妻人伦精品1国产丝袜 | 国产成人午夜福利在线播放 | 水蜜桃亚洲一二三四在线 | 国产亚洲精品久久久久久大师 | 国产亚洲精品久久久久久久久动漫 | 精品无人区无码乱码毛片国产 | 四十如虎的丰满熟妇啪啪 | 亚洲色欲色欲欲www在线 | 国产成人av免费观看 | 精品一区二区三区波多野结衣 | 亚洲国产av精品一区二区蜜芽 | 妺妺窝人体色www在线小说 | 又大又硬又黄的免费视频 | 亚洲国产av美女网站 | 3d动漫精品啪啪一区二区中 | 亚洲 欧美 激情 小说 另类 | 国产av一区二区精品久久凹凸 | 最近免费中文字幕中文高清百度 | 久久精品国产99精品亚洲 | 国产精品无码永久免费888 | 兔费看少妇性l交大片免费 | 蜜臀av无码人妻精品 | 午夜男女很黄的视频 | 国产精品毛多多水多 | 精品国精品国产自在久国产87 | 国产综合在线观看 | 久久人人爽人人人人片 | 人人超人人超碰超国产 | 午夜成人1000部免费视频 | 人人妻人人藻人人爽欧美一区 | 激情内射亚州一区二区三区爱妻 | 久久亚洲国产成人精品性色 | 亚洲色成人中文字幕网站 | av小次郎收藏 | 久久久精品456亚洲影院 | 亚洲精品国产品国语在线观看 | 国产av人人夜夜澡人人爽麻豆 | 久久国产精品萌白酱免费 | 成年女人永久免费看片 | 国产精品人人爽人人做我的可爱 | 久久久久亚洲精品男人的天堂 | 荫蒂添的好舒服视频囗交 | 无码福利日韩神码福利片 | 性欧美牲交xxxxx视频 | 无码av岛国片在线播放 | 丰满人妻精品国产99aⅴ | 成年女人永久免费看片 | 成人免费视频视频在线观看 免费 | 2020久久香蕉国产线看观看 | 在线精品亚洲一区二区 | 玩弄少妇高潮ⅹxxxyw | 中文字幕无码免费久久99 | 麻豆国产人妻欲求不满 | 亚洲成av人片天堂网无码】 | 色综合视频一区二区三区 | 无码一区二区三区在线 | 波多野结衣乳巨码无在线观看 | 欧美老妇交乱视频在线观看 | 男女性色大片免费网站 | 又大又紧又粉嫩18p少妇 | 中文字幕色婷婷在线视频 | 亚洲国产精品成人久久蜜臀 | 亚洲欧美国产精品专区久久 | 精品久久久久久亚洲精品 | 又大又紧又粉嫩18p少妇 | 性色av无码免费一区二区三区 | 久久亚洲中文字幕精品一区 | 久久97精品久久久久久久不卡 | 无码任你躁久久久久久久 | 亚洲天堂2017无码 | 久久国语露脸国产精品电影 | 51国偷自产一区二区三区 | 久久久久久a亚洲欧洲av冫 | 国产欧美精品一区二区三区 | 国产成人综合色在线观看网站 | 久久久成人毛片无码 | 国产sm调教视频在线观看 | 亚洲中文字幕在线观看 | 国产精品视频免费播放 | 国产莉萝无码av在线播放 | 久久精品中文字幕大胸 | 无码国产色欲xxxxx视频 | 亚洲精品久久久久中文第一幕 | 日日鲁鲁鲁夜夜爽爽狠狠 | 人人妻人人澡人人爽欧美精品 | 男女性色大片免费网站 | 国产午夜无码精品免费看 | 东京无码熟妇人妻av在线网址 | 无码帝国www无码专区色综合 | 无码纯肉视频在线观看 | 欧美老熟妇乱xxxxx | 中文字幕 亚洲精品 第1页 | 午夜精品久久久内射近拍高清 | 成人无码视频免费播放 | 国产日产欧产精品精品app | 久久久国产精品无码免费专区 | 免费人成在线观看网站 | 久久国产自偷自偷免费一区调 | 中文字幕无码视频专区 | 免费国产黄网站在线观看 | 亚洲第一网站男人都懂 | 黑人巨大精品欧美一区二区 | 国产精品福利视频导航 | 欧美午夜特黄aaaaaa片 | 亚洲精品一区二区三区婷婷月 | 亚洲欧美色中文字幕在线 | √天堂中文官网8在线 | 国产亚洲人成a在线v网站 | 免费人成网站视频在线观看 | 97精品人妻一区二区三区香蕉 | 领导边摸边吃奶边做爽在线观看 | 亚洲日韩av一区二区三区四区 | 日日天日日夜日日摸 | 成年美女黄网站色大免费视频 | 色综合天天综合狠狠爱 | 人人妻人人澡人人爽人人精品浪潮 | 国产午夜精品一区二区三区嫩草 | 中文字幕久久久久人妻 | 麻豆国产人妻欲求不满谁演的 | 日本一卡二卡不卡视频查询 | 熟妇激情内射com | 国产97在线 | 亚洲 | 国产成人综合色在线观看网站 | 少妇愉情理伦片bd | 久久97精品久久久久久久不卡 | 一二三四在线观看免费视频 | 欧美亚洲国产一区二区三区 | 日日躁夜夜躁狠狠躁 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 人妻天天爽夜夜爽一区二区 | 亚洲国产精品毛片av不卡在线 | 亚洲日韩av一区二区三区四区 | 99视频精品全部免费免费观看 | 久久久久国色av免费观看性色 | 又大又硬又黄的免费视频 | 综合网日日天干夜夜久久 | 国内揄拍国内精品少妇国语 | 婷婷丁香六月激情综合啪 | 国产在线一区二区三区四区五区 | 少妇久久久久久人妻无码 | 欧美人与物videos另类 | 日韩人妻无码中文字幕视频 | 人妻互换免费中文字幕 | 国内少妇偷人精品视频免费 | 色综合久久88色综合天天 | 欧美日韩在线亚洲综合国产人 | 99久久无码一区人妻 | 无码av中文字幕免费放 | 99久久精品国产一区二区蜜芽 | 亚洲成色在线综合网站 | 青草青草久热国产精品 | 国产人妻大战黑人第1集 | 国产黄在线观看免费观看不卡 | 国产精品亚洲一区二区三区喷水 | 亚洲日韩av一区二区三区中文 | 国产成人无码一二三区视频 | 亚洲欧美精品aaaaaa片 | 蜜臀av无码人妻精品 | 牛和人交xxxx欧美 | 精品 日韩 国产 欧美 视频 | 少妇高潮喷潮久久久影院 | 亚洲伊人久久精品影院 | 国产又爽又黄又刺激的视频 | 日韩在线不卡免费视频一区 | 无码人妻av免费一区二区三区 | 国产午夜手机精彩视频 | 人人爽人人爽人人片av亚洲 | 噜噜噜亚洲色成人网站 | 老熟妇乱子伦牲交视频 | 97无码免费人妻超级碰碰夜夜 | 中文字幕av日韩精品一区二区 | 丰满人妻被黑人猛烈进入 | 亚洲欧美日韩综合久久久 | 风流少妇按摩来高潮 | 国产香蕉尹人视频在线 | 免费乱码人妻系列无码专区 | 日本爽爽爽爽爽爽在线观看免 | 亚洲综合精品香蕉久久网 | 欧美激情综合亚洲一二区 | 初尝人妻少妇中文字幕 | 亚洲自偷自偷在线制服 | 一本久久a久久精品vr综合 | 日日天干夜夜狠狠爱 | 精品人妻中文字幕有码在线 | 精品无人区无码乱码毛片国产 | 一个人看的视频www在线 | 亚洲人成网站在线播放942 | 高潮毛片无遮挡高清免费视频 | 性欧美videos高清精品 | 97资源共享在线视频 | 中文字幕av无码一区二区三区电影 | 日韩无码专区 | 亚洲日韩精品欧美一区二区 | 精品国产福利一区二区 | 亚洲欧美精品aaaaaa片 | 欧美真人作爱免费视频 | 精品欧美一区二区三区久久久 | 亚洲欧洲无卡二区视頻 | 色婷婷香蕉在线一区二区 | 中文久久乱码一区二区 | 乌克兰少妇xxxx做受 | 久久人人爽人人爽人人片ⅴ | 午夜丰满少妇性开放视频 | 亚洲a无码综合a国产av中文 | 久久天天躁狠狠躁夜夜免费观看 | 精品国产一区二区三区av 性色 | 亚洲国产综合无码一区 | 娇妻被黑人粗大高潮白浆 | 伊人久久大香线焦av综合影院 | 一本久久伊人热热精品中文字幕 | 亚洲国产午夜精品理论片 | 日本大乳高潮视频在线观看 | 国产成人无码av片在线观看不卡 | 国内老熟妇对白xxxxhd | 国产人成高清在线视频99最全资源 | www一区二区www免费 | 青草视频在线播放 | 人人澡人人透人人爽 | v一区无码内射国产 | 日本一卡2卡3卡四卡精品网站 | 国产国语老龄妇女a片 | 影音先锋中文字幕无码 | 精品偷自拍另类在线观看 | 骚片av蜜桃精品一区 | 窝窝午夜理论片影院 | 特黄特色大片免费播放器图片 | 学生妹亚洲一区二区 | 日韩无套无码精品 | 一本大道久久东京热无码av | 黄网在线观看免费网站 | 中文字幕av日韩精品一区二区 | 国产精品爱久久久久久久 | 久久久久免费精品国产 | 国产精品亚洲专区无码不卡 | 97资源共享在线视频 | 成人亚洲精品久久久久软件 | 欧美国产日韩久久mv | 无码任你躁久久久久久久 | 少妇一晚三次一区二区三区 | 欧美亚洲国产一区二区三区 | 国产极品视觉盛宴 | 麻豆精产国品 | 日本免费一区二区三区最新 | 无码av免费一区二区三区试看 | 久久精品人人做人人综合试看 | 男女下面进入的视频免费午夜 | 色偷偷人人澡人人爽人人模 | 久久久国产精品无码免费专区 | 人妻人人添人妻人人爱 | 久久午夜无码鲁丝片秋霞 | 欧美日本免费一区二区三区 | 欧美国产亚洲日韩在线二区 | 55夜色66夜色国产精品视频 | 久久亚洲中文字幕精品一区 | 国产网红无码精品视频 | 欧美 丝袜 自拍 制服 另类 | 亚洲色欲色欲天天天www | 日本熟妇大屁股人妻 | 白嫩日本少妇做爰 | 亚洲成av人在线观看网址 | 欧美野外疯狂做受xxxx高潮 | 日产精品99久久久久久 | 极品嫩模高潮叫床 | 亚洲欧美综合区丁香五月小说 | 伊人久久婷婷五月综合97色 | 又大又硬又爽免费视频 | 一本无码人妻在中文字幕免费 | 中文字幕人妻无码一区二区三区 | 蜜桃视频插满18在线观看 | 国产成人综合在线女婷五月99播放 | 亚洲欧美日韩成人高清在线一区 | 初尝人妻少妇中文字幕 | 久久久精品人妻久久影视 | 成人毛片一区二区 | 久久久久久久女国产乱让韩 | 麻豆果冻传媒2021精品传媒一区下载 | 偷窥日本少妇撒尿chinese | 粉嫩少妇内射浓精videos | 成年美女黄网站色大免费全看 | 乱人伦人妻中文字幕无码久久网 | 国产激情无码一区二区 | 内射后入在线观看一区 | 日韩精品成人一区二区三区 | 无码福利日韩神码福利片 | 亚洲中文字幕乱码av波多ji | 两性色午夜视频免费播放 | 亚洲精品www久久久 | 国产av剧情md精品麻豆 | 亚洲欧美日韩综合久久久 | 人人妻人人澡人人爽人人精品浪潮 | 久久熟妇人妻午夜寂寞影院 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 色狠狠av一区二区三区 | 亚洲成a人一区二区三区 | 亚洲精品国产a久久久久久 | 国产手机在线αⅴ片无码观看 | 国产成人无码av一区二区 | 无遮挡国产高潮视频免费观看 | 精品厕所偷拍各类美女tp嘘嘘 | 美女毛片一区二区三区四区 | 中文字幕中文有码在线 | 天堂亚洲免费视频 | 国产网红无码精品视频 | 久久久久久亚洲精品a片成人 | 香蕉久久久久久av成人 | 18精品久久久无码午夜福利 | 久久综合给合久久狠狠狠97色 | 久久无码专区国产精品s | 国产偷抇久久精品a片69 | 亚洲精品一区二区三区大桥未久 | 人人妻人人澡人人爽欧美精品 | aⅴ亚洲 日韩 色 图网站 播放 | 国产午夜福利亚洲第一 | 少妇厨房愉情理9仑片视频 | 男女猛烈xx00免费视频试看 | 暴力强奷在线播放无码 | 美女毛片一区二区三区四区 | 日产精品高潮呻吟av久久 | 国产美女精品一区二区三区 | 亚洲欧洲无卡二区视頻 | 亚洲国产欧美国产综合一区 | 亚洲熟妇色xxxxx欧美老妇y | 天天摸天天碰天天添 | 国产激情无码一区二区 | 日本饥渴人妻欲求不满 | 成人免费视频一区二区 | 国内少妇偷人精品视频 | 日日碰狠狠丁香久燥 | 久久久无码中文字幕久... | 国产av一区二区精品久久凹凸 | 国产精品多人p群无码 | 永久免费观看国产裸体美女 | 日韩亚洲欧美中文高清在线 | 国产亚洲美女精品久久久2020 | 天干天干啦夜天干天2017 | 99久久久国产精品无码免费 | 又紧又大又爽精品一区二区 | 帮老师解开蕾丝奶罩吸乳网站 | 精品一区二区三区波多野结衣 | 日本丰满护士爆乳xxxx | 久久久久99精品成人片 | 亚洲一区av无码专区在线观看 | 久久国产精品精品国产色婷婷 | 久久国语露脸国产精品电影 | 东京热男人av天堂 | 一区二区三区乱码在线 | 欧洲 | 欧美人与牲动交xxxx | 丰腴饱满的极品熟妇 | 欧美人与牲动交xxxx | 丰满少妇弄高潮了www | 午夜精品一区二区三区在线观看 | 人人妻人人澡人人爽人人精品浪潮 | 超碰97人人射妻 | 中文字幕无码免费久久9一区9 | 亚洲无人区一区二区三区 | 国产麻豆精品一区二区三区v视界 | 欧美freesex黑人又粗又大 | 一本久久a久久精品亚洲 | 在线观看欧美一区二区三区 | 久久久久久亚洲精品a片成人 | 露脸叫床粗话东北少妇 | 国产性生交xxxxx无码 | 国产在线精品一区二区三区直播 | 亚洲高清偷拍一区二区三区 | 三上悠亚人妻中文字幕在线 | 18禁黄网站男男禁片免费观看 | av香港经典三级级 在线 | 亚洲午夜福利在线观看 | 色一情一乱一伦一区二区三欧美 | 成人动漫在线观看 | 精品国产乱码久久久久乱码 | 伊人久久大香线蕉午夜 | 免费无码一区二区三区蜜桃大 | 久精品国产欧美亚洲色aⅴ大片 | 老熟妇乱子伦牲交视频 | 2020久久香蕉国产线看观看 | 亚洲人成网站色7799 | 国产精品久久久 | 久久久国产一区二区三区 | 国产乱码精品一品二品 | 午夜精品久久久久久久久 | 亚洲精品中文字幕久久久久 | 俺去俺来也在线www色官网 | 国产欧美熟妇另类久久久 | 国产人妻久久精品二区三区老狼 | 日本爽爽爽爽爽爽在线观看免 | 一二三四社区在线中文视频 | 欧美成人免费全部网站 | 日本一区二区三区免费高清 | 老熟妇乱子伦牲交视频 | 在线精品亚洲一区二区 | 天天燥日日燥 | 亚洲 a v无 码免 费 成 人 a v | 欧美精品国产综合久久 | 中文精品无码中文字幕无码专区 | 狠狠色噜噜狠狠狠狠7777米奇 | а√资源新版在线天堂 | 国产猛烈高潮尖叫视频免费 | 亚洲国产欧美国产综合一区 | 色窝窝无码一区二区三区色欲 | 丰满人妻精品国产99aⅴ | 色综合久久88色综合天天 | 在教室伦流澡到高潮hnp视频 | 国产综合色产在线精品 | 亚洲熟妇自偷自拍另类 | 成 人 网 站国产免费观看 | 国产熟女一区二区三区四区五区 | 日日麻批免费40分钟无码 | 国产欧美亚洲精品a | 精品偷拍一区二区三区在线看 | 欧美熟妇另类久久久久久多毛 | 一本色道久久综合狠狠躁 | 色情久久久av熟女人妻网站 | 亚洲中文无码av永久不收费 | 亚欧洲精品在线视频免费观看 | 少妇性荡欲午夜性开放视频剧场 | 99精品久久毛片a片 | 国产内射爽爽大片视频社区在线 | 国产精品第一国产精品 | 曰韩少妇内射免费播放 | 97夜夜澡人人双人人人喊 | 窝窝午夜理论片影院 | 欧洲熟妇精品视频 | 偷窥日本少妇撒尿chinese | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 亚洲欧洲日本无在线码 | 国产精品久久久久久亚洲影视内衣 | 国产在线精品一区二区高清不卡 | 亚洲午夜福利在线观看 | 色噜噜亚洲男人的天堂 | 亚洲精品久久久久中文第一幕 | 久青草影院在线观看国产 | 国产av剧情md精品麻豆 | 2019午夜福利不卡片在线 | 日韩亚洲欧美中文高清在线 | 国产成人精品视频ⅴa片软件竹菊 | 国产午夜无码精品免费看 | 亚洲国产精品成人久久蜜臀 | 欧美精品国产综合久久 | 亚洲中文字幕久久无码 | 国产成人一区二区三区别 | 亚洲s码欧洲m码国产av | 俺去俺来也在线www色官网 | 少妇人妻av毛片在线看 | 特黄特色大片免费播放器图片 | 亚洲国产高清在线观看视频 | 免费国产成人高清在线观看网站 | 亚洲伊人久久精品影院 | 亚洲一区二区三区偷拍女厕 | 亚洲色大成网站www国产 | 97久久国产亚洲精品超碰热 | aⅴ亚洲 日韩 色 图网站 播放 | 国产精品永久免费视频 | 色婷婷综合激情综在线播放 | 欧美三级a做爰在线观看 | 国产人成高清在线视频99最全资源 | 97久久精品无码一区二区 | 又粗又大又硬又长又爽 | 国产凸凹视频一区二区 | 国产婷婷色一区二区三区在线 | 国产小呦泬泬99精品 | 国产两女互慰高潮视频在线观看 | 国产午夜福利亚洲第一 | 无码av最新清无码专区吞精 | 欧美人与牲动交xxxx | 成人一在线视频日韩国产 | 亚洲自偷自拍另类第1页 | 国产无遮挡吃胸膜奶免费看 | 丰满人妻被黑人猛烈进入 | 内射后入在线观看一区 | ass日本丰满熟妇pics | 麻豆国产人妻欲求不满谁演的 | 久久久亚洲欧洲日产国码αv | 中文字幕无码av激情不卡 | 在线观看欧美一区二区三区 | 乱人伦人妻中文字幕无码 | 日韩精品一区二区av在线 | 欧美猛少妇色xxxxx | 欧美精品无码一区二区三区 | 久久99精品国产.久久久久 | 一本久道高清无码视频 | 国产偷国产偷精品高清尤物 | 97久久超碰中文字幕 | 成人无码视频免费播放 | 四十如虎的丰满熟妇啪啪 | 国产精品二区一区二区aⅴ污介绍 | 精品无码av一区二区三区 | 日韩av无码一区二区三区 | 精品偷拍一区二区三区在线看 | 国产明星裸体无码xxxx视频 | 荫蒂添的好舒服视频囗交 | 久久午夜无码鲁丝片秋霞 | 精品国产麻豆免费人成网站 | 国产成人精品久久亚洲高清不卡 | 日本va欧美va欧美va精品 | 中文字幕无码日韩欧毛 | 久久精品无码一区二区三区 | 成年美女黄网站色大免费视频 | 东京热无码av男人的天堂 | 国产亚洲视频中文字幕97精品 | 久久精品视频在线看15 | 99久久久无码国产精品免费 | 人人妻人人藻人人爽欧美一区 | 午夜免费福利小电影 | 亚洲日韩一区二区三区 | 人妻少妇精品无码专区二区 | 久久无码专区国产精品s | 狠狠色丁香久久婷婷综合五月 | 国产无av码在线观看 | 久久精品国产大片免费观看 | 一本加勒比波多野结衣 | 中文无码伦av中文字幕 | 十八禁视频网站在线观看 | 麻豆国产人妻欲求不满谁演的 | 黑人大群体交免费视频 | 欧美 丝袜 自拍 制服 另类 | 好男人www社区 | 丝袜 中出 制服 人妻 美腿 | 中文字幕无线码 | 性生交片免费无码看人 | 亚洲精品久久久久avwww潮水 | 国产片av国语在线观看 | 中文字幕人妻无码一区二区三区 | 国产精品久久国产精品99 | 青青青爽视频在线观看 | 亚洲 a v无 码免 费 成 人 a v | 色欲综合久久中文字幕网 | 丰满人妻被黑人猛烈进入 | 少妇人妻大乳在线视频 | 精品亚洲韩国一区二区三区 | 六十路熟妇乱子伦 | 国产精品免费大片 | 国精产品一品二品国精品69xx | 曰本女人与公拘交酡免费视频 | 国产三级久久久精品麻豆三级 | 日韩人妻无码中文字幕视频 | 亚洲日本一区二区三区在线 | 人妻天天爽夜夜爽一区二区 | 人妻天天爽夜夜爽一区二区 | 三上悠亚人妻中文字幕在线 | 精品一区二区不卡无码av | 牲欲强的熟妇农村老妇女 | 中文字幕中文有码在线 | 亚洲成a人片在线观看无码3d | 亚洲 另类 在线 欧美 制服 | 狂野欧美激情性xxxx | 欧美亚洲国产一区二区三区 | 国产成人无码一二三区视频 | 99久久精品国产一区二区蜜芽 | 99麻豆久久久国产精品免费 | 国产成人无码区免费内射一片色欲 | 色偷偷人人澡人人爽人人模 | 人妻无码αv中文字幕久久琪琪布 | 日本精品久久久久中文字幕 | 无码午夜成人1000部免费视频 | 色噜噜亚洲男人的天堂 | 亚洲 日韩 欧美 成人 在线观看 | 欧美刺激性大交 | 夜夜高潮次次欢爽av女 | 男女作爱免费网站 | 奇米影视7777久久精品 | 久久久久久久女国产乱让韩 | 久久久精品成人免费观看 | 黑人巨大精品欧美黑寡妇 | 亚洲精品美女久久久久久久 | 亚洲国产av美女网站 | 久久伊人色av天堂九九小黄鸭 | 亚洲精品美女久久久久久久 | 日日干夜夜干 | 丰满岳乱妇在线观看中字无码 | 免费乱码人妻系列无码专区 | 精品久久久无码人妻字幂 | 男人的天堂av网站 | 亚洲啪av永久无码精品放毛片 |