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

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring IOC源代码具体解释之容器初始化

發布時間:2025/3/20 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring IOC源代码具体解释之容器初始化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Spring IOC源代碼具體解釋之容器初始化

上篇介紹了Spring IOC的大致體系類圖,先來看一段簡短的代碼,使用IOC比較典型的代碼

ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res);

上面使用創建IOC經歷了四個過程

  • 創建IOC配置文件的抽象資源
  • 創建一個BeanFactory
  • 把讀取配置信息的BeanDefinitionReader,這里是XmlBeanDefinitionReader配置給BeanFactory
  • 從定義好的資源位置讀入配置信息,詳細的解析過程由XmlBeanDefinitionReader來完畢,這樣完畢整個加載bean定義的過程。

從上面能夠看出,整個IOC初始化,大致分為資源定位、資源裝載、資源解析、Bean生成,Bean注冊這幾個過程

首先看資源的定位,一個常見的ApplicationContext

ApplicationContext =new FileSystemXmlApplicationContext(xmlPath);

追蹤FileSystemXmlApplicationContext。里面有一些構造函數,都指向以下這個

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent); //有前面類圖 可 以知道,終于 父類 為AbstractApplicationContextsetConfigLocations(configLocations);if (refresh) {refresh();}} //追蹤super,終于定位到 AbstractApplicationContext中public AbstractApplicationContext() {this.resourcePatternResolver = getResourcePatternResolver();}protected ResourcePatternResolver getResourcePatternResolver() {return new PathMatchingResourcePatternResolver(this);}

繼續往下,追蹤setConfigLocations方法

public void setConfigLocations(String... locations) {if (locations != null) {Assert.noNullElements(locations, "Config locations must not be null");this.configLocations = new String[locations.length];// 該方法調用 SystemPropertyUtils.resolvePlaceholders(path) ;對 path 中的占位 符進行// 替換, eg : path 路徑中含有 ${user.dir} ,則將替換為: System.getProperty(user.dir);for (int i = 0; i < locations.length; i++) {this.configLocations[i] = resolvePath(locations[i]).trim();}}else {this.configLocations = null;}} 代碼中 configLocations 為 AbstractRefreshableConfigApplicationContext 類中 string[] 類型的字段。至此應用程序傳入路徑保存在 AbstractRefreshableConfigApplicationContext 中 。

回到FileSystemXmlApplicationContext中繼續往下。即最關鍵的Refash方法,refresh()-方法定義在類: AbstractApplicationContext ,由類圖可知: FileSystemXmlApplicationContext 間接繼承至: AbstractApplicationContext refresh() 方法例如以下:

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //調用容器準備刷新的方法,獲取 容器的當時時間,同一時候給容器設置同步標識 prepareRefresh(); //告訴子類啟動refreshBeanFactory()方法。Bean定義資源文件的載入從 //子類的refreshBeanFactory()方法啟動 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //為BeanFactory配置容器特性,比如類載入器、事件處理器等 prepareBeanFactory(beanFactory); try { //為容器的某些子類指定特殊的BeanPost事件處理器 postProcessBeanFactory(beanFactory); //調用全部注冊的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory); //為BeanFactory注冊BeanPost事件處理器. //BeanPostProcessor是Bean后置處理器。用于監聽容器觸發的事件 registerBeanPostProcessors(beanFactory); //初始化信息源,和國際化相關. initMessageSource(); //初始化容器事件傳播器. initApplicationEventMulticaster(); //調用子類的某些特殊Bean初始化方法 onRefresh(); //為事件傳播器注冊事件監聽器. registerListeners(); //初始化全部剩余的單態Bean. finishBeanFactoryInitialization(beanFactory); //初始化容器的生命周期事件處理器,并公布容器的生命周期事件 finishRefresh(); } catch (BeansException ex) { //銷毀以創建的單態Bean destroyBeans(); //取消refresh操作。重置容器的同步標識. cancelRefresh(ex); throw ex; } } }
  • prepareRefresh(): 為刷新準備上下文環境

    • obtainFreshBeanFactory() :讓子類刷新內部 bean 工廠。

進入obtainFreshBeanFatory()。關閉前面全部 bean 工廠,為新的上下文環境初始化一個新的 bean 工廠。這里須要子類來 協助完畢資源位置定義 ,bean 加載和向 IOC 容器注冊的過程

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;}

上面代碼能夠看到refreshBeanFactory,AbstractApplicationContext子類中的方法 AbstractApplicationContext類中僅僅抽象定義了refreshBeanFactory()方法。容器真正調用的是其子類AbstractRefreshableApplicationContext實現的 refreshBeanFactory()方法,方法的源代碼例如以下

protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) {//假設已經有容器。銷 毀 容器中的bean,關閉容器 destroyBeans(); closeBeanFactory(); } try { //創建IoC容器 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); //對IoC容器進行定制化,如設置啟動參數,開啟注解的自己主動裝配等 customizeBeanFactory(beanFactory); //調用加載Bean定義的方法,主要這里使用了一個委派模式。在當前類中僅僅定義了抽象的loadBeanDefinitions方法,詳細的實現調用子類容器 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } 在這種方法中,先推斷BeanFactory是否存在,假設存在則先銷毀beans并關閉beanFactory,接著創建DefaultListableBeanFactory,并調用loadBeanDefinitions(beanFactory)裝載bean

在這種方法中,先推斷BeanFactory是否存在,假設存在則先銷毀beans并關閉beanFactory,接著創建DefaultListableBeanFactory,并調用loadBeanDefinitions(beanFactory)裝載bean定義。看上面的loadBeanDefinitions。在AbstractRefreshableApplicationContext子類。

相同。AbstractRefreshableApplicationContext中僅僅定義了抽象的loadBeanDefinitions方法,容器真正調用的是其子類AbstractXmlApplicationContext對該方法的實現,AbstractXmlApplicationContext的主要源代碼例如以下: protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {// 這里使用XMLBeanDefinitionReader來加載bean定義信息的XML文件XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//這里配置reader的環境,當中ResourceLoader是我們用來定位bean定義信息資源位置的///由于上下文本身實現了ResourceLoader接口,所以能夠直接把上下文作為ResourceLoader傳遞給XmlBeanDefinitionReaderbeanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));initBeanDefinitionReader(beanDefinitionReader);//這里轉到定義好的XmlBeanDefinitionReader中對加載bean信息進行處理loadBeanDefinitions(beanDefinitionReader);}

繼續,看到了最以下的loadBeanDefinitions(beanDefinitionReader);轉到XmlBeanDefinitionReader中的loadBeanDefinitions。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {Resource[] configResources = getConfigResources();if (configResources != null) {//調用XmlBeanDefinitionReader來加載bean定義信息。 reader.loadBeanDefinitions(configResources);}String[] configLocations = getConfigLocations();if (configLocations != null) {reader.loadBeanDefinitions(configLocations);}} Xml Bean讀取器(XmlBeanDefinitionReader)調用其父類AbstractBeanDefinitionReader的 reader.loadBeanDefinitions方法讀取Bean定義資源。

因為我們使用FileSystemXmlApplicationContext作為樣例分析,因此getConfigResources的返回值為null,因此程序運行reader.loadBeanDefinitions(configLocations)分支。

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { //這里得到當前定義的ResourceLoader,默認的 我 們 使用DefaultResourceLoaderResourceLoader resourceLoader = getResourceLoader();.........//假設沒有找到我們須要的ResourceLoader,直接拋出異常if (resourceLoader instanceof ResourcePatternResolver) {// 這里處理我們在定義位置時使用的各種pattern,須要ResourcePatternResolver來完畢try {Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);int loadCount = loadBeanDefinitions(resources);return loadCount;}........}else {// 這里通過ResourceLoader來完畢位置定位Resource resource = resourceLoader.getResource(location);// 這里已經把一個位置定義轉化為Resource接口,能夠供XmlBeanDefinitionReader來使用了int loadCount = loadBeanDefinitions(resource);return loadCount;}} 重載方法public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {Assert.notNull(locations, "Location array must not be null");int counter = 0;for (String location : locations) {counter += loadBeanDefinitions(location);}return counter;}

loadBeanDefinitions(Resource...resources)方法和上面分析的3個方法類似,相同也是調用XmlBeanDefinitionReader的loadBeanDefinitions方法。

從對AbstractBeanDefinitionReader的loadBeanDefinitions方法源代碼分析能夠看出該方法做了下面兩件事:

  • 首先,調用資源載入器的獲取資源方法resourceLoader.getResource(location)。獲取到要載入的資源。

  • 其次,真正運行載入功能是其子類XmlBeanDefinitionReader的loadBeanDefinitions方法。

由上類圖能夠知道此時調用的是DefaultResourceLoader中的getSource()方法定位Resource。由于FileSystemXmlApplicationContext本身就是DefaultResourceLoader的實現類。

2、資源載入

XmlBeanDefinitionReader通過調用其父類DefaultResourceLoader的getResource方法獲取要載入的資源,這樣,就能夠從文件系統路徑上對IOC配置文件進行載入 - 當然能夠依照這個邏輯從不論什么地方載入,在Spring中看到它提供的各種資源抽象。比方ClassPathResource, URLResource,FileSystemResource等來供我們使用。

//獲取Resource的具 體實現方法 public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); //假設是類路徑的方式。那須要使用ClassPathResource 來得到bean 文件的資源對象 if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } try { // 假設是URL 方式,使用UrlResource 作為bean 文件的資源對象 URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException ex) { } //假設既不是classpath標識。又不是URL標識的Resource定位,則調用 //容器本身的getResourceByPath方法獲取Resource return getResourceByPath(location); }

FileSystemXmlApplicationContext容器提供了getResourceByPath方法的實現。就是為了處理既不是classpath標識,又不是URL標識的Resource定位這樣的情況

@Overrideprotected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}

所以此時又回到了FileSystemXmlApplicationContext中來,提供了FileSystemResource來完畢從文件系統得到配置文件的資源定義。

Bean資源載入

繼續XmlBeanDefinitionReader的loadBeanDefinitions(Resource …)

//XmlBeanDefinitionReader加載資源 的入口方法 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { //將讀入的XML資源進行特殊編碼處理 return loadBeanDefinitions(new EncodedResource(resource)); } //這里是加載XML形式Bean定義資源文件方法public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { ....... try { //將資源文件轉為InputStream的IO流 InputStream inputStream = encodedResource.getResource().getInputStream(); try { //從InputStream中得到XML的解析源 InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } //這里是具體的讀取過程 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { //關閉從Resource中得到的IO流 inputStream.close(); } } ......... 26} //從特定XML文件里實際加載Bean定義資源的方法 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); //將XML文件轉換為DOM對象,解析過程由documentLoader實現 Document doc = this.documentLoader.loadDocument( inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware); //這里是啟動對Bean定義解析的具體過程,該解析過程會用到Spring的Bean配置規則return registerBeanDefinitions(doc, resource); } ....... }

源代碼的最后。將XML文件轉為DOM對象,即將Bean對象轉成DOm資源。這是怎樣完畢的呢?

3、資源解析

2中Bean定義的Resource得到了。最后還講到ocumentLoader將Bean定義資源轉換為Document對象:DocumentLoader將Bean定義資源轉換成Document對象的源代碼例如以下:

以下這句是XmlBeanDefinitionReader中關于DocumentLoader。用了DefaultDocumentLoaderprivate DocumentLoader documentLoader = new DefaultDocumentLoader();

上面的DefaultDocumentLoader肯定不陌生吧。在Spring AOP中多次出現了。找到DefaultDocumentLoader中的loadDocument()方法

//使用標準的JAXP 將 加載的B ean 定義 資源 轉換成document對象 public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { //創建文件解析器工廠 DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); if (logger.isDebugEnabled()) { logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]"); } //創建文檔解析器 DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); //解析Spring的Bean定義資源 return builder.parse(inputSource); }

繼續找到createDocumentBuilder

protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)throws ParserConfigurationException {DocumentBuilder docBuilder = factory.newDocumentBuilder();if (entityResolver != null) {docBuilder.setEntityResolver(entityResolver);}if (errorHandler != null) {docBuilder.setErrorHandler(errorHandler);}return docBuilder;}

上面調用了Javaee的JAXP標準。依據定位的Bean定義資源文件,載入讀入并轉換成為Document對象過程完畢

4、bean生成(依據DOM資源解析成bean)

回想3: XmlBeanDefinitionReader類中的doLoadBeanDefinitions方法是從特定XML文件里實際加載Bean定義資源的方法,該方法在加載Bean定義資源之后將其轉換為Document對象。繼續看doLoadBeanDefinitions,進入registerBeanDefinitions

Document doc = this.documentLoader.loadDocument()后面。有一句return registerBeanDefinitions(doc, resource); //依照Spring的Bean語義要求 將Bean 定 義 資源解析并轉換為容器內部數據結構 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //得到BeanDefinitionDocumentReader來對xml格式的BeanDefinition解析 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //獲得容器中注冊的Bean數量 int countBefore = getRegistry().getBeanDefinitionCount(); //解析過程入口。這里使用了委派模式,BeanDefinitionDocumentReader僅僅是個接口,//詳細的解析實現過程有實現類DefaultBeanDefinitionDocumentReader完畢 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); //統計解析的Bean數量 return getRegistry().getBeanDefinitionCount() - countBefore; } //創建BeanDefinitionDocumentReader對象。 解 析 D ocument對象 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass)); }

Bean定義資源的加載解析分為下面兩個過程:

  • 首先。通過調用XML解析器將Bean定義資源文件轉換得到Document對象,可是這些Document對象并沒有依照Spring的Bean規則進行解析。這一步是加載的過程

  • 其次,在完畢通用的XML解析之后,依照Spring的Bean規則對Document對象進行解析。

繼續

documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 這里的documentReader為BeanDefinitionDocumentReader對象,BeanDefinitionDocumentReader接口通過registerBeanDefinitions方法調用事實上現類DefaultBeanDefinitionDocumentReader對Document對象進行解析 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;//獲得XML 描 述 符 logger.debug("Loading bean definitions");Element root = doc.getDocumentElement();//獲得Document的根元素 doRegisterBeanDefinitions(root);} protected void doRegisterBeanDefinitions(Element root) {//BeanDefinitionParserDelegate中定義了Spring Bean 定 義 XML 文件的各種元素BeanDefinitionParserDelegate parent = this.delegate;this.delegate = createDelegate(getReaderContext(), root, parent);//以下有解析if (this.delegate.isDefaultNamespace(root)) { //這里應該是推斷是否使用默認命名空間String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {return;}}}//在解析Bean定義之前,進行自己定義的解析,增強解析過程的可擴展性 preProcessXml(root);//從Document的根元素開始進行Bean定義的Document對象,見以下解析parseBeanDefinitions(root, this.delegate);//在解析Bean定義之后,進行自己定義的解析,添加解析過程的可擴展性 postProcessXml(root);this.delegate = parent;} //上面的createDelegate()方法, 創建BeanDefinitionParserDelegate,用于完畢真正的解析過程 protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);//BeanDefinitionParserDelegate初始化Document根元素 delegate.initDefaults(root, parentDelegate);return delegate;} //上面的parseBeanDefinitions// 使 用Spring的Bean規則從Document的根元素開始進行Bean定義的Document對象 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {//Bean定義的Document對象使用了Spring默認的XML命名空間 if (delegate.isDefaultNamespace(root)) {//獲取Bean定義的Document對象根元素的全部子節點 NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {//獲得Document節點是XML元素節點 Node node = nl.item(i); if (node instanceof Element) {Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {//假設使用的是默認命名控件,使用Spring的Bean規則解析元素節點 parseDefaultElement(ele, delegate);}else {//沒有使用Spring默認的XML命名空間。則使用用戶自己定義的解//析規則解析元素節點 delegate.parseCustomElement(ele);}}}}else {//使用默認解析規則解析Document根節點 delegate.parseCustomElement(root);}} //使用默 認 規 則 是個什么樣子呢private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {//元素節點是IMPORT導入if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}//元素節點是Alias相關else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}//元素節點是Bean元素else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}

上面代碼的三中Import、Alials、Bean我們主要來看Bean的解析,追蹤processBeanDefinition(ele, delegate

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {//托付給BeanDefinitionParserDelegate來完畢對bean元素的 處 理 。這個類包括了詳細的bean解析的過程。 // 把解析bean文件得到的信息放到BeanDefinition里,他是bean信息的主要載體。也是IOC容器的管理對象。

//BeanDefinitionHolder是對BeanDefinition的封裝。即Bean定義的封裝類 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) {//假設存在bean定義的話 //對Document對象中<Bean>元素的解析由BeanDefinitionParserDelegate實現 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { //向Spring IoC容器注冊解析得到的Bean定義。這是Bean定義向IoC容器注冊的入口 。實際上是放到一個Map里面 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } //在完畢向Spring IoC容器注冊解析得到的Bean定義之后。發送注冊事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

這里事實上還能夠深入了解,bean的解析。追蹤上面的這條

BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

能夠進入parseBeanDefinitionElement方法中,里面具體講了Bean元素是怎樣解析的。

//解析<Bean>元素的入口 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } //解析Bean定義資源文件里的<Bean>元素。這個 方 法中主要處理<Bean>元素的id,name //和別名屬性 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { //獲取<Bean>元素中的id屬性值 String id = ele.getAttribute(ID_ATTRIBUTE); //獲取<Bean>元素中的name屬性值 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 獲取<Bean>元素中的alias屬性值 List<String> aliases = new ArrayList<String>(); //將<Bean>元素中的全部name屬性值存放到別名中 if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; //假設<Bean>元素中沒有配置id屬性時,將別名中的第一個值賦值給beanName if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } //檢查<Bean>元素所配置的id或者name的唯一性,containingBean標識<Bean> //元素中是否包括子<Bean>元素 if (containingBean == null) { //檢查<Bean>元素所配置的id、name或者別名是否反復 checkNameUniqueness(beanName, aliases, ele); } //具體對<Bean>元素中配置的Bean定義進行解析的地方 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { //假設<Bean>元素中沒有配置id、別名或者name。且沒有包括子//<Bean>元素,為解析的Bean生成一個唯一beanName并注冊 beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { //假設<Bean>元素中沒有配置id、別名或者name,且包括了子//<Bean>元素,為解析的Bean使用別名向IoC容器注冊 beanName = this.readerContext.generateBeanName(beanDefinition); //為解析的Bean使用別名注冊時,為了向后兼容 //Spring1.2/2.0。給別名加入類名后綴 String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } //當解析出錯時,返回null return null; } //具體對<Bean>元素中配置的Bean定義其它屬性進行解析,因為上面的方法中已經對//Bean的id、name和別名等屬性進行了處理,該方法中主要處理除這三個以外的其它屬性數據 public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { //記錄解析的<Bean> this.parseState.push(new BeanEntry(beanName)); //這里僅僅讀取<Bean>元素中配置的class名字,然后加載到BeanDefinition中去 //僅僅是記錄配置的class名字,不做實例化,對象的實例化在依賴注入時完畢 String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; //假設<Bean>元素中配置了parent屬性。則獲取parent屬性的值 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } //依據<Bean>元素配置的class名稱和parent屬性值創建BeanDefinition //為加載Bean定義信息做準備 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //對當前的<Bean>元素中配置的一些屬性進行解析和設置。如配置的單態(singleton)屬性等 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //為<Bean>元素解析的Bean設置description信息 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //對<Bean>元素的meta(元信息)屬性解析 parseMetaElements(ele, bd); //對<Bean>元素的lookup-method屬性解析 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //對<Bean>元素的replaced-method屬性解析 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //解析<Bean>元素的構造方法設置 parseConstructorArgElements(ele, bd); //解析<Bean>元素的<property>設置 parsePropertyElements(ele, bd); //解析<Bean>元素的qualifier屬性 parseQualifierElements(ele, bd); //為當前解析的Bean設置所需的資源和依賴對象 bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } //解析<Bean>元素出錯時。返回null return null; }

上面方法中一些對一些配置如元信息(meta)、qualifier等的解析。我們在Spring中配置時使用的也不多。我們在使用Spring的元素時,配置最多的是property屬性

//解析<property>元素中ref,value或者集合等子元素 public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) { //假設<property>沒有使用Spring默認的命名空間,則使用用戶自己定義的規則解析//內嵌元素 if (!isDefaultNamespace(ele)) { return parseNestedCustomElement(ele, bd); } //假設子元素是bean,則使用解析<Bean>元素的方法解析 else if (nodeNameEquals(ele, BEAN_ELEMENT)) { BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); if (nestedBd != null) { nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); } return nestedBd; } //假設子元素是ref。ref中僅僅能有下面3個屬性:bean、local、parent else if (nodeNameEquals(ele, REF_ELEMENT)) { //獲取<property>元素中的bean屬性值,引用其它解析的Bean的名稱 //能夠不再同一個Spring配置文件里。詳細請參考Spring對ref的配置規則 String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); boolean toParent = false; if (!StringUtils.hasLength(refName)) { //獲取<property>元素中的local屬性值。引用同一個Xml文件里配置 //的Bean的id,local和ref不同,local僅僅能引用同一個配置文件里的Bean refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE); if (!StringUtils.hasLength(refName)) { //獲取<property>元素中parent屬性值,引用父級容器中的Bean refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); toParent = true; if (!StringUtils.hasLength(refName)) { error("'bean', 'local' or 'parent' is required for <ref> element", ele); return null; } } } //沒有配置ref的目標屬性值 if (!StringUtils.hasText(refName)) { error("<ref> element contains empty target attribute", ele); return null; } //創建ref類型數據。指向被引用的對象 RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); //設置引用類型值是被當前子元素所引用 ref.setSource(extractSource(ele)); return ref; } //假設子元素是<idref>。使用解析ref元素的方法解析 else if (nodeNameEquals(ele, IDREF_ELEMENT)) { return parseIdRefElement(ele); } //假設子元素是<value>,使用解析value元素的方法解析 else if (nodeNameEquals(ele, VALUE_ELEMENT)) { return parseValueElement(ele, defaultValueType); } //假設子元素是null。為<property>設置一個封裝null值的字符串數據 else if (nodeNameEquals(ele, NULL_ELEMENT)) { TypedStringValue nullHolder = new TypedStringValue(null); nullHolder.setSource(extractSource(ele)); return nullHolder; } //假設子元素是<array>,使用解析array集合子元素的方法解析 else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { return parseArrayElement(ele, bd); } //假設子元素是<list>,使用解析list集合子元素的方法解析 else if (nodeNameEquals(ele, LIST_ELEMENT)) { return parseListElement(ele, bd); } //假設子元素是<set>,使用解析set集合子元素的方法解析 else if (nodeNameEquals(ele, SET_ELEMENT)) { return parseSetElement(ele, bd); } //假設子元素是<map>,使用解析map集合子元素的方法解析 else if (nodeNameEquals(ele, MAP_ELEMENT)) { return parseMapElement(ele, bd); } //假設子元素是<props>,使用解析props集合子元素的方法解析 else if (nodeNameEquals(ele, PROPS_ELEMENT)) { return parsePropsElement(ele); } //既不是ref,又不是value。也不是集合。則子元素配置錯誤,返回null else { error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } }

上面代碼中對property元素中配置的Array、List、Set、Map、Prop等各種集合子元素的都通過上述方法解析。生成相應的數據對象,比方ManagedList、ManagedArray、ManagedSet等,這些Managed類是Spring對象BeanDefiniton的數據封裝。對集合數據類型的詳細解析有各自的解析方法實現。假設想了解當中的一種集合是怎樣解析的 ,進入相應的方法。

5、Bean是怎樣在IOC容器中注冊的

以下看解析完的bean是如何在IOC容器中注冊的:接著4中的代碼,進入

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {//得到須要 注冊 的 bean名字String beanName = definitionHolder.getBeanName();//開始注冊registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// 別名也是能夠 通過IOC容器和bean聯系起來的進行注冊 String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}} 上面的registry對象是BeanDefinitionRegistry,上一步是BeanDefinitionReaderUtils.registerBeanDefinition(),即當調用BeanDefinitionReaderUtils向IoC容器注冊解析的BeanDefinition時。真正完畢注冊功能的是DefaultListableBeanFactory。

那么DefaultListableBeanFactory怎么會和BeanDefinitionReaderUtils扯到一起呢?

事實上上面的類圖還忽略了一點,就是

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {}DefaultListableBeanFactory 實現了BeanDefinitionRegistry接口。這下就豁然開朗,那么DefaultListableBeanFactory是怎樣注冊的呢

DefaultListableBeanFactory中使用一個HashMap的集合對象存放IoC容器中注冊解析的BeanDefinition。

@Override//---------------------------------------------------------------------// 這里是IOC容器對BeanDefinitionRegistry接口的實現//---------------------------------------------------------------------public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {.....//這里省略了對BeanDefinition的驗證過程//先看看在容器里是不是已經有了同名的bean,假設有拋出異常。Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);if (oldBeanDefinition != null) {if (!this.allowBeanDefinitionOverriding) {...........}else {//把bean的名字加到IOC容器中去this.beanDefinitionNames.add(beanName);}//這里把bean的名字和Bean定義聯系起來放到一個HashMap中去,IOC容器通過這個Map來維護容器里的Bean定義信息。this.beanDefinitionMap.put(beanName, beanDefinition);removeSingleton(beanName);}

這樣就完畢了Bean定義在IOC容器中的注冊。就可被IOC容器進行管理和使用了

總結IOC初始化過程

  • 1、setConfigLocations方法

  • 2、初始化的入口在容器實現中的 refresh()調用來完畢

  • 3、AbstractRefreshableApplicationContext實現的 refreshBeanFactory()方法

  • 4、創建DefaultListableBeanFactory,并調用loadBeanDefinitions(beanFactory)裝載bean定義

  • 5、轉到XmlBeanDefinitionReader中的loadBeanDefinitions。

  • 6、XmlBeanDefinitionReader通過調用其父類DefaultResourceLoader的getResource方法獲取要載入的資源

  • 7 、DocumentLoader將Bean定義資源轉換成Document對象

  • 8、doLoadBeanDefinitions中進入registerBeanDefinitions 解 析 D ocument對象

  • 9、DefaultListableBeanFactory中使用一個HashMap的集合對象存放IoC容器中注冊解析的BeanDefinition,

總結

以上是生活随笔為你收集整理的Spring IOC源代码具体解释之容器初始化的全部內容,希望文章能夠幫你解決所遇到的問題。

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

欧美一级裸体视频 | 精品视频一区在线观看 | 97成人精品视频在线观看 | 国产精品成人在线观看 | 欧美在线观看视频一区二区 | 最近中文字幕免费大全 | 精品久久1 | 成年人网站免费观看 | 在线有码中文字幕 | 精品国产乱码久久久久久天美 | 亚洲一级片 | 欧美久久久久久久久久久久 | 97视频免费| 国产精品成人一区二区 | 国内少妇自拍视频一区 | 人人干免费 | 国产一级视屏 | 91精品国产三级a在线观看 | 日韩成人中文字幕 | www久久国产| 久草视频精品 | av中文字幕免费在线观看 | 天天操人人干 | 狠狠久久综合 | 欧美天堂久久 | 国产自制av | 久草干| 97综合视频 | 久久免费视频2 | 在线免费国产视频 | 蜜臀av网址| 婷婷丁香花 | 国产精品18久久久久久不卡孕妇 | 日韩中文字幕免费视频 | 在线超碰av| 国内三级在线 | 国产在线观看一 | 日日爱视频 | 天天综合色| 国产精品毛片久久久久久久 | 一级片视频在线 | 日韩综合色 | 欧美综合色在线图区 | 中文字幕av网站 | 国产精品刺激对白麻豆99 | 精品久久久久久久久久 | 国产美女主播精品一区二区三区 | 日本中文字幕在线播放 | 欧美日韩一区二区在线观看 | 这里只有精品视频在线 | 综合色中文 | 中文字幕乱码一区二区 | 国产精品久久久久久高潮 | 激情文学综合丁香 | 在线免费观看涩涩 | 在线激情网| 天天天在线综合网 | 欧美日韩在线视频观看 | 在线观看一级 | 亚洲最新精品 | 极品嫩模被强到高潮呻吟91 | 成人在线免费观看网站 | 91av电影在线 | 亚洲精品午夜视频 | 中文字幕av免费观看 | 国产成人亚洲精品自产在线 | 国产精品免费观看视频 | 天天射天天舔天天干 | 一二三区视频在线 | 精品免费一区 | 国产一区二区观看 | 亚洲激情在线播放 | 激情偷乱人伦小说视频在线观看 | 色五月色开心色婷婷色丁香 | 99亚洲精品视频 | 成年人免费看片 | 国产高清一 | 婷婷在线五月 | 麻花豆传媒mv在线观看网站 | 在线视频观看你懂的 | 高潮毛片无遮挡高清免费 | 性色xxxxhd| 久久精品79国产精品 | 日日干美女 | 看毛片网站 | 婷婷在线精品视频 | 日韩特级黄色片 | 午夜av色 | 久久久毛片| 天天干天天操天天操 | 欧美精品中文在线免费观看 | 91视频亚洲 | 色综合久久久久网 | 五月婷婷国产 | www免费看片com | 在线国产中文字幕 | 国产精品久久久久高潮 | 亚洲精品视频偷拍 | 99精品在线免费 | 亚洲精品在 | 亚洲日日射 | av成人在线观看 | 91av福利视频 | 成人在线免费小视频 | 亚洲欧美日韩国产一区二区 | 九七人人干 | 最近免费中文字幕大全高清10 | 亚洲精品永久免费视频 | 欧美韩日在线 | 国产成视频在线观看 | www.久久久| 久久国产高清视频 | 91精品在线播放 | 亚洲 欧洲 国产 日本 综合 | 日韩av资源在线观看 | 久久精品最新 | 成人久久久久久久久久 | 午夜在线观看影院 | 欧美极度另类性三渗透 | 欧美日韩高清在线观看 | 黄色一级性片 | 免费在线观看av电影 | 操操操com | 蜜臀aⅴ精品一区二区三区 久久视屏网 | 91中文在线视频 | 国产在线国产 | 久久电影网站中文字幕 | 免费观看成人网 | 欧美少妇的秘密 | 久久不射网站 | 国产不卡在线看 | 91精品伦理| 中文字幕第| 久久不卡av| 成人久久久久久久久久 | 国产精品6999成人免费视频 | 999久久 | 又紧又大又爽精品一区二区 | 久久99热国产 | 欧美日韩精品在线 | 久久99久国产精品黄毛片入口 | 日韩精品一区二区免费视频 | 亚洲特级毛片 | 久久夜色精品国产欧美乱极品 | 欧美精品做受xxx性少妇 | 韩国三级av在线 | 91综合久久一区二区 | 日本资源中文字幕在线 | 国产又粗又猛又色又黄视频 | 亚洲精品伦理在线 | 国内精品久久久久影院优 | 99国产精品免费网站 | 成人免费视频网址 | www.888.av| 中文字幕在线观看免费高清完整版 | 麻豆视频国产 | 国产明星视频三级a三级点| 91热这里只有精品 | 国产麻豆果冻传媒在线观看 | 国产一区在线免费观看视频 | 国产在线观看一 | 最近免费中文字幕mv在线视频3 | 99精品亚洲 | 中文字幕av在线免费 | 在线观看一区视频 | 国产成人免费观看久久久 | 337p日本欧洲亚洲大胆裸体艺术 | 久久久久成人精品免费播放动漫 | 亚洲狠狠操 | 操操操人人人 | 国产精品免费久久久久久久久久中文 | 毛片美女网站 | 国产成人一区三区 | 精品999久久久 | 欧美一级片在线观看视频 | 国内精品久久久久久久97牛牛 | 国产精品理论在线观看 | 99精品国产99久久久久久97 | 天天干 天天摸 天天操 | 91高清不卡 | 综合久久精品 | 色婷婷www | 毛片美女网站 | av在线一级 | 精品亚洲一区二区三区 | 日本最新中文字幕 | 超碰97在线看 | 国产一区二区三区免费观看视频 | 99r精品视频在线观看 | 99精品在线看 | 91爱爱网址 | 成人影音在线 | 黄色小网站在线观看 | 韩国中文三级 | 国产伦精品一区二区三区四区视频 | 中文字幕乱码日本亚洲一区二区 | 国产欧美精品xxxx另类 | 天天爽夜夜爽人人爽曰av | 日韩在线视频不卡 | 国产毛片在线 | 91大神免费在线观看 | 国产精品av免费在线观看 | 激情在线网址 | 五月花丁香婷婷 | 亚洲人久久久 | 精品国产一区二区三区av性色 | 国产日产精品久久久久快鸭 | 欧美日韩精品国产 | 综合激情网... | 国产精品午夜久久久久久99热 | 中文字幕欧美日韩va免费视频 | 国产黄a三级 | 美女网站在线 | 超碰在线97国产 | 国产精品久久久久久久久久 | 91精品在线观看视频 | 日韩久久精品一区二区三区 | 国产视频一| 91精品亚洲影视在线观看 | 国产91免费在线观看 | 91成人短视频在线观看 | 香蕉视频免费在线播放 | 天天躁日日躁狠狠躁av麻豆 | 国产老太婆免费交性大片 | 国内精品久久天天躁人人爽 | 成人在线播放视频 | 天天操天天色综合 | 久久国产精品免费 | 激情在线免费视频 | 五月激情丁香图片 | 中文字幕免费国产精品 | 波多野结依在线观看 | 国产一二三精品 | 国产一区二区三区免费在线 | 国产一区二区网址 | 午夜精品999 | 天天天干夜夜夜操 | 国产精品久久久久久久久久久杏吧 | 免费福利在线视频 | 一区二区电影在线观看 | 欧美成人亚洲 | 狠狠躁夜夜躁人人爽视频 | 日韩欧美一区二区三区免费观看 | 国产精品不卡在线 | 97超视频| japanesexxx乱女另类 | 国产成人综合精品 | 国产高清网站 | www.久久成人 | 日本中文字幕久久 | 成人av影视在线 | 狠狠操综合网 | 国产成人黄色片 | 日韩在线电影 | 九九久久久久久久久激情 | 亚洲视频久久久 | 天天色综合天天 | 国产视频久 | 国产精品1区2区在线观看 | 黄色aaaaa| 成人午夜精品 | 精品麻豆| 天天干天天操天天拍 | 国产精品人人做人人爽人人添 | 三级黄在线| 成人国产电影在线观看 | 91人人澡人人爽人人精品 | 成人禁用看黄a在线 | 久久久国产精品一区二区三区 | 午夜精品久久久久久久99 | 在线视频 日韩 | 六月色| 在线a人片免费观看视频 | 国产第一页在线播放 | 亚洲黄色免费电影 | 久久久久免费网 | 狠狠的日 | 999久久久欧美日韩黑人 | 欧美欧美| 久久少妇 | 九九在线国产视频 | 五月天丁香亚洲 | 欧美日韩在线观看视频 | 国产毛片在线 | 91麻豆精品国产91久久久使用方法 | 婷婷激情五月 | 天天操操 | 福利区在线观看 | 亚洲精品久久久久久中文传媒 | 成人精品一区二区三区中文字幕 | 国产美女精品久久久 | 激情视频91 | 国产无遮挡又黄又爽在线观看 | 欧美男同视频网站 | 国产精品亚洲片在线播放 | 国产精品青草综合久久久久99 | 久久精品综合 | a黄色片| 制服丝袜在线91 | 久草视频免费 | 免费欧美 | 国产精品黄色影片导航在线观看 | 玖玖在线精品 | 成 人 黄 色 视频播放1 | 免费高清国产 | 99 久久久久 | 91丨九色丨国产女 | 贫乳av女优大全 | 午夜精品久久久久久久爽 | 国产不卡网站 | 黄色网大全 | 亚洲一区尤物 | 99久久精品无码一区二区毛片 | 一本一本久久a久久精品牛牛影视 | 麻豆精品在线视频 | 精品一区二区免费 | 91精品综合在线观看 | 成人一级电影在线观看 | 亚洲1级片 | 成人毛片久久 | 91精品国产91久久久久 | 99精品亚洲 | 日韩黄色一级电影 | 久久三级毛片 | 欧美二区视频 | 日韩欧美精品免费 | 国产精品mv在线观看 | 国产黄色片久久久 | 日韩高清一区 | 日韩在线理论 | 久久精品福利视频 | 免费成人在线电影 | 91麻豆网| 久久久久成 | 欧美成人精品三级在线观看播放 | av超碰在线观看 | 亚洲日本va午夜在线电影 | 国产精品视屏 | 中文字幕在线观看的网站 | 最近中文字幕国语免费高清6 | 久久超碰免费 | 婷婷伊人五月天 | 久久精品欧美一区 | 日韩精品一区二区三区免费视频观看 | 国产成人三级三级三级97 | 日韩aa视频 | 亚洲黄色在线免费观看 | 狠狠狠狠狠狠天天爱 | jizz18欧美18 | 最近中文字幕免费 | 在线韩国电影免费观影完整版 | 在线观看激情av | www.com.日本一级 | 中文字幕一区二区三区四区久久 | 国产大片免费久久 | 久久久久久久久艹 | 99热这里只有精品在线观看 | 久久久久成人精品 | 久久精品一二三区 | 草久在线观看 | 色国产精品一区在线观看 | 中文字幕免费一区 | 99r国产精品 | 99久久精品视频免费 | 亚洲另类交 | 亚洲黄色软件 | 国产精品一区久久久久 | 免费美女久久99 | 午夜精品婷婷 | 久久国产美女视频 | 国产精品成人av久久 | 草久久久 | 国产成人精品在线播放 | 精品日韩中文字幕 | 亚洲日日日 | 天天插天天干天天操 | 日本黄色大片儿 | 国产原创av在线 | 久久久久久久久毛片精品 | 国产精品久久久久久久7电影 | 日本中文字幕系列 | 色视频网站在线观看一=区 a视频免费在线观看 | 伊人五月天av | 又黄又爽又刺激的视频 | 精品一区在线 | av888.com| 亚洲少妇影院 | 99久久精品免费看国产四区 | 日韩欧美精品在线观看视频 | 国产美女久久久 | 国产成人亚洲在线电影 | 免费看片网站91 | 成 人 黄 色视频免费播放 | av在线电影免费观看 | 亚洲电影网站 | 一区二区三区在线观看免费 | 成人动漫一区二区 | 69国产盗摄一区二区三区五区 | 91毛片在线 | 久久这里只精品 | 久草视频中文在线 | 成人久久18免费网站麻豆 | 久久久久久久电影 | 久久精品一区二区三区中文字幕 | 国产精品videossex国产高清 | 狠狠久久伊人 | 久久艹在线观看 | 人人要人人澡人人爽人人dvd | 中文字幕 国产专区 | 久精品视频免费观看2 | 草久久影院 | 免费高清在线观看成人 | 成人国产精品久久久 | 高潮毛片无遮挡高清免费 | 色老板在线视频 | 欧美成人h版在线观看 | 欧美一区二区三区特黄 | 97色噜噜| 天天操天天谢 | 国产亚洲精品久久久久久大师 | 一区二区三区日韩在线观看 | 久久精品精品电影网 | 亚洲国产成人在线播放 | 三三级黄色片之日韩 | 国产精品黄色影片导航在线观看 | 九热在线 | 日日干网址 | 国内精品中文字幕 | 欧美日高清视频 | 91麻豆文化传媒在线观看 | 一区二区三区四区五区在线视频 | 久久婷综合 | 日韩中文字幕免费在线观看 | 久久久午夜精品理论片中文字幕 | 996久久国产精品线观看 | 国产精品久久久久国产精品日日 | 精品国产伦一区二区三区观看说明 | 日日爱网址 | 国产在线综合视频 | 五月天久久激情 | 亚洲成av人片一区二区梦乃 | 狠狠色丁香婷婷综合 | 日日操日日插 | 外国av网 | 中文字幕在线视频一区二区 | 色姑娘综合 | 亚洲va韩国va欧美va精四季 | 一区二区久久 | a视频免费在线观看 | 国产高清黄色 | 韩国av一区二区三区 | 日日爽视频| 免费视频色 | 97电影网站 | 天天摸夜夜操 | 久久er99热精品一区二区三区 | 黄色aa久久 | 新版资源中文在线观看 | 日韩性色 | 久久av网址 | 日韩av快播电影网 | 狠狠操狠狠干2017 | 激情 婷婷 | 97国产超碰| 欧洲在线免费视频 | 亚洲精品小视频在线观看 | 91看片在线免费观看 | 国产成人免费精品 | 久久国产品 | 婷婷色吧 | 久久久影院一区二区三区 | 亚洲午夜久久久影院 | av片一区| 日韩精品中文字幕在线播放 | 国产网站av | 深爱激情久久 | 国产一在线精品一区在线观看 | 色鬼综合网| 精品亚洲免费 | 国产九九热 | 九九免费在线观看视频 | 天天色天天操综合 | 亚洲成人精品 | 中文字幕亚洲欧美日韩 | 色小说av | 天天夜夜狠狠操 | 97在线观看免费视频 | 日韩一级成人av | 久草视频免费在线观看 | 69亚洲精品| 久久99精品国产一区二区三区 | 日韩91精品 | 中文在线免费看视频 | av一本久道久久波多野结衣 | 9幺看片| 国产爽妇网 | 国产成人福利在线 | 美女视频黄在线 | 曰本免费av | 免费看黄色小说的网站 | 成人在线观看资源 | 久久三级毛片 | 免费av网址大全 | av大片免费在线观看 | 亚洲国产成人高清精品 | 日韩精品一区在线观看 | 狠狠色噜噜狠狠狠狠 | 热久久免费视频精品 | 日批网站在线观看 | 国产中文字幕在线视频 | 免费在线激情电影 | 99情趣网视频 | 久久另类小说 | 国产成人黄色在线 | 亚洲三级黄色 | 免费三级影片 | 超碰在线国产 | 伊人日日干| 91 在线视频 | 久久黄色免费观看 | 国产精品麻豆视频 | 久久久精品国产免费观看同学 | 91污在线| 探花国产在线 | 973理论片235影院9 | 午夜精品福利一区二区 | 在线观看免费色 | 欧美专区国产专区 | 91福利视频久久久久 | 婷婷久久精品 | 色播五月婷婷 | 中文字幕在线视频免费播放 | 中文字幕在线观看第一区 | 国产91勾搭技师精品 | 久久中文欧美 | 日韩二区三区在线 | 黄a在线观看 | 日韩在线观看中文 | 天天爽天天碰狠狠添 | 8x成人在线 | 亚洲免费一级电影 | 四虎在线视频 | 国产色影院 | 久久在线免费观看视频 | 在线观看黄色av | 久久国产系列 | 色婷婷综合成人av | 亚洲精品乱码久久久久久高潮 | 欧美一区二区免费在线观看 | 欧美成人性战久久 | 久久成人黄色 | 亚洲精品中文在线观看 | 国产精品久久久久久久久大全 | 黄色亚洲精品 | 中文字幕在线一区二区三区 | 亚洲毛片一区二区三区 | 国产视频一二三 | 人人爽久久涩噜噜噜网站 | 国内精品久久久久久中文字幕 | 人人爱爱 | 可以免费看av | 99久久久久久 | 高清中文字幕 | 在线观看成人毛片 | 天天色天天爱天天射综合 | 成人网页在线免费观看 | 国产在线精品视频 | 国产精品精品国产 | 国内精品久久久久久久影视简单 | 免费亚洲婷婷 | 探花视频在线版播放免费观看 | 久久久久久久久久久综合 | av资源在线看| av免费片| 亚洲精品国产精品乱码不99热 | 国产视频一区二区在线观看 | 草莓视频在线观看免费观看 | 中文 一区二区 | 天堂成人在线 | 麻豆视频在线 | 天堂在线免费视频 | 久久免费在线视频 | 五月婷婷色综合 | 成人资源在线 | 免费av一级电影 | 国产视频97 | www.五月婷婷| 久草视频在线免费播放 | 婷婷六月天在线 | 97色免费视频 | www.综合网.com | 久久私人影院 | 久久天天躁夜夜躁狠狠躁2022 | 日韩欧美亚州 | 在线观看中文字幕网站 | 日韩视频 一区 | 99视频在线精品国自产拍免费观看 | 国产日产精品一区二区三区四区的观看方式 | 国产中文字幕视频在线观看 | 97av视频在线观看 | 久久久久久久久久电影 | 91精品国 | 欧美黄色软件 | 婷婷激情五月 | 精品在线视频一区二区三区 | 91久久久久久久 | 黄色av电影免费观看 | 亚洲国产精品免费 | 激情图片久久 | 色多多污污 | 国产黑丝袜在线 | 蜜桃视频在线观看一区 | 婷婷精品进入 | 国产日韩欧美视频在线观看 | 天天拍天天干 | 日本mv大片欧洲mv大片 | 中文字幕第一页在线vr | 亚洲一区网 | 天天综合网久久综合网 | 亚洲成人av在线 | 最近中文字幕免费 | 亚洲美女久久 | 黄色毛片在线观看 | 国产成人久久精品 | 日本在线精品视频 | 久久国产免费视频 | 国产精品免费久久久久久 | 一级片在线 | 国产中文字幕在线观看 | 国语麻豆 | 91成人在线视频 | 亚洲国产成人精品在线观看 | 人人草人 | 在线av资源 | 国产一区二区三区高清播放 | 国产1区2区3区精品美女 | 视频 天天草 | 麻豆91精品91久久久 | 日本在线观看视频一区 | 国产91在线免费视频 | 日韩成人高清在线 | 天天操福利视频 | www.成人久久| 亚洲成人免费观看 | 欧美日韩精品二区第二页 | 中文字幕在线高清 | 国产 欧美 日本 | 97超碰人人澡 | 全黄网站 | 日韩在线免费高清视频 | 视频在线一区 | 亚洲成人免费 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 久久综合操| 国产精品中文久久久久久久 | 狠狠狠操 | 婷婷激情5月天 | 国产亚洲精品成人av久久影院 | 在线看日韩 | 99这里只有久久精品视频 | 99产精品成人啪免费网站 | 色片网站在线观看 | 五月天中文字幕mv在线 | 欧美乱码精品一区 | 99久久久成人国产精品 | 九九精品视频在线观看 | 成人性生交大片免费看中文网站 | 美女黄色网在线播放 | 久久久久久网址 | 成人亚洲免费 | 免费视频在线观看网站 | 99国产精品久久久久老师 | 四虎影视精品成人 | 中文字幕丝袜 | 黄色com| 色窝资源 | 久久久久国产精品免费免费搜索 | 久久国产高清视频 | 97精品国产97久久久久久免费 | 人人干狠狠干 | 欧美资源在线观看 | 最新黄色av网址 | 香蕉久久久久久av成人 | 五月天色中色 | 国产福利在线 | 青青网视频 | 精品视频免费看 | 2021av在线 | 精品福利在线视频 | 久久精品成人欧美大片古装 | 一区二区三区国产欧美 | 在线免费成人 | 99精品久久久久久久 | 久久国内精品99久久6app | 99精品视频免费观看 | av免费线看 | 国精产品999国精产品视频 | 91黄站| 国产正在播放 | 婷婷久久国产 | 天天天天天天天天操 | 日韩精品一区二区在线 | 五月婷婷激情六月 | 特级a老妇做爰全过程 | 四虎成人精品 | 中文字幕高清免费日韩视频在线 | 福利视频一二区 | 麻豆视频免费看 | 精品国产伦一区二区三区观看体验 | 天天操天天干天天玩 | 美女精品 | 日本精品久久久久中文字幕5 | 天堂入口网站 | 特级毛片在线免费观看 | 美女久久 | 色婷婷av一区二 | 国产在线播放一区二区 | 日韩精品一区二区免费视频 | 欧美日韩国产亚洲乱码字幕 | www.福利 | 国产精品婷婷午夜在线观看 | 91桃色在线免费观看 | 五月香视频在线观看 | 韩国一区二区三区在线观看 | 超碰国产在线观看 | 久久精品79国产精品 | 国产精品免费久久久久久 | 日韩精品免费在线视频 | 日韩精品一区二区免费视频 | 免费看的av片 | 久久精品视频日本 | 午夜成人影视 | 国产系列在线观看 | 日韩欧美国产免费播放 | 国产综合激情 | 色综合狠狠干 | 国产亚洲精品中文字幕 | 国产精品久久久电影 | 久久精品激情 | 97成人超碰 | 91精品久久久久久 | 日韩欧美在线观看一区二区 | 欧美日韩国产综合网 | 六月婷婷网 | 在线日本看片免费人成视久网 | 久久综合精品一区 | www麻豆视频 | 色婷婷欧美 | 成人亚洲网 | 国产小视频精品 | 91精品一区二区在线观看 | 国产亚洲一区二区在线观看 | 午夜精品婷婷 | 久久免费看视频 | 免费观看9x视频网站在线观看 | 国产一区二区成人 | 丁香婷婷社区 | 五月婷婷丁香网 | 精品在线小视频 | 国产精品久久久久久久久免费 | 一区 二区电影免费在线观看 | www.色午夜,com| 天天躁日日躁狠狠躁av中文 | 久久久久免费 | 国产成人一区二区三区电影 | 成人免费视频免费观看 | 麻豆首页 | 高清日韩一区二区 | 国内99视频 | 91在线观看视频网站 | 免费a一级 | 麻豆视频国产 | 久久精品国产免费观看 | 中文字幕一区二区三区在线播放 | 国产人在线成免费视频 | 成年人毛片在线观看 | 青春草免费在线视频 | 日韩大片在线看 | 国产伦理久久精品久久久久_ | 国产在线a视频 | 久久久久综合视频 | 欧美色精品天天在线观看视频 | 亚洲视频一 | 国产精品 9999 | 日本在线中文 | 久久久精品电影 | 最近中文字幕在线播放 | 欧美日韩免费观看一区=区三区 | 99精品视频在线播放观看 | 亚洲码国产日韩欧美高潮在线播放 | 国产精品视频99 | 久久手机精品视频 | 日韩精品一区二区在线观看视频 | 香蕉在线观看视频 | 91秒拍国产福利一区 | 在线高清 | 国产永久免费观看 | 国产亚洲免费观看 | 中文字幕人成乱码在线观看 | 国产欧美精品xxxx另类 | 玖玖在线资源 | 久久久麻豆视频 | av中文字幕在线播放 | 99夜色 | zzijzzij日本成熟少妇 | 日韩高清在线不卡 | 午夜影视一区 | 91av在线视频免费观看 | 久久精品五月 | 亚洲 欧洲av | 精品久久1 | 天天射天天操天天 | 亚洲国产精品激情在线观看 | 日日操天天操狠狠操 | 日韩欧美在线一区二区 | 国产一级一片免费播放放 | 国产亚洲在线 | 91视频3p | 香蕉视频91 | 中文在线a∨在线 | 久久观看最新视频 | 久草视频视频在线播放 | 免费a级大片 | 超级碰碰视频 | 精品国产一区二区三区久久影院 | 91看片在线播放 | 中文字幕人成乱码在线观看 | 久久视频这里只有精品 | 黄色在线观看免费网站 | 国产精品手机视频 | 欧美性做爰猛烈叫床潮 | 欧美日韩国产伦理 | www色片 | 一级片视频免费观看 | 国产一级二级av | 中文成人字幕 | 91精品国产综合久久福利 | 日韩激情一二三区 | 欧美国产一区在线 | 精品国产一区二区三区四区在线观看 | 久久久久亚洲精品国产 | 日日夜av| 97人人模人人爽人人少妇 | 久久久免费精品视频 | 欧美色操 | 久久人人艹 | 久草在线免费新视频 | 久久久久久久久久电影 | 91精品在线播放 | 成人av在线直播 | 99精品视频在线观看播放 | 91视频 - v11av | 国产精品一区二区在线 | 亚洲欧美日韩精品一区二区 | 午夜婷婷在线播放 | zzijzzij日本成熟少妇 | 成人久久久久久久久 | 国产福利91精品 | 91看片黄色 | 中文字幕免费高清av | 精品一区二区在线免费观看 | av网站免费在线 | 久久久久久蜜桃一区二区 | 激情五月在线视频 | 日韩一二区在线 | 99精品国产一区二区三区麻豆 | 日本久久中文字幕 | 国产美女精品人人做人人爽 | 中文字幕亚洲在线观看 | www黄在线 | 欧美日韩国产免费视频 | 天天操操 | 国产女教师精品久久av | 日韩免费播放 | 国产露脸91国语对白 | 国产精品视频99 | www.超碰97.com| 日本黄色免费大片 | 四虎永久免费 | 美女网站在线观看 | 日批网站免费观看 | 亚洲视频综合在线 | 亚洲免费在线看 | 日韩欧美高清在线 | 国产精品成人国产乱一区 | 人人爱人人做人人爽 | 日韩成人xxxx | 97色在线视频 | 亚洲国产午夜精品 | 五月婷婷影视 | 国产午夜不卡 | 精品国产综合区久久久久久 | 91成人网页版 | 久草视频免费在线观看 | 国产精品久久久久久爽爽爽 | 日本精品在线视频 | 国产视频亚洲精品 | 91精品视频免费观看 | 免费看黄在线 | 丝袜av网站 | 欧亚久久 | 91丨九色丨高潮 | 久久久久久久久久久电影 | 国产成人免费 | 久久91网| 在线成人小视频 | 亚洲va男人天堂 | 国产一二三在线视频 | 日韩欧美网址 | 国产精品99久久久久久小说 | av亚洲产国偷v产偷v自拍小说 | 九九视频网 | 欧美久久九九 | 欧美一二三区在线播放 | 日韩福利在线观看 | 亚洲涩涩涩涩涩涩 | 国产色女 | 欧美一级免费片 | 24小时日本在线www免费的 | 国产中文字幕亚洲 | 五月激情姐姐 | 久久在线观看视频 | 91av视频免费在线观看 | 在线观看一区二区精品 | 色婷婷免费视频 | 99热最新| 在线国产一区二区三区 | 久久97视频| 天天干天天干天天干天天干天天干天天干 | 国产福利精品在线观看 | 91看片淫黄大片一级在线观看 | 亚洲高清91| 97人人人人 | 国产精品综合在线观看 | 久久另类小说 | 在线视频 日韩 | 2019中文在线观看 | 国产精品一区二区62 | 白丝av免费观看 | 中文资源在线观看 | av免费黄色| 久久综合五月天婷婷伊人 | 在线观看免费高清视频大全追剧 | 毛片1000部免费看 | 免费在线观看视频a | 天天天天射 | 日日夜夜91 | 国产九色视频在线观看 | 国产一级电影在线 | 国产一区视频在线观看免费 | 国产在线一区二区三区播放 | 又黄又网站 | av经典在线| 天天夜操 | 欧美一级性生活 | 亚洲干视频在线观看 | 国产黄大片在线观看 | 在线免费高清 | 一区在线观看视频 | 人人爽人人乐 | 91精品视频导航 | 中国黄色一级大片 | 日韩精品视频免费看 | 国产中文字幕在线 | 久久影视精品 | 夜夜夜精品| 日韩在线免费不卡 | 国产va饥渴难耐女保洁员在线观看 | 久精品视频| 黄网在线免费观看 | 久久亚洲影院 | 国产最新在线观看 | 欧美a级在线 | 久久精品日产第一区二区三区乱码 | 欧美激情视频在线观看免费 | 国产色女 | 国产网站在线免费观看 | 狠狠操操网 | 中文字幕色在线视频 | 日本韩国精品一区二区在线观看 | 97电影在线 | 九七人人干 | 中文字幕高清在线 | 免费男女羞羞的视频网站中文字幕 | 欧美日韩一区二区三区免费视频 | 亚洲免费av网站 | 在线免费中文字幕 | 国产操在线| 91伊人影院 | 在线观看视频你懂 | 国产麻豆精品久久 | 精品国产一区二区三区久久久 | 亚洲精品xxx | 超碰精品在线观看 | 天堂网中文在线 | 国产精品成人av电影 | 婷婷丁香综合 | 久久久91精品国产一区二区三区 |