日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不一样 使用别名 数据字段和bean_【修炼内功】[spring-framework] [3] Bean是如何创建又是如何销毁的?...

發(fā)布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不一样 使用别名 数据字段和bean_【修炼内功】[spring-framework] [3] Bean是如何创建又是如何销毁的?... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


書接上文,在 [spring-framework] [2] BeanDefinitionReader 一文中簡單介紹了XMLBeanFactory解析xml配置、并注冊BeanDefinition的邏輯,本文就bean的實例化過程及銷毀做簡要分析

先放一張大圖(點擊圖片放大查看,右鍵或長按保存后更清晰),展示完整的bean創(chuàng)建過程及銷毀過程,如果對spring原理有一些理解可將此圖作為開發(fā)過程中的參考,如果對spring原理還有一些模糊可繼續(xù)向下閱讀(長文預(yù)警!)

BeanDefinition

通過前文簡單了解到,Spring在初始化過程中并不是直接實例化bean,而是先收集所有bean的元數(shù)據(jù)信息并注冊,bean的元數(shù)據(jù)描述為接口BeanDefinition,該接口定義了你能想到的一切有關(guān)bean的屬性信息

BeanDefinition衍生出一系列實現(xiàn)類

  • AbstractBeanDefinition
    如同其他Spring類,大部分BeanDefinition接口的邏輯都由該抽象類實現(xiàn)
  • GenericBeanDefinitionGenericBeanDefinition是一站式、用戶可見的bean definition,如何理解“用戶可見”?
    可見的bean definition意味著可以在該bean definition上定義post-processor來對bean進行操作
  • RootBeanDefinition
    當bean definition存在父子關(guān)系的時候,RootBeanDefinition用來承載父元數(shù)據(jù)的角色(也可獨立存在),同時它也作為一個可合并的bean definition使用,在Spring初始化階段,所有的bean definition均會被(向父級)合并為RootBeanDefinition,子bean definition(GenericBeanDefinition/ChildBeanDefinition)中的定義會覆蓋其父bean definition(由parentName指定)的定義
  • ChildBeanDefinition
    當bean definition存在父子關(guān)系的時候,ChildBeanDefinition用來承載子元數(shù)據(jù)的角色(也可獨立存在),在Spring推出GenericBeanDefinition后,其完全可以被GenericBeanDefinition替代,目前使用場景已經(jīng)非常少
  • AnnotatedBeanDefinition
    如其名,主要用來定義注解場景的bean definition
    • ScannedGenericBeanDefinition
      主要用來定義@Component、@Service等bean definition,其AnnotationMetadata metadata屬性用來存儲該bean的類注解信息
    • AnnotatedGenericBeanDefinition
      與ScannedGenericBeanDefinition不同的是,其主要用來定義@Configuration等配置類中@Bean的bean definition,其AnnotationMetadata metadata屬性與ScannedGenericBeanDefinition相同,MethodMetadata factoryMethodMetadata屬性用來存儲@Bean描述的方法信息

BeanDefinitionHolder只是簡單捆綁了BeanDefinition、bean-name、bean-alias,用于注冊BeanDefinition及別名alias

BeanRegistry

在一般工程中,bean的定義分散在各種地方(尤其使用注解之后),Spring并不能在解析出每一個bean的元數(shù)據(jù)信息后立即對該bean做實例化動作,對于依賴的分析與注入、類(方法)的代理、功能上的擴展等,必須等所有的bean元數(shù)據(jù)全部解析完成之后才能進行

在bean元數(shù)據(jù)解析完成之后、bean實例化之前,對bean的元數(shù)據(jù)信息有一個暫存的過程,這個過程便是bean的注冊

bean的注冊邏輯分兩步,一為BeanDefinition的注冊,一為別名的注冊

  • BeanDefinition注冊的定義在BeanDefinitionRegistry#registerBeanDefinition,其實現(xiàn)使用一個Map來保存bean-name和BeanDefinition的關(guān)系
  • 別名的注冊定義在AliasRegistry#registerAlias,其實現(xiàn)同樣使用一個Map來保存別名alias-name和bean-name(或另一個別名alias-name)的關(guān)系

在完成bean的元數(shù)據(jù)注冊之后,便是根據(jù)詳盡的元數(shù)據(jù)信息進行實例化了

BeanFactory

bean的實例化過程比較復(fù)雜(Spring考慮到了各種場景),附上BeanRegistry&BeanFactory相關(guān)的類依賴圖

初看此圖,請不要失去信心和耐心,圖中各類的作用會一一講解(見 #附錄#相關(guān)類說明),這里先介紹幾個核心的接口

  • AliasRegistry
    bean別名注冊和管理
  • BeanDefinitionRegistry
    bean元數(shù)據(jù)注冊和管理
  • SingletonBeanRegistry
    單例bean注冊和管理
  • BeanFactory
    bean工廠,提供各種bean的獲取及判斷方法

大致瀏覽上圖(類依賴圖)不難發(fā)現(xiàn),核心實現(xiàn)落在了DefaultListableBeanFactory,我們以此類作為切入點分析bean實例化過程

bean的實例化過程發(fā)生在getBean調(diào)用階段(對于singleton則發(fā)生在首次調(diào)用階段),getBean的實現(xiàn)方法眾多,我們追根溯源,找到最通用的方法AbstractBeanFactory#doGetBean

// org.springframework.beans.factory.support.AbstractBeanFactory protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 1. 獲取真正的beanNamefinal String beanName = transformedBeanName(name);Object bean;// 2. 嘗試獲取(提前曝光的)singleton bean實例(為了解決循環(huán)依賴)Object sharedInstance = getSingleton(beanName);// 3. 如果存在if (sharedInstance != null && args == null) { ... }// 4. 如果不存在else { ... }// 5. 嘗試類型轉(zhuǎn)換if (requiredType != null && !requiredType.isInstance(bean)) { ... }return (T) bean; }

bean的實例化過程雖然復(fù)雜,但大體邏輯非常清楚

接下,就以上五個子流程(藍色部分)一一展開

在實例化bean的過程當中,Spring會使用大量的中間態(tài)來判斷、處理各種場景和情況,此處先行列出Spring所使用的一些關(guān)鍵的中間態(tài)(各中間態(tài)的作用會在下文介紹,見 #附錄#中間態(tài)說明),以便在下文中更好地理解bean實例化過程中對各種情況的判斷和處理邏輯

bean name轉(zhuǎn)換

在使用bean-name獲取bean的時候,除了可以使用原始bean-name之外,還可以使用alias別名等,bean-name的轉(zhuǎn)換則是將傳入的‘bean-name’一層層轉(zhuǎn)為最原始的bean-name

Return the bean name, stripping out the factory dereference prefix if necessary, and resolving aliases to canonical names.protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name)); }

函數(shù)canonicalName的作用則是利用別名注冊aliasMap,將別名alias轉(zhuǎn)為原始bean-name

函數(shù)transformedBeanName比較特殊,其是將FactoryBean的bean-name前綴 '&' 去除(BeanFactory#FACTORY_BEAN_PREFIX 下文會介紹)

嘗試獲取單例

拿到原始的bean-name之后,便可以實例化bean或者直接獲取已經(jīng)實例化的singleton-bean,此處為什么叫‘嘗試’獲取呢?

在獲取singleton-bean的時候一般存在三種情況:1. 還未實例化(或者不是單例);2. 已經(jīng)實例化;3. 正在實例化;

  • 對于 “1. 還未實例化” ,返回null即可,后續(xù)進行實例化動作
  • 對于“2. 已經(jīng)實例化”,直接返回實例化的singleton-bean
  • 對于“3. 正在實例化”,則較難理解

Spring中對于singleton-bean,有一個sharedInstance的概念,在調(diào)用getSingleton函數(shù)時,返回的不一定是完全實例化的singleton-bean,有可能是一個中間狀態(tài)(創(chuàng)建完成,但未進行屬性依賴注入及其他后處理邏輯),這種中間狀態(tài)會通過getSingleton函數(shù)提前曝光出來,目的是為了解決循環(huán)依賴(下文會詳細介紹循環(huán)依賴)

在實例化beanA的過程中,需要依賴beanB和beanC,如果beanC同時又依賴beanA,則需要beanA在實例化完成之前提前曝光出來,以免造成beanA等待beanC實例化完成,beanC等待beanA實例化完成,類似一種死鎖的狀態(tài)

在繼續(xù)進行之前,有必要簡單介紹幾個中間態(tài)(詳見 #附錄#中間態(tài)說明)

  • singletonObjects
    緩存已經(jīng)實例化完成的singleton-bean
  • earlySingletonObjects
    緩存正在實例化的、提前曝光的singleton-bean,用于處理循環(huán)依賴
  • singletonFactories
    緩存用于生成earlySingletonObject的 ObjectFactory
ObjectFactory,定義了一個用于創(chuàng)建、生成對象實例的工廠方法java @FunctionalInterface public interface ObjectFactory<T> { T getObject() throws BeansException; }

介紹了上述之后,再來描述getSingleton的邏輯就會比較清楚

不用糾結(jié)上述中間態(tài)的值是何時被設(shè)置進去的,下文會逐步提及

FactoryBean處理(sharedInstance存在的邏輯)

上述 sharedInstance 一定是我們需要的bean實例么?未必!

定義bean的時候可以通過實現(xiàn)FactoryBean接口來定制bean實例化的邏輯,以此增加更多的靈活性及可能性

How to use the Spring FactoryBean? | Baeldung?www.baeldung.com@Bean(initMethod = "init", destroyMethod = "destroy") public FactoryBean myBean() {return new FactoryBean<MyBean>() {/*** 定制bean初始化邏輯*/@Overridepublic MyBean getObject() throws Exception {MyBean myBean = new MyBean();// ... 定制化的邏輯return myBean;}/*** 真正的bean類型*/@Overridepublic Class<?> getObjectType() {return MyBean.class;}@Overridepublic boolean isSingleton() {return true;}} }

通過注冊FactoryBean類型的bean,實例化后的原始實例類型同樣為FactoryBean,但我們需要的是通過FactoryBean#getObject方法得到的實例,這便需要針對FactoryBean做一些處理,這也是接下來要講解的函數(shù)AbstractBeanFactory#getObjectForBeanInstance

Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.
Now we have the bean instance, which may be a normal bean or a FactoryBean. If it's a FactoryBean, we use it to create a bean instance.

該函數(shù)要實現(xiàn)的邏輯比較簡單,如果sharedInstance是 FactoryBean,則使用getObject方法創(chuàng)建真正的實例

getObjectForBeanInstance是一個通用函數(shù),并不只針對通過getSingleton得到的sharedInstance,任何通過緩存或者創(chuàng)建得到的 rawInstance,都需要經(jīng)過getObjectForBeanInstance處理,拿到真正需要的 beanInstance

簡單介紹getObjectForBeanInstance函數(shù)的入?yún)?/p>/*** @param beanInstance sharedInstance / rawInstance,可能為FactoryBean* @param name 傳入的未做轉(zhuǎn)換的 bean name* @param beanName 對name做過轉(zhuǎn)換后的原始 canonical bean name* @param mbd 合并后的RootBeanDefinition,下文會介紹*/ protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)

getObjectForBeanInstance函數(shù)的處理邏輯

上圖中有一個邏輯判斷,如果入?yún)ame以'&' (BeanFactory#FACTORY_BEAN_PREFIX)開頭則直接返回(BeanFactory)

這里兼容了一種情況,如果需要獲取/注入FactoryBean而不是getObject生成的實例,則需要在bean-name/alias-name前加入'&'

/*** 注入FactoryBean#getObject生成的實例*/ @Autowired private MyBean myBean;/*** 直接注入FactoryBean*/ @Resource(name = "&myBean") private FactoryBean<MyBean> myFactoryBean;

對于singleton,FactoryBean#getObject的結(jié)果會被緩存到factoryBeanObjectCache,對于緩存中不存在或者不是singleton的情況,會通過FactoryBean#getObject生成(上圖中藍色未展開的邏輯)

Spring并非簡單的調(diào)用FactoryBean#getObject,而是分為兩部分處理

bean instance生成

上圖中doGetObjectFromFactoryBean,主要對getObject方法進行了包裝,判斷是否需要在SecurityManager框架內(nèi)執(zhí)行以及對null結(jié)果進行封裝(NullBean)

bean instance后處理

上圖中postProcessObjectFromFactoryBean,主要對生成的bean instance做一些后處理(可以跟蹤到AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization),

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {// 拿到所有注冊的BeanPostProcessor,執(zhí)行后處理動作Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result; }

postProcessAfterInitialization函數(shù)可以對現(xiàn)有bean instance做進一步的處理,甚至可以返回新的bean instance,這就為bean的增強提供了一個非常方便的擴展方式(可以思考一下,AOP的代理類是如何生成的)

加載bean實例(sharedInstance不存在的邏輯)

以上,討論了bean instance存在于緩存中的情況,如果緩存中不存則需要進行bean的加載

簡單來講,bean的加載/創(chuàng)建分為三大部分

  • 將BeanDefinition合并為RootBeanDefinition
    這里類似類繼承,子BeanDefinition屬性會覆蓋父BeanDefinition
  • 依次加載所依賴的bean
    對于有依賴的情況,優(yōu)先遞歸加載依賴的bean
  • 按照不同的bean類型,根據(jù)BeanDefinition的定義進行加載/創(chuàng)建
  • BeanDefinition合并(RootBeanDefinition)

    將BeanDefinition轉(zhuǎn)為RootBeanDefinition,如果存在父子關(guān)系,則進行合并

    這里不再贅述,可以參考 AbstractBeanFactory#getMergedLocalBeanDefinition

    加載depends-on beans

    String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) {// 遍歷所有的依賴for (String dep : dependsOn) {// 檢測循環(huán)依賴if (isDependent(beanName, dep)) { /* throw exception */ }// 注冊依賴關(guān)系registerDependentBean(dep, beanName);// 遞歸getBean,加載依賴beantry { getBean(dep); }catch (NoSuchBeanDefinitionException ex) { /* throw exception */ }} }

    邏輯很簡單,但這里涉及到兩個中間態(tài)dependentBeanMap、dependenciesForBeanMap

    • dependentBeanMap
      存儲哪些bean依賴了我(哪些bean里注入了我)
      如果 beanB -> beanA, beanC -> beanA,key為beanA,value為[beanB, beanC]
    • dependenciesForBeanMap
      存儲我依賴了哪些bean(我注入了哪些bean)
      如果 beanA -> beanB, beanA -> beanC,key為beanA,value為[beanB, beanC]

    理解兩者的存儲關(guān)系,有助于在閱讀源碼的過程中理解bean的加載和銷毀順序

    加載singleton bean實例

    if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {// singletonFactory - ObjectFactorytry { return createBean(beanName, mbd, args); }catch (BeansException ex) { destroySingleton(beanName); throw ex; }});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }

    這里涉及兩個比較核心的函數(shù)createBean、getObjectForBeanInstance

    • createBean
      根據(jù)BeanDefinition的內(nèi)容,創(chuàng)建/初始化bean instance
    • getObjectForBeanInstance
      上文已經(jīng)介紹過,主要處理FactoryBean,將FactoryBean轉(zhuǎn)為真正需要的bean instance

    createBean被包裝在lambda(singletonFactory)中作為getSingleton的參數(shù),我們來看getSingleton的實現(xiàn)邏輯

    所以,關(guān)鍵的邏輯在createBean函數(shù)中,bean的創(chuàng)建邏輯較為復(fù)雜,我們放到后面介紹

    加載prototype bean實例

    else if (mbd.isPrototype()) {Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally { afterPrototypeCreation(beanName); }bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }

    prototype bean的創(chuàng)建與singleton bean類似,只是不會緩存創(chuàng)建完成的bean

    加載其他scope bean實例

    scope,即作用域,或者可以理解為生命周期

    上文介紹了singleton-bean及prototype-bean的創(chuàng)建過程,嚴格意義上講以上兩種都是一種特殊的scope-bean,分別對應(yīng)ConfigurableBeanFactory#SCOPE_SINGLETON及ConfigurableBeanFactory#SCOPE_PROTOTYPE,前者作用域為整個IOC容器,也可理解為單例,后者作用域為所注入的bean,每次注入(每次觸發(fā)getBean)都會重新生成

    Spring中還提供很多其他的scope,如WebApplicationContext#SCOPE_REQUEST或WebApplicationContext#SCOPE_SESSION,前者作用域為一次web request,后者作用域為一個web session周期

    自定義scope的bean實例創(chuàng)建過程與singleton bean的創(chuàng)建過程十分相似,需要實現(xiàn)Scope的get方法(org.springframework.beans.factory.config.Scope#get),

    else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) { /* throw exception */ }try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);// createBean被封裝在Scope#get函數(shù)的lambda參數(shù)ObjectFactory中try { return createBean(beanName, mbd, args); }finally { afterPrototypeCreation(beanName); }});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);} catch (IllegalStateException ex) { /* throw exception */} }

    Scope接口除了get方法之外,還有一個remove方法,前者用于定義bean的初始化邏輯,后者用于定義bean的銷毀邏輯

    public interface Scope {/*** Return the object with the given name from the underlying scope*/Object get(String name, ObjectFactory<?> objectFactory);/*** Remove the object with the given name from the underlying scope.*/Object remove(String name); }

    WebApplicationContext#SCOPE_SESSION對應(yīng)的Scope實現(xiàn)見org.springframework.web.context.request.SessionScope

    WebApplicationContext#SCOPE_REQUEST對應(yīng)的Scope實現(xiàn)見org.springframework.web.context.request.RequestScope

    以上兩種Scope實現(xiàn)都較為簡單,前者將初始化的bean存儲在request attribute種,后者將初始化的bean存儲在http session中,具體細節(jié)請自行查閱源碼

    Q: Spring中實現(xiàn)了哪些Scope?又是什么時候注冊的?

    Bean創(chuàng)建過程

    AbstractAutowireCapableBeanFactory#createBean

    了解bean創(chuàng)建的過程也是一個抽絲剝繭的過程,真正創(chuàng)建的過程封裝在AbstractAutowireCapableBeanFactory#doCreateBean中,而在此之前有一些準備工作,整體流程如下圖

  • resolveBeanClass
  • 這一步驟用于鎖定bean class,在沒有顯示指定beanClass的情況下,使用className加載beanClass

    2. 驗證method overrides

    在 [spring-framework] [2] BeanDefinitionReader 一文中有提到過lookup-method及replace-method,該步驟是為了確認以上兩種配置中的method是否存在

    3. 執(zhí)行InstantiationAwareBeanPostProcessor前處理器(postProcessBeforeInstantiation)

    這里要特別注意的是,如果這個步驟中生成了“代理”bean instance,則會有一個短路操作,直接返回該bean instance而不再執(zhí)行doCreate,這是一個“細思極恐”的操作,但在一些特殊場景(尤其框架之中)提供了良好的擴展機制

    try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {// 如果這里生成了代理的bean instance會直接返回return bean;} } cache (Throwable ex) { // throw exception }try {// 創(chuàng)建bean instanceObject beanInstance = doCreateBean(beanName, mbdToUse, args);// ... }Q: InstantiationAwareBeanPostProcessor的使用場景有哪些?Spring有哪些功能使用了InstantiationAwareBeanPostProcessor?它們是在什么時候注冊的?

    4. doCreateBean (AbstractAutowireCapableBeanFactory)
    真正bean的創(chuàng)建及初始化過程在此處實現(xiàn),但Spring對bean創(chuàng)建及初始化邏輯的復(fù)雜程度完全超出了本篇文章之承載,這里只對一些關(guān)鍵的邏輯做梳理

    創(chuàng)建bean實體

    AbstractAutowireCapableBeanFactory#createBeanInstance

    從上面的流程圖可以看出,創(chuàng)建bean實體不一定會使用到構(gòu)造函數(shù),有兩個特殊的方式

    1. instance supplier

    AbstractAutowireCapableBeanFactory#obtainFromSupplier

    從Spring5開始,多了一種以函數(shù)式注冊bean的方式(參考https://www.baeldung.com/spring-5-functional-beans)

    // 注冊MyService context.registerBean(MyService.class, () -> new MyService()); // 注冊MyService,并指定bean name context.registerBean("mySecondService", MyService.class, () -> {MyService myService = new MyService();// 其他的邏輯return myService; }); // 注冊MyService,指定bean name,并增強bean definition context.registerBean("myCallbackService", MyService.class, () -> {MyService myService = new MyService();// 其他的邏輯return myService; }), bd -> bd.setAutowireCandidate(false));

    或者

    // 構(gòu)建BeanDefinition BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MyService.class, () -> {MyService myService = new MyService();// 其他的邏輯return myService; }); // 注冊BeanDefinition beanFactory.registerBeanDefinition("myService", bd);

    通過以上方式注冊的bean,Spring會調(diào)用該supplier生成bean實體

    2. factory method

    AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod

    ConstructorResolver#instantiateUsingFactoryMethod

    在xml配置中還有一種不太常見的bean注冊方式

    public class MyHome {// 靜態(tài)方法public static MyHome create() {return new MyHome();} }public class MyFactory {// 非靜態(tài)方法public MyHome create() {return new MyHome();} }<bean id="myFactory" class="com.manerfan.MyFactory"></bean><!-- 方式一 --> <!-- 使用指定類的靜態(tài)方法 --> <bean id="myHome1" class="com.manerfan.MyHome" factory-method="create"></bean> <!-- 方式二 --> <!-- 使用指定bean的非靜態(tài)方法 --> <bean id="myHome2" class="com.manerfan.MyHome" factory-method="create" factory-bean="myFactory"></bean>

    Spring會通過指定類的指定方法生成bean實體,其中有兩種方式,一種方式(僅指定factory-method)使用指定類的靜態(tài)方法生成,另一種方式(同時指定factory-method和factory-bean)使用指定bean的非靜態(tài)方法生成

    同時factory-method中還允許傳入一些參數(shù),如果存在同名函數(shù),Spring會根據(jù)參數(shù)的個數(shù)及類型找到匹配的method

    public class MyHome {private MyHouse house;private MyCar car;// setters }public class MyFactory {// 攜帶入?yún)ublic MyHome create(MyHouse house, MyCar car) {MyHome myHome = new MyHome();myHome.setHouse(house);myHome.setCar(car)return myHome;}// 同名函數(shù)public MyHome create(MyHouse house) {MyHome myHome = new MyHome();myHome.setHouse(house);myHome.setCar(defaultCar)return myHome;} }<bean id="myHome2" class="com.manerfan.MyHome" factory-method="create" factory-bean="myFactory"><!-- 這里使用的是構(gòu)造函數(shù)參數(shù)類型 --><constructor-arg name="house" ref="house"/><constructor-arg name="car" ref="car"/> </bean>

    這樣的代碼是不是讓你想到了@Configuration中的@Bean,@Bean所修飾方法如果存在參數(shù)的話,Spring會通過參數(shù)的類型及名稱自動進行依賴注入

    @Configuration public class MyFactory {@Beanpublic MyHome create(MyHouse house, MyCar car) {MyHome myHome = new MyHome();myHome.setHouse(house);myHome.setCar(car)return myHome;} }

    我們可以大膽猜測,@Configuration + @Bean的實現(xiàn)方式就是factory-bean + factory-method,在后文介紹Spring的注解體系時會揭曉

    使用指定(類)bean的(靜態(tài))方法創(chuàng)建bean實體的邏輯在ConstructorResolver#instantiate(String, RootBeanDefinition, Object, Method, args),而真正的邏輯在SimpleInstantiationStrategy#instantiate(RootBeanDefinition, String, BeanFactory, Object, Method, Object...),其核心的執(zhí)行邏輯非常簡單,有了方法factoryMethod(factoryBean)及入?yún)rgs,便可以調(diào)用該方法創(chuàng)建bean實體

    Object result = factoryMethod.invoke(factoryBean, args);

    factoryBean可以通過beanFactory.getBean獲取到(正是當前在講的邏輯),factoryMethod可以通過反射獲取到,入?yún)rgs如何獲取?這便涉及到Spring中的一個重要概念 -- 依賴注入,如何準確的找到依賴的實體并將其注入,便是接下來的重點,這里涉及到一個非常重要的函數(shù)ConstructorResolver#resolvePreparedArguments,該函數(shù)的作用是將BeanDefinition中定義的入?yún)⑥D(zhuǎn)換為真是需要的參數(shù)(xml中定義的或者注解中定義的),在[spring-framework] [2] BeanDefinitionReader 一文中有過介紹,ref會被封裝為RuntimeBeanReference存儲、value會被封裝為TypedStringValue存儲等等,如何將這些封裝好的存儲類型轉(zhuǎn)為真正需要的函數(shù)參數(shù),便是ConstructorResolver#resolvePreparedArguments函數(shù)的作用

    這里分成了三大分支

  • resolveValueIfNecessary
  • 針對BeanMetadataElement,進行值的轉(zhuǎn)換,其中又會包含特別細的分支,大致如下

    • RuntimeBeanNameReference
      AbstractBeanFactory#evaluateBeanDefinitionString
      支持Spl表達式解析bean name
    • BeanDefinitionHolder 、BeanDefinition
      BeanDefinitionValueResolver#resolveInnerBean
      與createBean函數(shù)的邏輯類似,創(chuàng)建一個inner bean
    • DependencyDescriptor
      AutowireCapableBeanFactory#resolveDependency
      用來處理OptionalBean、LazyBean、AutowireCandidateBean等(詳見下文“注解注入”一節(jié))
    • ManagedArray、ManagedList、ManagedSet、ManagedMap
      BeanDefinitionValueResolver#resolveManagedArray
      BeanDefinitionValueResolver#resolveManagedList
      BeanDefinitionValueResolver#resolveManagedSet
      BeanDefinitionValueResolver#resolveManagedMap
      內(nèi)部遞歸使用resolveValueIfNecessary方法獲取bean并最終封裝成對應(yīng)的類型
    • ManagedProperties
      通過BeanDefinitionValueResolver#evaluate(Spel)計算value的值,最終封裝為Properties
    • TypedStringValue
      通過BeanDefinitionValueResolver#evaluate(Spel)計算value的值

    對于這部分內(nèi)容,Spring在接下來的發(fā)展中可能還會不斷地擴充

    2. String

    AbstractBeanFactory#evaluateBeanDefinitionString

    與resolveValueIfNecessary中的RuntimeBeanNameReference一致,支持Spl表達式解析表達式

    3. 其他

    • InjectionPoint
      使用ThreadLocal提供當前bean被注入到的注入點,可以參考
    What's New in Spring 4.3? | Baeldung?www.baeldung.com@Bean @Scope("prototype") public Logger logger(InjectionPoint injectionPoint) {// return MyComponent.classreturn Logger.getLogger(injectionPoint.getMethodParameter().getContainingClass()); }@Component public class MyComponent {@Autowiredprivate Logger logger; }
    • 其他
      與resolveValueIfNecessary中的DependencyDescriptor一致,用來處理OptionalBean、LazyBean等
    需要留意的是,上述在進行依賴注入的過程中,都會調(diào)用DefaultSingletonBeanRegistry#registerDependentBean方法,將各bean之間的依賴關(guān)系保存起來,如同前文在介紹加載depends-on時一致,bean之間的依賴關(guān)系會分別存放在dependentBeanMap及dependenciesForBeanMap之中(下文在介紹屬性注入的時候亦是如此),這對于bean銷毀順序的理解起著至關(guān)重要的作用

    在返回之前還有convertIfNecessary的方法調(diào)用,該函數(shù)是將上述解析得到的值轉(zhuǎn)換為函數(shù)參數(shù)真正的類型

    為何要轉(zhuǎn)換?其實上述過程拿到的值并非真正需要的值,如

    public class MyComponent {private Resource initSql; }<bean id="myComponent" class="com.manerfan.MyComponent"><property name="initSql" value="classpath:/init/sql/init.sql"></property> </bean>

    或者

    public class MyComponent {@Value("${init.sql}")// or @Value("classpath:/init/sql/init.sql")private Resource initSql; } init.sql=classpath:/init/sql/init.sql

    不論哪種形式,在convertIfNecessary之前解析到的值都是字符串 "classpath:/init/sql/init.sql",convertIfNecessary的作用便是將上述解析得到的值轉(zhuǎn)換為函數(shù)參數(shù)真正的類型Resource

    convert的邏輯在TypeConverterDelegate#convertIfNecessary,其內(nèi)部基本的邏輯為

  • 找到合適的PropertyEditor (propertyEditorRegistry)
  • 使用PropertyEditor的setValue/getValue方法進行轉(zhuǎn)換
  • 將url轉(zhuǎn)換為Resource的PropertyEditor對應(yīng)為 org.springframework.core.io.ResourceEditor,正是使用ResourceEditor將 字符串"classpath:/init/sql/init.sql”轉(zhuǎn)為對應(yīng)的Resource

    Q: Spring默認的PropertyEditor有哪些?又是什么時候注冊的?

    3. 有參構(gòu)造函數(shù)

    AbstractAutowireCapableBeanFactory#autowireConstructor

    ConstructorResolver#autowireConstructor

    使用有參構(gòu)造函數(shù)創(chuàng)建bean實例的一個點在于尋找與參數(shù)相對應(yīng)的構(gòu)造函數(shù)(可能定義了多個構(gòu)造函數(shù)),而對于參數(shù)的解析和轉(zhuǎn)換(參數(shù)的依賴注入)則與使用factory method一樣,調(diào)用ConstructorResolver#resolvePreparedArguments函數(shù)進行處理,這里不再重復(fù)描述

    在拿到真實的入?yún)⒓皩?yīng)的構(gòu)造函數(shù)后,下一步便是使用構(gòu)造函數(shù)來創(chuàng)建bean實例,但事情貌似也并沒有那么簡單

    實例化的過程在ConstructorResolver#instantiate,內(nèi)部并沒有統(tǒng)一利用反射技術(shù)直接使用構(gòu)造函數(shù)創(chuàng)建,而是分為兩種情況

    一種,沒有設(shè)置override-method時,直接使用構(gòu)造函數(shù)創(chuàng)建

    一種,在設(shè)置了override-method時,使用cglib技術(shù)構(gòu)造代理類,并代理override方法

    以上,Spring默認的實例化策略為CglibSubclassingInstantiationStrategy

    4. 無參構(gòu)造函數(shù)

    AbstractAutowireCapableBeanFactory#instantiateBean

    無參構(gòu)造函數(shù)創(chuàng)建bean實例的過程與有參構(gòu)造函數(shù)創(chuàng)建過程完全一致,只是少了參數(shù)的依賴注入,使用默認無參構(gòu)造函數(shù)進行實例化

    BeanDefinition后處理

    AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

    在屬性注入之前提供一次機會來對BeanDefinition進行處理,內(nèi)部執(zhí)行所有注冊MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法

    在閱讀源碼時注意到一個MergedBeanDefinitionPostProcessor的實現(xiàn)類 AutowiredAnnotationBeanPostProcessor,深入到實現(xiàn)內(nèi)部AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata,其實現(xiàn)了兩個注解類的解析 @Value 及 @Autowired ,找到注解修飾的Filed或者Method并緩存,具體的邏輯會在屬性注入一節(jié)中詳細介紹

    Q: Spring注冊了哪些MergedBeanDefinitionPostProcessor?它們都是做什么用的?又是什么時候注冊的?

    提前暴露實體

    DefaultSingletonBeanRegistry#addSingletonFactory -> AbstractAutowireCapableBeanFactory#getEarlyBeanReference

    還記得上文介紹的“嘗試獲取單例”(AbstractBeanFactory.getSingleton)么?為了解決循環(huán)依賴會將singleton-bean提前暴露出來,暴露的邏輯會封裝為ObjectFactory(AbstractAutowireCapableBeanFactory#getEarlyBeanReference實現(xiàn))緩存在DefaultSingletonBeanRegistry.singletonFactories中,在getBean的邏輯getSingleton中會執(zhí)行ObjectFactory的邏輯將singleton提前暴露

    此時暴露的singleton-bean僅完成了bean的實例化,屬性注入、初始化等邏輯均暫未執(zhí)行

    屬性注入

    AbstractAutowireCapableBeanFactory#populateBean

    在“創(chuàng)建bean實體”小節(jié)中介紹了factory method方式及有參構(gòu)造函數(shù)方式的參數(shù)注入邏輯,除此之外還有一種注入便是屬性注入

    流程圖中兩次出現(xiàn)了InstantiationAwareBeanPostProcessor,還記得在“Bean創(chuàng)建過程”小結(jié)中介紹的InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation么?如果該步驟生成了“代理”bean instance,則會有一個短路操作,直接返回該bean instance而不再執(zhí)行后續(xù)的doCreate

    InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation同樣是一個短路操作,如果有任意一個InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法返回false,則會跳出屬性注入的邏輯,官方對此的解釋如下

    Give any InstantiationAwareBeanPostProcessors the opportunity to modify the state of the bean before properties are set. This can be used, for example, to support styles of field injection.

    autowireByName及autowireByType方法作為“候補”補充BeanDefinition的propertyValues

    Fill in any missing property values with references to other beans.

    PropertyValue中記錄了需要注入的屬性信息及需要注入的屬性值,那BeanDefinition的propertyValues都來自哪里?xml中的bean配置、自定義的BeanDefinition等

    public class MyService {/*** string*/private String name;/*** resource*/private Resource res;/*** bean ref*/private MyComponent myComponent; }

    xml中定義PropertyValue

    <bean id="myMyService" class="com.manerfan.MyService"><property name="name" value="SpringDemoApp"></property><property name="res" value="classpath:/init/init.sql"></property><property name="myComponent" ref="myComponent"></property> </bean>

    BeanDefinition中直接定義PropertyValue

    // 構(gòu)建BeanDefinition BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MyService.class).addPropertyValue("name", "${spring.application.name}").addPropertyValue("res", "classpath:/init/init.sql").addPropertyReference("myComponent", "myComponent").getBeanDefinition(); // 注冊BeanDefinition beanFactory.registerBeanDefinition("myService", bd);

    所有的ProperValue均會在AbstractAutowireCapableBeanFactory#applyPropertyValues中進行依賴的解析、轉(zhuǎn)換并設(shè)置到bean實例對應(yīng)的屬性中,詳細的邏輯下文介紹

    注解注入

    除此之外通過注解修飾的屬性(方法)是如何注入的?

    public class MyService {/*** string*/@Value("${spring.application.name}")private String name;/*** resource*/@Value("classpath:/init/init.sql")private Resource res;/*** bean ref by parameter*/@Autowired@Qualifier("myComponent1")// or @Resource("myComponent1")// or @Injectprivate MyComponent myComponent1;private MyComponent myComponent2;/*** bean ref by setter method*/@Autowiredpublic void setMyComponet2(@Qualifier("myComponent1") MyComponet component) {this.myComponent2 = component} }各注解的使用可以參考 https://www.baeldung.com/spring-annotations-resource-inject-autowireWiring in Spring: @Autowired, @Resource and @Inject | Baeldung?www.baeldung.com

    在AbstractAutowireCapableBeanFactory#applyPropertyValues之前發(fā)現(xiàn)還有一個動作InstantiationAwareBeanPostProcessor#postProcessProperties(是的InstantiationAwareBeanPostProcessor又出現(xiàn)了),在此有兩個實現(xiàn)引起了我的注意AutowiredAnnotationBeanPostProcessor#postProcessProperties及CommonAnnotationBeanPostProcessor#postProcessProperties,我們來對比兩個實現(xiàn)的內(nèi)部邏輯

    // AutowiredAnnotationBeanPostProcessor#postProcessProperties public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);} catch (Throwable ex) { /* handle exception */ }return pvs; } // CommonAnnotationBeanPostProcessor#postProcessProperties public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);} catch (Throwable ex) { /* handle exception */ }return pvs; }

    從代碼及流程圖可以看出,兩種實現(xiàn)的差異僅在InjectionMetadata的查找邏輯,一個個來

    AutowiredAnnotation

    AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata的核心邏輯可以追蹤到AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

    CommonAnnotation

    CommonAnnotationBeanPostProcessor#findResourceMetadata的核心邏輯可以追蹤到CommonAnnotationBeanPostProcessor.buildResourceMetadata

    InjectionElement

    以上,對于不同的注解不同的方式(屬性/方法),會被封裝為不同的InjectionElement,并最終將所有的InjectionElement封裝在InjectionMetadata中

    在找到InjectionElement之后,下一步便是依賴的解析和注入了(InjectionMetadata#inject)

    這里的邏輯無非就是遍歷內(nèi)部所有的InjectionElement并執(zhí)行InjectionElement.inject,上面已經(jīng)介紹,對于不同的注解不同的方式(屬性/方法),會被封裝為不同的InjectionElement,那不同的InjectionElement也會有不同的inject邏輯,至此我們大致可以理出一個注解注入的大框架

    所以,歸根結(jié)底,注入的過程在AutowiredFieldElement、AutowiredMethodElement、ResourceElement、等InjectionElement內(nèi)部,在繼續(xù)進行之前有必要了解一下DefaultListableBeanFactory#resolveDependency

    還記得上文“創(chuàng)建bean實體”一節(jié)中介紹參數(shù)的注入時提到的AutowireCapableBeanFactory#resolveDependency么?該函數(shù)正是調(diào)用了DefaultListableBeanFactory#resolveDependency,上文并未詳細展開該函數(shù)的邏輯實現(xiàn),其除了處理OptionalBean、及LazyBean之外,我們比較關(guān)心的邏輯在DefaultListableBeanFactory#doResolveDependency

    該函數(shù)處理了@Value、@Qualifier、@Primary、@Order等的邏輯

    @Value的解析有兩個過程,1. StringValueResolver解析(${spring.sql.init} -> classpath:/init/init.sql);2. PropertyEditor轉(zhuǎn)換(classpath:/init/init.sql -> Resouce);

    AutowiredFieldElement無非就是使用DefaultListableBeanFactory#doResolveDependency將依賴的bean解析到,并設(shè)置到對應(yīng)的屬性上

    AutowiredMethodElement則是使用DefaultListableBeanFactory#doResolveDependency將參數(shù)對應(yīng)依賴的bean解析到,并執(zhí)行對應(yīng)的方法

    Q: 我們是否可以自定義注解(InstantiationAwareBeanPostProcessor),來實現(xiàn)類似 @Value、@Autowired 的功能?

    屬性注入

    AbstractAutowireCapableBeanFactory#applyPropertyValues

    還記得在一開始提到的BeanDefinition中的propertyValues么?(xml中的bean配置、自定義的BeanDefinition,也有可能來自InstantiationAwareBeanPostProcessor#postProcessProperties),至此這一部分的屬性還未注入依賴

    PropertyValue中記錄了需要注入的屬性,已經(jīng)依賴的類型(String、RuntimeBeanReference、等),根據(jù)不同的類型解析依賴的bean并設(shè)置到對應(yīng)的屬性上(此過程與DefaultListableBeanFactory#doResolveDependency極其相似,不再贅述)

    初始化

    AbstractAutowireCapableBeanFactory#initializeBean

    以上,完成了bean實例的創(chuàng)建和屬性注入,之后還有一些初始化的方法,比如各種Aware的setXxx是如何調(diào)用的、@PostConstruct是怎么調(diào)用的?

    Q: Aware類有很多,除了上圖中的三種之外,其他的Aware是什么時候調(diào)用的?
    Q: @PreDestroy是如何調(diào)用的?destroy-method是何時執(zhí)行的?
    Q: AbstractAdvisingBeanPostProcessor都做了什么?是如何處理AOP代理的?

    注冊Disposable

    AbstractBeanFactory#registerDisposableBeanIfNecessary

    至此,終于完成了bean實例的創(chuàng)建、屬性注入以及之后的初始化,此后便可以開始使用了

    在使用Spring的過程中經(jīng)常還會碰到設(shè)置銷毀邏輯的情況,如數(shù)據(jù)庫連接池、線程池等等,在Spring銷毀bean的時候還需要做一些處理,類似于C++中的析構(gòu)

    在bean的創(chuàng)建邏輯中,最后一個步驟則是注冊bean的銷毀邏輯(DisposableBean)

    銷毀邏輯的注冊有幾個條件

  • 非prototype(singleton或者注冊的scope)
  • 非NullBean
  • 指定了destroy-method(如xml中指定或者BeanDefinition中直接設(shè)置)或者存在@PreDestroy注解的方法(CommonAnnotationBeanPostProcessor.requiresDestruction)
  • if (!mbd.isPrototype() && requiresDestruction(bean, mbd))

    滿足以上條件的bean會被封裝為DisposableBeanAdapter,并注冊在DefaultSingletonBeanRegistry.disposableBeans中(詳見附錄#中間態(tài)說明)

    Q: 理解了bean的銷毀注冊邏輯,那bean的銷毀時何時觸發(fā)以及如何執(zhí)行的?

    嘗試類型轉(zhuǎn)換

    以上,完成了bean的創(chuàng)建、屬性的注入、dispose邏輯的注冊,但獲得的bean類型與實際需要的類型可能依然不相符,在最終交付bean之前(getBean)還需要進行一次類型轉(zhuǎn)換,上文反復(fù)提到過PropertyEditor,此處不例外,使用的既是PropertyEditor進行的類型轉(zhuǎn)換,具體的邏輯不再贅述,再將bean轉(zhuǎn)換為真正需要的類型后,便完成了整個getBean的使命

    Bean銷毀過程

    了解了bean的完成創(chuàng)建過程后,那bean是如何銷毀的呢?

    bean的創(chuàng)建過程始于DefaultListableBeanFactory.getBean,銷毀過程則終于ConfigurableApplicationContext#close,跟蹤下去,具體的邏輯在DefaultSingletonBeanRegistry#destroySingletons

    // org.springframework.beans.factory.support.DefaultSingletonBeanRegistry public void destroySingletons() {synchronized (this.singletonObjects) {this.singletonsCurrentlyInDestruction = true;}String[] disposableBeanNames;synchronized (this.disposableBeans) {disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());}for (int i = disposableBeanNames.length - 1; i >= 0; i--) {// 遍歷注冊的DisposableBeandestroySingleton(disposableBeanNames[i]);}// 清理各種緩存this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();clearSingletonCache(); }

    在介紹bean創(chuàng)建的時候提到過兩個概念

  • DefaultSingletonBeanRegistry.disposableBeans
  • 需要注冊銷毀邏輯的bean會被封裝為DisposableBeanAdapter并緩存在此處

    2. DefaultSingletonBeanRegistry.dependentBeanMap

    對于存在依賴注入關(guān)系的bean,會將bean的依賴關(guān)系緩存在此處(dependentBeanMap: 哪些bean依賴了我; dependenciesForBeanMap: 我依賴了哪些bean)

    從上圖中可以看出,bean的銷毀順序與創(chuàng)建順序正好相反,如果有 beanA --dependsOn--> beanB --> beanC ,創(chuàng)建(getBean)時一定是beanC -> beanB -> beanA,銷毀時一定是 beanA -> beanB -> beanC,以此避免因為依賴關(guān)系造成的一些異常情況

    循環(huán)依賴

    在介紹Bean創(chuàng)建的時候提到過earlySingletonObject,為了解決循環(huán)依賴的問題,在實例化完后屬性注入之前會提前將當前的bean實體暴露出來,以防止在屬性注入過程中所注入的bean又依賴當前的bean造成的類似“死鎖”的狀態(tài),但即便有這樣的邏輯還是要注意幾點

    顯示設(shè)置dependsOn的循環(huán)依賴

    @DependsOn("beanB") @Component public class BeanA {}@DependsOn("beanC") @Component public class BeanB {}@DependsOn("beanA") @Component public class BeanC {}

    dependsOn的依賴,在bean的創(chuàng)建之前便會處理

    Spring在實例化以上bean時,在創(chuàng)建BeanA之前會觸發(fā)創(chuàng)建BeanB,創(chuàng)建BeanB之前會觸發(fā)創(chuàng)建BeanC,而創(chuàng)建BeanC之前又會觸發(fā)創(chuàng)建BeanA,由此引發(fā)一個無解的循環(huán)依賴

    構(gòu)造函數(shù)循環(huán)依賴

    @Component public class BeanA {public BeanA(BeanB beanB) {} }@Component public class BeanB {public BeanB(BeanC beanC) {} }@Component public class BeanC {public BeanC(BeanA beanA) {} }

    與dependsOn一樣的原理,構(gòu)造函數(shù)參數(shù)依賴,同樣在bean的創(chuàng)建之前便會處理,從而引發(fā)無解的循環(huán)依賴

    factory-method依賴

    @Bean public BeanA beanA(BeanB beanB) {return new BeanA(); }@Bean public BeanB beanB(BeanC beanC) {return new BeanB(); }@Bean public BeanC beanC(BeanA beanA) {return new BeanC(); }

    原理與上述相同,不再贅述

    顯示dependsOn、構(gòu)造函數(shù)依賴、factory-method依賴任意混合

    @DependsOn("beanB") @Component public class BeanA { }@Component public class BeanB {public BeanB(BeanC beanC) {} }@Bean public BeanC beanC(BeanA beanA) {return new BeanC(); }

    似乎我們找到了一定的規(guī)律,只要一個循環(huán)依賴中的所有bean,其依賴關(guān)系都需要在創(chuàng)建bean實例之前進行解決,此循環(huán)依賴則一定無解

    打破無解的循環(huán)依賴

    還以上述三個Bean為例,先將其中任意一個依賴設(shè)置為屬性依賴(屬性依賴的處理,在bean實例創(chuàng)建完成且暴露earlySingleton之后)

    @Component public class BeanA {@Autowiredprivate BeanB beanB; }@Component public class BeanB {public BeanB(BeanC beanC) {} }@Bean public BeanC beanC(BeanA beanA) {return new BeanC(); }

    @DependsOn("beanB") @Component public class BeanA { }@Component public class BeanB {private BeanC beanC;@Resourcepublic void setBeanC(BeanC beanC) {this.beanC = beanC;} }@Bean public BeanC beanC(BeanA beanA) {return new BeanC(); }

    等等

    為了避免無解的循環(huán)依賴,在構(gòu)成循環(huán)依賴的一個環(huán)中,只需要保證其中至少一個bean的依賴在該bean創(chuàng)建且暴露earlySingleton之后處理即可

    我們以“bean創(chuàng)建且暴露earlySingleton”為節(jié)點,在此之前處理依賴的有instance supplier parameter、factory method parameter、constructor parameter、等,在此之后處理的依賴有 class property、setter parameter、等

    小結(jié)

    本文介紹了Spring體系內(nèi)bean的創(chuàng)建及銷毀過程,在經(jīng)過萬次的commit后,也造就了Spring一定程度上的復(fù)雜度

    本文并未全方位的詮釋bean的創(chuàng)建過程,文中遺留了很多疑問點,同時也能發(fā)現(xiàn)Spring提供了眾多的擴展點來增強Ioc的能力,讓開發(fā)者能夠更好的使用/駕馭

    下一篇文章,將著重介紹Spring本文中遺留的疑問點及Spring所提供的各種擴展能力

    附錄

    中間態(tài)說明


    林中通幽徑,深山藏小舍

    總結(jié)

    以上是生活随笔為你收集整理的不一样 使用别名 数据字段和bean_【修炼内功】[spring-framework] [3] Bean是如何创建又是如何销毁的?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    中文字幕乱码视频 | 日韩欧美在线观看 | 国产精品ⅴa有声小说 | 国产精品免费在线播放 | 婷婷亚洲五月 | 亚洲春色综合另类校园电影 | 一级黄色电影网站 | 日日干,天天干 | 在线免费观看视频a | 91视频在线免费下载 | 三上悠亚一区二区在线观看 | 日韩精品在线看 | 99久久婷婷国产综合精品 | 久久99婷婷 | 黄色日本免费 | 国产精品网在线观看 | 久久成人免费 | 国产免费资源 | 天天干天天操天天入 | 在线免费中文字幕 | av高清一区二区三区 | 四虎成人精品 | 中文字幕一区二区三区四区久久 | 欧美日韩另类视频 | 色多多污污 | 日韩欧美在线免费 | 波多野结衣综合网 | 国产 视频 高清 免费 | 久久久久久高潮国产精品视 | 亚洲高清网站 | 9999免费视频 | 日韩在线第一 | 欧美日韩一区二区三区免费视频 | 激情网色 | 中文字幕亚洲高清 | 91视频a | 一区久久久 | 色在线免费观看 | 欧美成人高清 | 国产精品九色 | 九九影视理伦片 | 视频三区| av先锋影音少妇 | 精品中文字幕在线播放 | 中文字幕a∨在线乱码免费看 | 日日麻批40分钟视频免费观看 | 玖草在线观看 | 久久a v视频| 视频二区在线 | 一区二区三区不卡在线 | 永久av免费在线观看 | 精品国产一区二区三区四区vr | 九九视频网站 | 亚洲精品国产精品国自产 | 亚洲精品白浆高清久久久久久 | 久久精品三级 | av免费电影网站 | 九色精品免费永久在线 | 四虎国产精品免费观看视频优播 | 国产精品女同一区二区三区久久夜 | 精品国产一区二区三区男人吃奶 | 开心激情五月婷婷 | 午夜美女wwww | 在线亚洲欧美视频 | 日韩欧美一区二区三区在线观看 | 久99热| 日本公妇色中文字幕 | 激情视频免费在线观看 | 久久激情婷婷 | 国产97碰免费视频 | 在线观看亚洲精品视频 | 一级一片免费观看 | 国产中文在线视频 | 欧美精品视 | 午夜视频福利 | 国产成人一区二区三区久久精品 | 欧美一二三区播放 | 日韩乱码中文字幕 | 日本一区二区高清不卡 | 日韩欧美有码在线 | 九草在线视频 | www.亚洲精品在线 | 欧美性生交大片免网 | 婷婷五天天在线视频 | 色综合天天综合 | 免费看片日韩 | 在线亚洲精品 | 五月天中文在线 | 久久午夜网| 9999国产精品 | 天天综合天天综合 | 国产91在线 | 美洲 | 成人99免费视频 | 黄色aaa毛片 | 9幺看片| 国产视频1 | 在线亚洲日本 | 亚洲天堂网在线视频 | 99热官网 | 欧美国产在线看 | 日本三级中文字幕在线观看 | 九九爱免费视频在线观看 | 狠狠躁夜夜躁人人爽视频 | 午夜av激情| 亚洲区精品 | 日日爱网站| 丁香花在线观看免费完整版视频 | 韩国av免费在线 | 国产不卡精品 | 国产成人精品一区二区 | 色黄久久久久久 | 黄色免费网站大全 | 欧美一级久久久久 | 国产激情电影综合在线看 | 五月丁婷婷 | 日韩精品一区二区免费 | 久久一区二区三区日韩 | 在线观看成人 | 成人av资源网 | 精品亚洲男同gayvideo网站 | 日韩精品一区在线播放 | 国产免码va在线观看免费 | 97在线免费视频观看 | 91爱爱免费观看 | 九九视频一区 | 久久官网 | 日本中文一级片 | 六月丁香综合网 | 国产剧情一区在线 | 国产欧美日韩精品一区二区免费 | 美女视频黄是免费的 | 亚洲一区免费在线 | 婷婷激情小说网 | 色网免费观看 | 色姑娘综合网 | av大全在线免费观看 | 久草视频在| 国产乱对白刺激视频不卡 | 天天射天天添 | 九九视频免费观看视频精品 | 免费在线色电影 | 国产精品国产三级国产专区53 | 天天操天天舔天天爽 | 91精品在线观看入口 | 婷婷视频在线 | 久久久91精品国产一区二区三区 | av在线免费不卡 | 欧美精品国产综合久久 | 91香蕉嫩草 | 国产黄色一级片在线 | 狠狠狠干| 日韩免费在线观看视频 | 国产三级久久久 | 最近中文字幕完整视频高清1 | 久久久在线视频 | 精品视频在线播放 | 久久天天拍 | 欧美精品三级在线观看 | 成人资源在线播放 | av超碰在线 | 免费观看91视频大全 | 99亚洲视频 | 亚洲国产69 | 亚洲精品国产精品国自产在线 | 91亚洲精品乱码久久久久久蜜桃 | 欧美精品xx | 最新精品视频在线 | 99免费在线 | 黄色一集片| 999久久a精品合区久久久 | 麻豆传媒在线视频 | 91精品在线视频观看 | 岛国av在线| 欧美激情另类文学 | 成人在线观看影院 | 成人免费共享视频 | 丁香五月亚洲综合在线 | 国产高清 不卡 | 免费看污污视频的网站 | 狠狠干综合 | 日日爱网址 | 欧美精品乱码久久久久久按摩 | 韩国三级一区 | 国产 一区二区三区 在线 | 在线视频精品播放 | 草久草久 | 97免费公开视频 | 国产色婷婷精品综合在线手机播放 | 国产91全国探花系列在线播放 | 国产黄色在线看 | 成人毛片在线观看 | 久久人人爽人人 | 一区二区三区 中文字幕 | 一区二区三区在线免费观看 | 国产精品久久精品国产 | 99热都是精品 | 亚洲精品久久久久中文字幕二区 | 日本三级不卡视频 | 亚州欧美精品 | 亚洲精品午夜久久久久久久 | 中中文字幕av在线 | 草在线视频 | 亚洲欧美日韩在线看 | 天天爽天天爽天天爽 | 久久久www免费电影网 | 国产欧美精品一区二区三区 | www.伊人网.com| 又粗又长又大又爽又黄少妇毛片 | 国产亚洲久一区二区 | 成人一区在线观看 | av直接看| 久久久久久久久久久免费视频 | 在线久热 | 久久免费成人网 | 国精产品满18岁在线 | 中文字幕av免费观看 | 久久中文欧美 | 国产精品18久久久久久久久 | 亚洲精品成人av在线 | 人人草在线视频 | www免费在线观看 | 国产高清视频在线免费观看 | 国产精品婷婷 | 中文字幕第一页在线 | 在线观看黄色小视频 | 西西4444www大胆艺术 | 久久九九影视网 | 91黄色在线看 | 精品国产亚洲日本 | 日韩视频一区二区三区在线播放免费观看 | 精品视频免费观看 | 免费色视频| 国产91精品在线播放 | 国产精品门事件 | 成人a免费视频 | 中文亚洲欧美日韩 | 国产精品一区二区三区在线免费观看 | 国产精品女教师 | 日本中文在线观看 | 激情导航 | 91av手机在线 | 亚洲h视频在线 | 免费瑟瑟网站 | 在线观看视频亚洲 | 999精品在线 | 在线观看成人 | 日韩欧美在线综合网 | 成人欧美一区二区三区在线观看 | 五月婷婷在线观看视频 | 久久99偷拍视频 | 欧美日韩精品在线免费观看 | 91在线视频精品 | 久久66热这里只有精品 | 蜜桃视频在线观看一区 | 精品在线二区 | 一区久久久 | 麻豆视频在线免费看 | 久久精品日产第一区二区三区乱码 | 亚洲天堂网站视频 | 久久精品免费电影 | 99久久夜色精品国产亚洲 | 97免费| 亚洲欧美国产日韩在线观看 | 成人九九视频 | 中文在线字幕免费观看 | 久草在线资源免费 | 午夜 在线 | 天干啦夜天干天干在线线 | 国产精品99久久久久久小说 | 亚洲国产偷 | 免费色视频在线 | 久久精品一区二区三区四区 | 色婷五月天 | 亚洲女欲精品久久久久久久18 | 一区二区三区韩国免费中文网站 | 黄色av成人在线观看 | 亚洲精品大片www | 丁香九月激情综合 | 日本特黄一级片 | 99久久国产免费免费 | 丁香高清视频在线看看 | 五月婷婷在线视频观看 | 国产精品久久亚洲 | 国产涩涩在线观看 | 成年人视频在线免费播放 | 久久精品综合 | 国产高清成人av | 中文字幕亚洲欧美日韩2019 | 久久久久久在线观看 | 天天射天天爽 | 麻豆91精品91久久久 | 午夜av免费在线观看 | 91精品成人久久 | 18国产精品福利片久久婷 | 国产一区av在线 | 国产第一页在线播放 | 在线观看成人网 | 久久精品视频在线观看免费 | 亚洲精品乱码久久久久v最新版 | 天天综合人人 | 96久久 | 亚洲乱码一区 | 精产嫩模国品一二三区 | 成年人免费观看在线视频 | 国产区久久 | 久久免费看av | 欧美人体xx| 久久人人爽爽人人爽人人片av | 国产高清久久久久 | 天天干夜夜爱 | 国产 日韩 欧美 中文 在线播放 | 亚洲最新在线视频 | 免费亚洲精品 | 亚洲黄色在线观看 | 狠狠躁18三区二区一区ai明星 | 久久99精品久久只有精品 | 日韩欧美在线观看一区二区 | 精品三级av | 亚洲女同videos | 久久精彩免费视频 | 狠狠干成人综合网 | 国产专区一 | www99精品| 国产a国产a国产a | 国产精品少妇 | 亚洲影院色 | 日韩精品免费在线播放 | 91精品老司机久久一区啪 | 色综合天 | 91精品国产乱码久久桃 | 在线看日韩 | 91精品国产网站 | 最近2019中文免费高清视频观看www99 | www.在线看片.com | 中文字幕高清视频 | 国产人免费人成免费视频 | 97人人澡人人添人人爽超碰 | 精品自拍网 | 公与妇乱理三级xxx 在线观看视频在线观看 | 国产精品美女久久久 | 97视频免费在线观看 | 欧美精品xx | 婷婷网在线| 免费又黄又爽视频 | 丁香六月婷婷开心 | 五月综合色 | 久久精品免费 | 中文字幕国产 | 国产一区二区在线免费 | 久久夜视频 | 五月天综合 | 国产黄色片网站 | av高清一区二区三区 | 久久国产亚洲精品 | 在线导航av | 一区二区三区日韩视频在线观看 | 久久人人添人人爽添人人88v | www天天干 | 日韩首页 | 国产成a人亚洲精v品在线观看 | 久久综合五月天婷婷伊人 | 国产美女网 | 黄色毛片网站在线观看 | 欧美日韩一级在线 | 综合色伊人| 日本夜夜草视频网站 | 97视频在线观看网址 | 久久综合狠狠综合久久激情 | 国产精品24小时在线观看 | 久久久久亚洲精品男人的天堂 | 久久av中文字幕片 | 午夜骚影 | 免费网站看av片 | 久草免费在线视频观看 | 国产精品资源网 | 亚洲欧美视频网站 | 国产精品21区 | 国产免费大片 | 久久96| 黄色片软件网站 | 成人久久18免费网站图片 | 麻豆一精品传二传媒短视频 | 国产视频日本 | 国产+日韩欧美 | 在线а√天堂中文官网 | 免费97视频 | 成人动漫一区二区三区 | 欧美性高跟鞋xxxxhd | 国产成人精品亚洲日本在线观看 | 精品欧美一区二区精品久久 | 精品一区电影 | av在线播放不卡 | 91成熟丰满女人少妇 | 国产黄色免费观看 | 欧美天堂影院 | 久久久精品久久日韩一区综合 | 日韩av片免费在线观看 | 亚洲天堂网视频在线观看 | 三级黄色欧美 | 欧美激情精品一区 | 中文在线中文a | 五月婷丁香 | 永久免费av在线播放 | 特级aaa毛片 | 欧美成人手机版 | 亚洲国产精品成人综合 | 激情网站免费观看 | 欧美成人精品欧美一级乱 | 三级黄色网址 | 日本久久91 | 免费能看的黄色片 | 久久久久国产精品免费 | 曰本三级在线 | 成年人视频在线观看免费 | 欧美 激情 国产 91 在线 | 久久久在线视频 | 久久综合福利 | 99性视频| 精品国产一区二区三区在线 | av三级av| www久久com| 狠狠狠色丁香婷婷综合激情 | 国产三级精品三级在线观看 | 欧美91成人网 | 日韩欧美在线播放 | 久草网在线视频 | 色在线视频网 | 亚洲精品国偷拍自产在线观看蜜桃 | 丁香婷婷激情 | 最近高清中文在线字幕在线观看 | 国产又粗又猛又爽又黄的视频先 | 伊人国产女 | 99久久精品无码一区二区毛片 | 婷婷激情五月综合 | 国产精品久久片 | 国产日韩视频在线播放 | 国内精品美女在线观看 | 午夜国产福利在线 | 成人av电影在线播放 | 中文字幕乱偷在线 | 亚洲视频分类 | 色综合久 | japanesefreesex中国少妇 | 成人动漫一区二区 | 国产男女无遮挡猛进猛出在线观看 | 欧美日本三级 | 在线一二三四区 | 伊甸园av在线 | 91久久精品一区二区二区 | 国产.精品.日韩.另类.中文.在线.播放 | 97在线免费 | 二区三区视频 | 91精品老司机久久一区啪 | 欧美日韩一区二区三区在线观看视频 | 久精品视频 | 国产精品 9999| 91人人射 | 久久ww| 中文不卡视频 | 日韩精品欧美专区 | 韩国av一区二区三区在线观看 | 成人在线超碰 | 国产精品久久一区二区三区, | 欧美在线视频一区二区 | 国产成人香蕉 | 久久综合激情 | 国产高清在线a视频大全 | 又黄又爽又色无遮挡免费 | 国产一级免费视频 | 伊人狠狠色 | 欧美大荫蒂xxx | 久草精品视频在线播放 | 久久天天躁夜夜躁狠狠躁2022 | 国产亚洲视频中文字幕视频 | 久久影视精品 | 在线播放日韩 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 久久久免费观看完整版 | 欧美成人xxxxxxxx| 日韩国产精品一区 | 欧美日韩亚洲在线观看 | av福利在线看 | 人人涩 | 久久精品8| www日日| 日韩大片在线 | 久久夜色精品国产欧美乱极品 | 国产电影黄色av | 亚州黄色一级 | 欧美精品亚洲精品 | 久久老司机精品视频 | 五月天六月婷 | 日韩精品免费一区 | 成人黄性视频 | www.超碰| 美女网站在线看 | 99久久综合国产精品二区 | 久久久影院官网 | 免费观看成人网 | 久久婷婷精品视频 | 国产中文字幕视频 | 国产高清视频网 | 欧美日韩亚洲在线观看 | 日韩视频一区二区三区在线播放免费观看 | 夜夜夜精品 | 国产精品久久久久永久免费观看 | 超碰在线人 | 久久精品专区 | 久草新在线 | 免费成人在线电影 | 天天干天天天天 | 日日夜夜婷婷 | 久久精品一区二 | 精品自拍网 | 91麻豆精品91久久久久同性 | 国产四虎影院 | 欧美日韩中字 | av线上免费观看 | 91麻豆高清视频 | 国产高清精品在线观看 | 免费看短 | 欧洲亚洲国产视频 | 亚洲欧洲精品一区二区精品久久久 | 超碰在线1 | 精品美女久久久久 | 久久人人射 | 久久人人爽爽人人爽人人片av | 久久艹国产视频 | 国产亚洲精品久久网站 | 精品国产亚洲日本 | 黄网站免费久久 | 欧美日韩首页 | 国产91精品看黄网站 | 最近中文字幕第一页 | 亚洲伦理中文字幕 | 免费看片色 | 久草线 | 91成年人在线观看 | 欧美日韩二三区 | 成人午夜电影在线播放 | 久久这里只有精品视频首页 | a黄色片在线观看 | 国产精品黄网站在线观看 | 日日草天天草 | 日韩r级电影在线观看 | 欧美a√在线 | 人人插人人爱 | 一级片免费观看视频 | 在线免费观看视频一区二区三区 | 国产精品欧美激情在线观看 | 久久夜色精品国产欧美一区麻豆 | 国产美腿白丝袜足在线av | 色五月成人 | 午夜免费视频网站 | 激情xxxx| 国内精品在线观看视频 | 欧美久久久久久久久 | 超碰在线97国产 | 亚洲精品视频在线观看网站 | 狠狠狠色丁香综合久久天下网 | 毛片1000部免费看 | 网站免费黄 | 国内精品视频在线 | 亚洲精品视频一二三 | 久久久精品小视频 | 日本电影久久 | 久久久亚洲精品 | 日韩一区正在播放 | 一区二区三区中文字幕在线 | 日日日操操 | 色姑娘综合天天 | 国产福利小视频在线 | 丁香婷婷激情国产高清秒播 | adc在线观看 | 综合天堂av久久久久久久 | 天天综合色网 | 丁香婷婷在线观看 | 亚洲国产一区av | 色九色 | 中文字幕有码在线观看 | 99爱视频在线观看 | 深爱五月网 | 成年人在线免费视频观看 | 操操操天天操 | 九九久久久 | 免费在线观看成人小视频 | 九九亚洲精品 | 精品v亚洲v欧美v高清v | 成人午夜黄色影院 | av亚洲产国偷v产偷v自拍小说 | 在线看日韩 | 五月婷婷黄色网 | 精品国产乱码一区二区三区在线 | 国产无套一区二区三区久久 | 亚洲一级久久 | 欧美二区视频 | 福利视频区 | 免费看黄网站在线 | 久久天天综合网 | 天堂av在线 | 中日韩免费视频 | 黄色免费视频在线观看 | 涩涩网站在线 | 久久久免费| 日日综合 | 国产精品 日韩 | 91pony九色丨交换 | 激情校园亚洲 | 久热这里有精品 | 国产一卡二卡在线 | 91精品久久久久久综合五月天 | 天天操天天色天天 | 999ZYZ玖玖资源站永久 | 欧美日韩在线网站 | 久久精品91久久久久久再现 | 深夜免费福利网站 | 人人干人人模 | 黄色在线看网站 | 亚洲精品国产第一综合99久久 | 一区二区国产精品 | 97在线免费观看 | 久久久久久国产精品免费 | 亚洲午夜精品福利 | 亚洲成av人片 | 久久久久久国产精品999 | 欧美精品中文在线免费观看 | 97超碰人人网 | 中文字幕高清视频 | 国产在线精品播放 | 国产91粉嫩白浆在线观看 | 91av小视频 | 狠狠艹夜夜干 | 成人免费在线视频观看 | 亚洲精品小区久久久久久 | 亚洲精品在线资源 | 中文字幕黄色 | 国产高清精品在线观看 | 日日麻批40分钟视频免费观看 | 国内精品久久久久影院男同志 | 97人人澡人人添人人爽超碰 | 五月婷婷丁香 | 日韩高清一区 | 99热这里是精品 | 九九免费观看全部免费视频 | 婷婷精品国产欧美精品亚洲人人爽 | 91看片淫黄大片一级在线观看 | 丁香六月久久综合狠狠色 | 午夜av一区二区三区 | 香蕉视频啪啪 | 免费看黄在线网站 | 亚洲天堂在线观看完整版 | 国产精品久久久久久久久久久久午 | 亚洲国产欧美在线看片xxoo | 国产成人av片 | 国产成人一区二区三区在线观看 | 97精品超碰一区二区三区 | 欧美韩日在线 | 色婷婷九月 | 日韩在线 一区二区 | 国产 视频 高清 免费 | 五月天伊人| 日本中文一区二区 | 免费精品久久久 | 高清av免费看 | av在线等 | 狠狠干狠狠艹 | 久久精品女人毛片国产 | 亚洲精品久久久久www | 99热国产在线 | 超碰在线最新 | 一区在线电影 | 国产精品嫩草影视久久久 | 黄色小说免费观看 | 黄色在线免费观看网站 | 欧美日韩精品电影 | 成人精品福利 | 欧美日韩国产综合网 | 91av视频在线观看免费 | 国产性天天综合网 | 国产毛片在线 | 亚洲午夜精品福利 | 国产高清视频在线播放一区 | 久草久热 | 免费看国产曰批40分钟 | 丁香六月婷婷开心 | 麻豆影视在线免费观看 | 高潮毛片无遮挡高清免费 | 日日操天天射 | 五月开心六月伊人色婷婷 | 国产成人一区二区三区电影 | 九九综合久久 | 人人射| 色夜影院 | 欧美性生活久久 | 天堂av最新网址 | 日韩激情视频在线观看 | 国产第一页在线播放 | 国产一区视频在线播放 | 视频国产| 欧美日韩中文视频 | 99久久99视频只有精品 | 免费观看一区二区 | 国产香蕉视频在线观看 | 色播五月婷婷 | 免费在线视频一区二区 | 久久综合色8888 | 国产日产精品久久久久快鸭 | 日韩久久精品一区二区三区下载 | a久久免费视频 | a级成人毛片 | 中文字幕日本在线观看 | 在线视频一二区 | avav片 | 日日干夜夜干 | 香蕉影院在线观看 | 色美女在线 | 欧美一级特黄aaaaaa大片在线观看 | 欧美一级xxxx | 久久天天躁狠狠躁亚洲综合公司 | 国产精品久久久久一区 | 91热爆视频 | 久草国产在线 | 亚洲成a人片77777kkkk1在线观看 | 久久久www | 9免费视频 | 色视频在线免费观看 | 夜添久久精品亚洲国产精品 | 日韩网站一区二区 | 在线观看黄网站 | 一区二区三区四区五区在线 | 日韩特黄一级欧美毛片特黄 | 久久久久欧美精品999 | 亚洲天堂首页 | 狠狠做深爱婷婷综合一区 | 久久香蕉国产精品麻豆粉嫩av | 国产精品都在这里 | av在线影片 | 亚洲三级黄| 麻豆首页 | 国产女教师精品久久av | 综合中文字幕 | 97国产精品一区二区 | 久热超碰 | 久久视频一区二区 | 久久久久电影网站 | 日日爱网址 | 久久在线 | 日本高清dvd| 日本不卡视频 | 精品视频在线看 | 国产精品久久久久久久久久免费 | 国产黄在线 | 青草草在线 | 亚洲午夜av久久乱码 | 国产精品久久久毛片 | 日韩成人在线一区二区 | 国产免费一区二区三区最新 | 91成人亚洲| 美女视频国产 | 免费黄色av电影 | 国产伦理精品一区二区 | 日韩va亚洲va欧美va久久 | 亚洲精品久久激情国产片 | 国产精品福利午夜在线观看 | 国产精品久久久久毛片大屁完整版 | 97中文字幕| 一区二区三区免费在线播放 | 欧美一级免费在线 | 国产精品久久久久永久免费看 | 国产一区二区免费看 | 欧美a级在线免费观看 | 欧美性大胆 | av色综合网| 久久久91精品国产 | 国产精品一区二区在线观看 | av性在线| 久操视频在线免费看 | 欧美性成人 | 天天射天天射天天射 | 日韩精品欧美精品 | 日日干夜夜草 | 4p变态网欧美系列 | 精品亚洲欧美无人区乱码 | 亚洲综合色婷婷 | 成人在线播放免费观看 | 国产亚洲精品久久久久久网站 | 狠狠色丁香久久婷婷综合丁香 | 精品国产区 | 九色91视频| 亚洲视频在线免费观看 | 成人理论电影 | 久久综合九色综合久久久精品综合 | 国产高清在线免费观看 | 91在线日韩 | 国产小视频在线播放 | 久草视频在线看 | 91精品国自产在线观看 | 久久人人爽人人爽 | 超碰在线公开免费 | 97超级碰碰碰视频在线观看 | 欧美午夜视频在线 | 一区三区视频在线观看 | 免费a级大片 | 91精品一区二区在线观看 | 成人小视频在线观看免费 | 娇妻呻吟一区二区三区 | 国产精品精品 | 手机在线观看国产精品 | 亚洲片在线资源 | 97人人澡人人添人人爽超碰 | 51久久成人国产精品麻豆 | 国产一级黄色片免费看 | 天天干人人插 | 日韩高清精品一区二区 | 91av视频在线免费观看 | 欧美日韩高清一区二区三区 | 日韩高清观看 | 在线观看视频你懂的 | 超碰人人乐 | 免费国产亚洲视频 | 国产精品一区二区免费视频 | 欧美最猛性xxxxx免费 | 一本一本久久a久久精品综合小说 | 国产护士hd高朝护士1 | 久久久久免费观看 | 欧美日韩成人一区 | 成人小视频在线观看免费 | 国产成人在线看 | 日本高清中文字幕有码在线 | 国产精品久久久久久久av大片 | 天天操导航 | 久久永久免费 | 免费看片成人 | 国产免费一区二区三区最新 | 一区二区三区久久精品 | 天天久久夜夜 | 91视频在线看 | 国产69熟| 日本一区二区三区免费观看 | av短片在线 | 日韩黄色免费在线观看 | 国产精品久久久久久久久久不蜜月 | 亚洲国产欧美在线人成大黄瓜 | 国产麻豆电影在线观看 | 国产高清在线免费视频 | 免费成人av在线看 | 亚洲高清精品在线 | 久久av中文字幕片 | 成人h在线观看 | 免费看污黄网站 | 国产精品久久久久9999吃药 | 四虎影视国产精品免费久久 | 久草视频观看 | 亚洲日本国产精品 | 九九九在线观看 | 久久综合五月天 | 99久久激情视频 | 激情伊人五月天久久综合 | 欧美 日韩 成人 | 亚州精品一二三区 | 亚洲一区二区精品3399 | 人成在线免费视频 | 成人香蕉视频 | 99久热精品| 热久久免费视频 | 成人香蕉视频 | 国产精品婷婷午夜在线观看 | av黄色在线播放 | 成人欧美一区二区三区黑人麻豆 | 国产精品久久久久国产精品日日 | 久久久久国产a免费观看rela | 天天操网站 | 精品免费一区 | 91免费看黄色 | 美女视频黄免费的久久 | 国产精品丝袜久久久久久久不卡 | 国产精品久久久久久久久久久久午夜片 | 国产无遮挡又黄又爽馒头漫画 | 国产综合香蕉五月婷在线 | 国产区久久 | 日日夜夜噜噜噜 | 日韩av电影中文字幕 | 一区二区欧美在线观看 | 狠狠网亚洲精品 | 亚洲视频免费在线看 | 97免费在线观看视频 | 欧美日韩精品影院 | 国产精品亚洲精品 | 女人高潮一级片 | 免费亚洲电影 | 日韩在线观看你懂的 | 久久久久久久久影院 | 天天插综合网 | 久久久久久久国产精品视频 | 免费成人在线电影 | 亚洲h色精品 | 亚洲精品美女久久久久网站 | 欧美性极品xxxx做受 | 成人在线免费看视频 | 日韩欧美在线高清 | 91精品办公室少妇高潮对白 | 国语自产偷拍精品视频偷 | www日韩| 国产精品嫩草影视久久久 | 亚洲激情综合 | 香蕉影院在线播放 | 亚洲 欧美变态 另类 综合 | 国内精品久久久久久 | 亚洲激情 欧美激情 | av免费网站| 国产视频在线看 | 国产亚洲精品v | 精一区二区| 五月综合在线观看 | 狠狠操夜夜操 | av免费观看高清 | 久久国产精品精品国产色婷婷 | 99一级片| 久久综合狠狠 | 国产一级视屏 | 91热精品| 国产精品12 | 成人午夜电影网站 | 九色91福利 | 亚洲一本视频 | 国产a国产a国产a | 深爱婷婷激情 | 特级大胆西西4444www | 91污污视频在线观看 | 91亚洲精品国偷拍自产在线观看 | 亚洲观看黄色网 | 91亚洲精品国产 | 亚洲精品黄网站 | 人人玩人人添人人澡97 | 国产精品久久人 | 99精品国产一区二区三区麻豆 | 麻豆一区在线观看 | 久久高清免费视频 | 丁香婷五月 | 久久精品电影网 | 国产又粗又硬又长又爽的视频 | 国产伦理久久精品久久久久_ | 久草在线资源观看 | 夜夜视频欧洲 | 欧美一级高清片 | 四虎成人免费影院 | 国产中文字幕第一页 | 男女啪啪视屏 | 亚洲视频456 | 国产精品中文久久久久久久 | 亚洲综合色网站 | 日韩在线不卡av | 亚洲97在线 | 91麻豆网站| 日本精品久久久一区二区三区 | 免费污片| 日日夜夜网站 | av网址最新 | 亚洲欧美婷婷六月色综合 | 999国内精品永久免费视频 | 国产高清视频色在线www | 亚洲黄色片在线 | 国产精品综合久久久久 | 三级黄色片子 | 亚洲永久精品视频 | 香蕉手机在线 | 免费看网站在线 | 日韩在线免费视频观看 | 激情伊人五月天久久综合 | 黄色大片中国 | 亚洲欧美日本国产 | 在线激情小视频 | 国产午夜不卡 | 一本到在线 | 国内精品久久久久影院一蜜桃 | 国产在线久草 | 99热精品视 | 久久免费电影网 | 黄色亚洲大片免费在线观看 | 午夜精品视频一区 | 西西人体www444 | 亚洲欧美偷拍另类 | 精品一区二区视频 | 久草在线最新视频 | 国产色视频一区二区三区qq号 | 开心激情网五月天 | 亚洲三级在线免费观看 | 91免费视频国产 | 国产无遮挡又黄又爽在线观看 | 日韩免费专区 | 国产精品久久久久久久99 | 亚洲日本黄色 | 亚洲一区日韩 | 日本成人黄色片 | 91麻豆国产福利在线观看 | 日韩激情小视频 | 欧美成年人在线视频 | 深夜福利视频一区二区 |