亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發(fā)設計 > 正文

Spring4.3.x 容器的刷新過程

2019-11-10 20:17:56
字體:
來源:轉載
供稿:網友

概述


SPRing容器體系的繼承結構圖如下。

這里寫圖片描述

從圖中可以看出抽象類AbstractapplicationContext是所有容器類的父類。AbstractApplicationContext實現了它繼承的所有接口方法,并定義了三個用于管理BeanFactory對象的抽象方法,如下

//--------------------------------------------------------------------- // Abstract methods that must be implemented by subclasses //--------------------------------------------------------------------- /** * Subclasses must implement this method to perform the actual configuration load. * The method is invoked by {@link #refresh()} before any other initialization work. * <p>A subclass will either create a new bean factory and hold a reference to it, * or return a single BeanFactory instance that it holds. In the latter case, it will * usually throw an IllegalStateException if refreshing the context more than once. * @throws BeansException if initialization of the bean factory failed * @throws IllegalStateException if already initialized and multiple refresh * attempts are not supported */ protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException; /** * Subclasses must implement this method to release their internal bean factory. * This method gets invoked by {@link #close()} after all other shutdown work. * <p>Should never throw an exception but rather log shutdown failures. */ protected abstract void closeBeanFactory(); /** * Subclasses must return their internal bean factory here. They should implement the * lookup efficiently, so that it can be called repeatedly without a performance penalty. * <p>Note: Subclasses should check whether the context is still active before * returning the internal bean factory. The internal factory should generally be * considered unavailable once the context has been closed. * @return this application context's internal bean factory (never {@code null}) * @throws IllegalStateException if the context does not hold an internal bean factory yet * (usually if {@link #refresh()} has never been called) or if the context has been * closed already * @see #refreshBeanFactory() * @see #closeBeanFactory() */ @Override public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

小技巧:告訴大家如何查看一個抽象類未實現的接口方法有哪些,比如上面的AbstractApplicationContext抽象類。我創(chuàng)建了一個MyApplicationContext 類,如果未實現任何方法,IDE會提醒我實現父類中未實現的方法,代碼如下。

public class MyApplicationContext extends AbstractApplicationContext { @Override protected void refreshBeanFactory() throws BeansException, IllegalStateException { } @Override protected void closeBeanFactory() { } @Override public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException { return null; }}

回歸正題,Spring容器在初始化的時候都會執(zhí)行一個方法來結束初始化,那就是refresh()方法,此方法定義在接口ConfigurableApplicationContext中,并且抽象類AbstractApplicationContext實現了它,代碼如下

@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 為容器的刷新做準備工作,設置啟動日期,更新活動標志,加載屬性資源 prepareRefresh(); // 獲取最新的bean工廠對象。 // 要求子類刷新自身持有的bean工廠對象 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 在容器使用bean工廠之前,設置bean工廠 // 主要是添加特定的bean后處理器 prepareBeanFactory(beanFactory); try { // 鉤子方法,允許在子類中bean工廠做進一步的處理 // 子類可以根據自身需要,添加更多的bean后處理器 postProcessBeanFactory(beanFactory); // 在上下文容器中執(zhí)行所有注冊了的bean工廠后處理器 // 執(zhí)行步驟:1. 在bean工廠中找到所有實現了BeanFactoryPostProcessor的對象 // ->2. 執(zhí)行所有bean工廠后處理器的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(beanFactory); // 把所有用戶配置的bean后處理器添加到bean工廠中 registerBeanPostProcessors(beanFactory); // 初始化國際化消息對象,默認為DelegatingMessageSource initMessageSource(); // 初始化事件傳播器,默認為SimpleApplicationEventMulticaster initApplicationEventMulticaster(); // 鉤子方法,初始化其他特定的bean onRefresh(); // 注冊用戶指定的和容器創(chuàng)建時添加的監(jiān)聽器 registerListeners(); // 初始化所有剩下的單例非延遲bean finishBeanFactoryInitialization(beanFactory); // 完成刷新,包括發(fā)布容器刷新事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } /// 銷毀所有已經創(chuàng)建好的bean,以防止內存浪費 destroyBeans(); // 重置活動標志 cancelRefresh(ex); throw ex; } finally { // 重置反射緩存 resetCommonCaches(); } } }

refresh方法的設計使用了模板方法設計模式,它設定了容器刷新的流程,并把特定階段的執(zhí)行延遲到子類中執(zhí)行,比如bean工廠的創(chuàng)建。它還在特定的階段提供鉤子方法,以方便子類根據自身需要進一步完成更多的操作。下面我們一步一步的探討refresh方法的執(zhí)行流程。下圖是它的一個大概流程圖。

refresh方法在容器的基本配置完成后被調用,它是spring容器初始化過程的主要戰(zhàn)場,下面我們一步一步的探討refresh方法的執(zhí)行流程。

容器刷新過程


1. 容器刷新前準備

在refresh方法的第1步中,調用AbstractApplicationContext的prepareRefresh()方法完成容器刷新前的準備,代碼如下。

protected void prepareRefresh() { // 設置啟動時間 this.startupDate = System.currentTimeMillis(); this.closed.set(false); // 把容器設置為活動 this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // 鉤子方法,讓子類把所有的stub屬性資源替換成真正需要的屬性資源。 initPropertySources(); // 驗證所有被標注為required的屬性是否可被解析 getEnvironment().validateRequiredProperties(); // 允許事件傳播器可用的時候發(fā)布一些事件 // earlyApplicationEvents存儲需要在事件傳播器可用時發(fā)布的事件 this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>(); }

prepareRefresh方法設置容器啟動時間和活動標志,以及通過調用initPropertySources()方法完成所有的property資源的初始化。initPropertySources()方法是一個空實現,子類可以用它來完成property資源的初始化。例如,下面代碼是在AbstractRefreshableWebApplicationContext類中的實現

@Override protected void initPropertySources() { super.initPropertySources(); ConfigurableEnvironment env = this.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources( this.servletContext, this.servletConfig); } }

這個方法主要是把ServletContext和ServletConfig對象保存到ConfigurableWebEnvironment環(huán)境對象中,以方便環(huán)境對象通過getProperty(String key)方法獲取定義在ServletContext和ServletConfig中特定的初始化init-param參數。

2. 創(chuàng)建BeanFactory

執(zhí)行AbstractApplicationContext的obtainFreshBeanFactory方法,獲取最新的bean工廠對象,代碼如下。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 刷新bean工廠,是一個抽象方法,由子類實現。 refreshBeanFactory(); // 從子類中獲取bean工廠,也是一個抽象方法,由子類實現 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }

obtainFreshBeanFactory方法首先調用子類的refreshBeanFactory()方法刷新bean工廠,然后調用子類的getBeanFactory()方法獲取bean工廠。在spring中,refreshBeanFactory()在GenericApplicationContext類和AbstractRefreshableApplicationContext類中都有實現,下面是在AbstractRefreshableApplicationContext類中的實現。

@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { // 如果當前上線文容器已有bean工廠 // 銷毀bean工廠中所有單例bean destroyBeans(); // 關閉已有的bean工廠 closeBeanFactory(); } try { // 創(chuàng)建一個新的bean工廠 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 自定義bean工廠,包括設置是否允許覆蓋相同ID的bean,是否允許循環(huán)引用,等等 customizeBeanFactory(beanFactory); // 加載所有BeanDefinition,是一個抽象方法,有子類實現 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

這個方法里面,首先把已創(chuàng)建的單例bean銷毀并關閉持有的bean工廠,然后調用createBeanFactory()方法重新創(chuàng)建一個x新的bean工廠代碼如下。最后,并調用子類的loadBeanDefinitions方法把BeanDefinition對象加載到bean工廠中。

/** * 創(chuàng)建一個新的bean工廠 **/ protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }

3. 初始化BeanFactory

獲取到BeanFactory對象后,refresh()方法調用AbstractApplicationContext對象的prepareBeanFactory方法和postProcessBeanFactory方法完成bean工廠的初始化。在這個階段,容器中所有的BeanDefinition對象已經被注冊到bean工廠中(除被@Configuration注解的類管理的bean配置外),但是沒有任何一個BeanDefinition所代表的bean被創(chuàng)建,包括工廠后處理器。下面我們看看這個兩個方法的執(zhí)行情況。

首先,調用prepareBeanFactory方法。這個方法主要功能是,為bean工廠設置容器的類加載器,以及一些特定的bean后處理器,代碼如下。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 要求bean工廠和容器共用同一個類加載器 beanFactory.setBeanClassLoader(getClassLoader()); // 設置SpEL表達式解析器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver()); // 添加Resource編輯器注冊器 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 添加ApplicationContextAwareProcessor后處理器 // 有可能某些工廠后處理器實現了ApplicationContextAware、ResourceLoaderAware等等如下類似接口 // ApplicationContextAwareProcessor后處理器就就為這些接口傳遞相應的對象 // 因此,在執(zhí)行工廠后處理器前,必須要設置此后處理器 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Detect a LoadTimeWeaver and prepare for weaving, if found. // 檢測用戶是否配置了loadTimeWeaver bean對象 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { // 添加LoadTimeWeaverAwareProcessor后處理器,此后處理器用于向bean中注入LoadTimeWeaver對象 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // 為類型匹配檢測配置臨時的類加載器 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 注冊默認的環(huán)境bean對象 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } // 注冊OS系統(tǒng)屬性對象 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } // 注冊OS系統(tǒng)環(huán)境對象 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }

然后,調用postProcessBeanFactory方法。這個方法在AbstractApplicationContext類中的定義如下。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }

postProcessBeanFactory方法被作為鉤子方法,讓子類在bean工廠初始化的時候根據自身需要,對bean工廠做更多的操作。在web應用中,AbstractRefreshableWebApplicationContext類重寫此方法,代碼如下。

/** * 注冊request/session作用域, 和ServletContextAwareProcessor bean后處理器, . */ @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 添加ServletContextAwareProcessor后處理器 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); // 注冊request/session作用域 WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); // 把ServletContext對象和ServletConfig對象等以單例bean的形式注冊到bean工廠中 WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }

4. 執(zhí)行bean工廠后處理器的postProcessBeanFactory方法

bean工廠初始化完成后,refresh()方法調用AbstractApplicationContext的invokeBeanFactoryPostProcessors方法完成容器中所有bean工廠后處理器的執(zhí)行,代碼如下。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 把執(zhí)行工廠后處理器的任務委托給PostProcessorRegistrationDelegate PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // 檢測LoadTimeWeaver對象 // 聲明:String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver"; if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }

這段代碼主要是把工廠后處理器的任務委托給PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法,此方法的代碼如下。

public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // 首先執(zhí)行BeanDefinitionRegistryPostProcessors Set<String> processedBeans = new HashSet<String>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 遍歷容器中的工廠后處理器,并執(zhí)行BeanDefinitionRegistryPostProcessors for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 執(zhí)行BeanDefinitionRegistryPostProcessors的 // ->postProcessBeanDefinitionRegistry方法 registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } // 獲取bean工廠中定義的BeanDefinitionRegistryPostProcessor對象 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 首先,執(zhí)行實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor對象 List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registryPostProcessors.addAll(priorityOrderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); // 然后,執(zhí)行實現了Ordered接口的BeanDefinitionRegistryPostProcessor對象 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(beanFactory, orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); // 最后執(zhí)行其它的BeanDefinitionRegistryPostProcessor對象 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } } // 執(zhí)行BeanDefinitionRegistryPostProcessor工廠后處理器 invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); // 執(zhí)行容器中普通的工廠后處理器 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // 執(zhí)行容器中的bean工廠后處理器 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // 獲取定義在bean工廠中的bean工廠后處理器 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 把bean工廠后處理器按PriorityOrdered、Ordered和其他來分類 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // 排除前面已經執(zhí)行了的后處理器 } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 首先執(zhí)行實現了PriorityOrdered接口的后處理器 sortPostProcessors(beanFactory, priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 然后執(zhí)行實現了Ordered接口的后處理器 List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(beanFactory, orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // 最后執(zhí)行其他的后處理器 List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // 清除工廠中的元數據緩存 beanFactory.clearMetadataCache(); } /** * 執(zhí)行給定的BeanDefinitionRegistryPostProcessor beans. */ private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } } /** * 執(zhí)行給定的bean工廠 **/ private static void invokeBeanFactoryPostProcessors( Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { for (BeanFactoryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanFactory(beanFactory); } }

上面的執(zhí)行流程用圖表達如下。 這里寫圖片描述

上圖很明顯的表達了bean工廠后處理器的執(zhí)行順序,但這里還有兩點需要說明的。

a. 為什么要先執(zhí)行BeanDefinitionRegistryPostProcessor?因為實現BeanDefinitionRegistryPostProcessor 接口的后處理器可以在bean工廠創(chuàng)建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類就是這樣一種工廠后處理器,它主要把被@Configuration注解的類中定義的bean信息轉換成BeanDefinition對象,并注冊到bean工廠中。

b. 這個流程中有一個很明顯的規(guī)定就是,不管是什么工廠后處理器,都必須先執(zhí)行容器中的工廠后處理器后,才執(zhí)行bean工廠中的工廠后處理器。

5. 注冊BeanPostProcessor

refresh()方法執(zhí)行完bean工廠后處理器后,接著調用AbstractApplicationContext的registerBeanPostProcessors方法向bean工廠注冊bean后處理器,registerBeanPostProcessors方法的代碼如下。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 把注冊bean后處理器的任務委托給PostProcessorRegistrationDelegate PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }

registerBeanPostProcessors方法把注冊bean后處理器的任務委托給PostProcessorRegistrationDelegate類的registerBeanPostProcessors方法,下面是這個方法的代碼。

public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { // 從bean工廠中找到所有BeanPostProcessor對象的名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // 注冊BeanPostProcessorChecker后處理器 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // 對所有的bean后處理器根據實現PriorityOrdered,Ordered和其他的進行分組 List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 首先注冊實現了PriorityOrdered接口的bean后處理器 sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 然后注冊實現了Ordered接口的后處理器. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(beanFactory, orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 再次,注冊所有普通的后處理器 List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // 最后,重新注冊所有內部后處理器 // ->即實現了MergedBeanDefinitionPostProcessor接口的后處理器 sortPostProcessors(beanFactory, internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); } /** * 注冊指定的BeanPostProcessor beans. */ private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { for (BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); } }

這部分代碼注冊bean后處理器的注冊流程如下。

這里寫圖片描述

整個流程根據PriorityOrdered、Ordered、非Ordered的順序注冊bean后處理器,最后注冊MergedBeanDefinitionPostProcessor bean后處理器。其中MergedBeanDefinitionPostProcessor會在其他bean后處理器執(zhí)行前執(zhí)行它的postProcessMergedBeanDefinition方法。

6. 初始化MessageSource國際化消息

執(zhí)行AbstractApplicationContext的initMessageSource方法,代碼如下

protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource"; // 檢測用戶是否指定了messageSource if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // 使當前messageSource能夠使用父容器中的messageSource if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isDebugEnabled()) { logger.debug("Using MessageSource [" + this.messageSource + "]"); } } else { // 用戶沒有指定messageSource // 使用一個空的MessageSource,以能夠接受getMessage方法的調用 DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isDebugEnabled()) { logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME + "': using default [" + this.messageSource + "]"); } } }

注意:如果要使用國際化消息,必須提供bean名稱為messageSource的MessageSource對象,形如下面的配置。

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>/WEB-INF/languages/globe/messages</value> </list> </property> <property name="cacheSeconds" value="1800"/> <property name="defaultEncoding" value="UTF-8"/> </bean>

7. 初始化事件傳播器

refresh()方法完成國際化消息對象初始化后,接著調用AbstractApplicationContext的initApplicationEventMulticaster方法為容器添加事件傳播器,代碼如下。

protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster"; // 檢測用戶是否制定了事件傳播器 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { // 使用默認的事件傳播器 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }

8. 其他初始化

refresh()方法完成國際化消息和事件傳播器的初始化后,把容器的初始化交給onRefresh()方法,代碼如下。

protected void onRefresh() throws BeansException { // For subclasses: do nothing by default. }

onRefresh()方法被設計成容器初始化的鉤子,以方便子類初始化其他特定的bean。例如,下面是在AbstractRefreshableWebApplicationContext類中onRefresh()方法被重寫的代碼。

/** * Initialize the theme capability. */ @Override protected void onRefresh() { this.themeSource = UiApplicationContextUtils.initThemeSource(this); }

其中,UiApplicationContextUtils工具類的initThemeSource(ApplicationContext context)方法的代碼如下。

public static ThemeSource initThemeSource(ApplicationContext context) { // 聲明有:public static final String THEME_SOURCE_BEAN_NAME = "themeSource"; if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) { ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class); // 使themeSource關聯父容器,這個父容器必須實現了ThemeSource接口 if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) { HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource; if (hts.getParentThemeSource() == null) { hts.setParentThemeSource((ThemeSource) context.getParent()); } } if (logger.isDebugEnabled()) { logger.debug("Using ThemeSource [" + themeSource + "]"); } return themeSource; } else { HierarchicalThemeSource themeSource = null; if (context.getParent() instanceof ThemeSource) { // 把對ThemeSource的操作代理給父容器 themeSource = new DelegatingThemeSource(); themeSource.setParentThemeSource((ThemeSource) context.getParent()); } else { // 使用默認的ThemeSource themeSource = new ResourceBundleThemeSource(); } if (logger.isDebugEnabled()) { logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME + "': using default [" + themeSource + "]"); } return themeSource; } }

9. 注冊監(jiān)聽器

執(zhí)行完成子類實現的onRefresh()方法,需要向容器中注冊各種監(jiān)聽器,此時執(zhí)行AbstractApplicationContext的registerListeners()方法,這個方法的代碼如下。

protected void registerListeners() { // 首先注冊容器中特定的事件監(jiān)聽器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 找到用戶配置的所有的監(jiān)聽器bean名稱 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { // 在事件傳播器中只保存監(jiān)聽器的bean名稱 // 這里不實例化監(jiān)聽器的原因是為了讓后處理器在它們真正實例化的時候作用于它們 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 發(fā)布那些需要提前發(fā)布的事件 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }

10. 實例化非延遲單例bean

前面所有的初始化操作都完成了后,則開始實例化剩下的單例非延遲加載的bean。通過執(zhí)行AbstractApplicationContext的finishBeanFactoryInitialization方法完成,這個方法的代碼如下。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 初始化ConversionService // 在ConfigurableApplicationContext接口中聲明:String CONVERSION_SERVICE_BEAN_NAME = "conversionService"; if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 注冊一個默認的內部value解析器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue(String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } // 初始化LoadTimeWeaverAware對象來支持注冊他們的transformers String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 停止使用臨時類加載器來做類型匹配 beanFactory.setTempClassLoader(null); // 允許緩存所有的bean元數據定義,不希望今后再更改 beanFactory.freezeConfiguration(); // 初始化所有非延遲單例bean beanFactory.preInstantiateSingletons(); }

11. 完成刷新

refresh()方法的最后一步,AbstractApplicationContext的finishRefresh方法,完成容器刷新,執(zhí)行LifecycleProcessor對象的onRefresh方法,以及發(fā)布刷新事件。代碼如下,

protected void finishRefresh() { // 初始化生命周期處理器,默認為DefaultLifecycleProcessor initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. // 首先把刷新操作傳遞給生命周期處理器 getLifecycleProcessor().onRefresh(); // 最后發(fā)布容器刷新事件 publishEvent(new ContextRefreshedEvent(this)); // 把spring容器加入到LiveBeansView的MBeanServer中 LiveBeansView.registerApplicationContext(this); } /** * 初始化生命周期處理器 **/ protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor"; if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { // 使用用戶指定的生命周期處理器 this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); if (logger.isDebugEnabled()) { logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]"); } } else { // 使用默認的聲明周期處理器 DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); if (logger.isDebugEnabled()) { logger.debug("Unable to locate LifecycleProcessor with name '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "': using default [" + this.lifecycleProcessor + "]"); } } }

到這里spring的刷新也就完成了。

總結


(1)spring的所有容器都直接或間接繼承了抽象類AbstractApplicationContext。

(2) spring的容器在創(chuàng)建并完成基本的配置后,在初次使用前,還必須執(zhí)行refresh()方法。

(3)實現BeanDefinitionRegistryPostProcessor 接口的后處理器可以在bean工廠創(chuàng)建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類,它主要把被@Configuration注解的類中定義的bean信息轉換成BeanDefinition對象,并注冊到bean工廠中。

(4)可以自定義BeanPostProcessor工廠后處理器對BeanDefinition對象做處理,比如spring的PreferencesPlaceholderConfigurer工廠后處理器,它把屬性文件中的值與BeanDefinition中相應的屬性值相替換。

(5)指定國際化消息時,MessageSource對象的bean名稱必須為messageSource。

(6)容器刷新過程中的鉤子方法有: a. initPropertySources()由子類根據自身的應用環(huán)境初始化property資源。 b. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)用于在bean工廠后處理器執(zhí)行前由子類對bean工廠做更多的初始化操作。 c. onRefresh()用于初始化子類中特定的bean。

(7)LiveBeansView的使用

Spring容器初始化過程中的最后一步,把spring容器加入到LiveBeansView的MBeanServer中。這個LiveBeansView它是一個MBean對象,它的作用是查看當前活動的bean以及這些bean的依賴。下面步驟介紹如何使用它。

a. 在web.xml文件配置如下,其中param-value可以任意取

<context-param> <param-name>spring.liveBeansView.mbeanDomain</param-name> <param-value>chyohn_liveBeansView</param-value> </context-param>

b. 啟動應用后,打開%java_HOME%/bin/jconsole.exe程序,如下

這里寫圖片描述

c. 我使用的tomcat服務器啟動的,點擊第2個鏈接,進入的頁面,如下

這里寫圖片描述

上面的JSON數據中就包含當前spring容器中所有的bean,是不是很神奇?這也是java MBean的一個例子。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
久草视频在线资源站| 日韩av密桃| 欧美国产日韩一区二区在线观看| 日本激情视频在线观看| 97视频在线看| 尤物网精品视频| 欧美日韩国产不卡| 8x8x拔插拔插影库永久免费| 精品久久在线播放| 日本成人免费| 国产又大又黄又粗又爽| www成人在线| 麻豆一区二区三区视频| 色午夜这里只有精品| heyzo一本久久综合| 欧美日韩电影在线| 粉嫩虎白女毛片人体| caoporn视频在线观看| 欧美最猛性xxxx高清| 国产午夜精品理论片在线| 国产精品又粗又长| 1000部国产精品成人观看| 玖玖玖免费嫩草在线影院一区| 8x拔播拔播x8国产精品| av网站在线观看不卡| 天天摸天天舔天天操| 国产伊人久久| 久久资源亚洲| 国产美女精品免费电影| 中文字幕乱码日本亚洲一区二区| 粗暴91大变态调教| 久久久无码精品亚洲国产| 欧美丰满一区二区免费视频| 激情一区二区| 日韩乱码人妻无码中文字幕| 欧美日本一区二区视频在线观看| 欧洲午夜精品久久久| 日韩亚洲不卡在线| 91人人澡人人爽| 国产三级精品视频| 亚洲av无码一区二区三区dv| 久久久久久久久久久久久久av| 蜜桃视频网站在线观看| 久久国产精品99久久久久久老狼| 欧美xxxxxxxxx| 国产精品入口免费| 精品肉丝脚一区二区三区| 亚洲av人人澡人人爽人人夜夜| 免费免费啪视频在线观播放| bdsmchinese医疗折磨| 91入口在线观看| 欧美日韩免费一区二区| 91看片免费| 欧洲一级精品| 成人免费乱码大片a毛片软件| 国产一区二区三区精彩视频| 老司机午夜在线视频| 国产日韩一区二区三区在线| 日韩激情av在线免费观看| 欧洲性视频在线播放| 亚洲黄色免费网站| 青青青国产视频| 欧美一区三区二区在线观看| 成人av动漫| 在线视频91p| 欧美激情视频在线观看| 丁香花在线电影| 99在线精品免费视频九九视| 成人黄页毛片网站| 免费又爽又黄禁片视频1000片| 日本三级在线电影| 中文字幕乱视频| 国产 欧美 日韩 在线| 中文字幕日本视频| 精品91久久| 国产视频在线观看网站| 日本免费网站视频| 国产伦精品一区二区三区视频网站| 男人添女荫道口女人有什么感觉| 91在线观看网站| 日韩理论片久久| 五月婷婷丁香色| 欧美丰满少妇xxxbbb| 91网页版在线| 国产精选在线视频拍拍拍| 中文字幕久久精品一区二区| 日本一区二区在线视频观看| 亚洲欧美日韩一区在线观看| 四虎影视18库在线影院| 91啪九色porn原创视频在线观看| 成人夜晚看av| 日韩三级网址| 国产精品pans私拍| 91精品国产入口在线| 色琪琪综合男人的天堂aⅴ视频| 亚洲九九精品| 久久99国产精品久久久久久久久| 中国女人内谢25xxxx免费视频| 欧美激情aⅴ一区二区三区| videos性欧美另类高清| 青青草av免费在线观看| 天天夜夜人人| 九色porny蝌蚪视频在线观看| 日本强好片久久久久久aaa| 国产91在线免费观看| 精品1区2区在线观看| 极品尤物一区二区三区| 亚洲午夜激情网页| 最近2019中文字幕大全第二页| 老司机aⅴ在线精品导航| 欧美精品xx| 日韩精品一区二区三区四区五区| 日韩av在线精品| 欧美日韩国产一区二区三区不卡| 国产亚洲第一区| ●精品国产综合乱码久久久久| 久久黄色免费看| 一区二区日韩精品| 6080午夜| 精品久久久影院| 性生活一级大片| 亚洲经典一区二区三区| 日韩字幕在线观看| 国产福利小视频在线观看| 日韩在线视频免费观看高清中文| 国产精品理论片| 欧美香蕉大胸在线视频观看| 国内精品久久久久久影院老狼| 国产成人免费视频一区| 绯色av蜜臀vs少妇| 97影视在线观看| 色在线中文字幕| 久久久久久久久影院| 亚洲精品视频导航| 久久久精品国产一区二区三区| 韩国三级成人在线| 91丨国产丨九色丨pron| 精品国产一区二区三区香蕉沈先生| 美女av在线播放| 99re在线播放| 欧美a在线播放| 国产wwwxx| 欧美日韩视频免费看| 狠狠色丁香婷综合久久| 亚洲午夜精品一区二区国产| 4438成人网| 麻豆国产精品一区| 99精品视频免费全部在线| 欧产日产国产69| 成人精品电影在线观看| 国产欧美一区二区在线播放| 日本欧美在线视频| 国产女主播视频一区二区| 羞羞网站在线免费观看| 高清在线观看av| 国产精品18久久久久久久久久| 国产精品免费成人| 亚洲精品97久久久babes| 国产亚洲第一伦理第一区| 少妇精品视频一区二区| 欧美24videosex性欧美| 中文另类视频| 一区二区蜜桃| 国产成人在线精品| 国产高清精品二区| 999精品在线观看| 国产成人麻豆免费观看| 久久久久久久久久久久久91| 免费欧美激情| 精品欧美日韩在线| 美日韩在线观看| 国内视频在线精品| 亚洲7777| 韩日a级毛片| 伊人精品视频| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 国产精品一区二区不卡视频| 中文字幕视频免费在线观看| 三级毛片网站| 国产欧美一区二区精品性色超碰| 日本一本中文字幕| 日韩亚洲一区在线播放| 国产裸体永久免费无遮挡| 欧美黄色成人| 亚洲视频欧美视频| 久久久久亚洲精品一区二区三区| 亚洲乱码一区二区三区| 久久成人免费| 黄色美女网站在线观看| 亚洲欧美在线一区二区| 国产伦精品一区二区三区视频金莲| 欧美日韩xxxx| 成人区人妻精品一区二| 先锋影音亚洲资源| 欧美激情视频播放| 波多野结衣在线一区二区| 日韩精品一区二区三区蜜臀| 欧美性受xxxx黑人xyx性爽| 亚洲线精品一区二区三区| 免费看电影在线| 国产亚洲欧美日韩精品| 欧美牲交a欧美牲交aⅴ免费真| 国产嫩草一区二区三区在线观看| 99国产精品一区二区三区| 91中文字精品一区二区| 高清美女视频一区| 91禁男男在线观看| 蜜桃av色综合| 老司机在线精品视频| 亚洲欧美天堂在线| 日韩一区精品| 538精品视频| 国产精品色网| 成人精品一区二区三区电影黑人| 中文字幕欧美精品日韩中文字幕| 亚洲视频在线观看免费| 色综合久久综合网欧美综合网| 老熟妇高潮一区二区三区| 日韩精品乱码免费| 伊人网在线播放| 亚洲国产一区二区三区在线播| 国产精品久久久久久9999| 国产98在线| 一卡二卡三卡四卡| av理论在线观看| 日韩一二三在线视频播| 久久精品国产99国产精品澳门| 新版的欧美在线视频| 日产精品99久久久久久| 亚洲国产精品va在线观看黑人| 丁香在线视频| 欧美国产综合色视频| 波多野结衣91| 欧美一级xxx| 高端美女服务在线视频播放| 成年人视频观看| 亚洲欧美视频一区二区三区| 天天操天天干天天舔| 久久成人免费电影| 日韩三级电影免费观看| 羞羞色国产精品| 天堂中文字幕一二区| 国产精品欧美久久久久一区二区| 久久国产精品免费| 夜色福利资源站www国产在线视频| 亚洲天堂av高清| 一级香蕉视频在线观看| 浮生影视网在线观看免费| 国产一区久久久| 日本免费黄网站| 国产 日韩 欧美大片| 五月婷婷六月婷婷| 加勒比av中文字幕| 欧美又粗又大又爽| 欧美大学生性色视频| 亚洲男人的天堂在线aⅴ视频| 久久不射中文字幕| 91大神在线资源观看无广告| 7777精品伊人久久久大香线蕉最新版| free性欧美高清另类| 91麻豆精品国产自产在线观看一区| 黄色网址在线免费| 国产乱人视频免费播放| 国产九九在线视频| 性欧美极品xxxx欧美一区二区| 999国产在线视频| 日韩欧美精品一区二区| 川上优av中文字幕一区二区| 91成人在线| 在线免费av播放| 久久久青草婷婷精品综合日韩| 伊人久久精品一区二区三区| 在线视频一区二区三区四区| 日本色综合中文字幕| 国产午夜精品久久久| 美女日韩在线中文字幕| 最新热久久免费视频| 妺妺窝人体色www在线下载| 一二三四视频在线社区中文字幕2| 亚洲国产精品电影在线观看| 日本在线观看网址| 亚洲免费看片| 亚洲国产精品人人爽夜夜爽| 久久中文视频| av无码av天天av天天爽| 亚洲综合自拍一区| 国产不卡视频在线观看| 国产一区二三区好的| 国产 日韩 欧美 综合 一区| 全部孕妇毛片丰满孕妇孕交| 日韩中文一区二区三区| 久久久精品2019中文字幕神马| 日韩精品亚洲一区二区三区免费| 日韩成人手机在线| 欧美片第1页综合| 国产视频手机在线播放| 久久久久亚洲蜜桃| www毛片com| 色婷婷久久久综合中文字幕| 先锋影音av321| 先锋影音资源综合在线播放av| 亚洲最新免费视频| 国产乱码精品一区二区三区卡| 国产欧美一区二区三区在线| 日日躁夜夜躁人人揉av五月天| 涩涩视频在线免费看| 日本美女bbw| 99视频在线观看一区三区| 精品无码一区二区三区爱欲| 日韩免费观看在线观看| 性插视频在线观看| 三级视频在线观看| www.欧美日本| 国产91露脸中文字幕在线| 波多野结衣免费观看| 亚洲老板91色精品久久| 亚洲精品国产一区黑色丝袜| 成人av在线观| 骚虎黄色影院| 亚洲一区二区三区xxx视频| 在线播放一区二区精品视频| 日韩少妇高潮抽搐| 久久偷看各类wc女厕嘘嘘偷窃| 国产乱淫片视频| 国产精品一区二区三区av| 欧美一级免费观看| a级黄色免费视频| 色欲无码人妻久久精品|