精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Spring 聲明式事務應該怎么學?

開發 架構
Spring 的聲明式事務極大地方便了日常的事務相關代碼編寫,它的設計如此巧妙,以至于在使用中幾乎感覺不到它的存在,只需要優雅地加一個 @Transactional 注解,一切就都順理成章地完成了!

[[422057]]

本文轉載自微信公眾號「Java課代表」,作者Java課代表。轉載本文請聯系Java課代表公眾號。

1、引言

Spring 的聲明式事務極大地方便了日常的事務相關代碼編寫,它的設計如此巧妙,以至于在使用中幾乎感覺不到它的存在,只需要優雅地加一個 @Transactional 注解,一切就都順理成章地完成了!

毫不夸張地講,Spring 的聲明式事務實在是太好用了,以至于大多數人都忘記了編程式事務應該怎么寫。

不過,越是你認為理所應當的事情,如果出了問題,就越難排查。不知道你和身邊的小伙伴有沒有遇到過 @Transactional 失效的場景,這不但是日常開發中常踩的坑,也是面試中的高頻問題。

其實這些失效場景不用死記硬背,如果搞明白了它的工作原理,再結合源碼,需要用到的時候 Debug 一下就能自己分析出來。畢竟,源碼才是最好的說明書。

還是那句話,授人以魚不如授人以漁,課代表就算總結 100 種失效場景,也不一定能覆蓋到你可能踩到的坑。所以本文中,課代表將結合幾個常見失效情況,從源碼層面解釋其失效原因。認真讀完本文,相信你會對聲明式事務有更深刻的認識。

文中所有代碼已上傳至課代表的 github,為了方便快速部署并運行,示例代碼采用了內存數據庫H2,不需要額外部署數據庫環境。

2、回顧手寫事務

數據庫層面的事務,有 ACID 四個特性,他們共同保證了數據庫中數據的準確性。事務的原理并不是本文的重點,我們只需要知道樣例中用的 H2 數據庫完全實現了對事務的支持(read committed)。

編寫 Java 代碼時,我們使用 JDBC 接口與數據庫交互,完成事務的相關指令,偽代碼如下:

  1. //獲取用于和數據庫交互的連接 
  2. Connection conn = DriverManager.getConnection(); 
  3. try { 
  4.     // 關閉自動提交: 
  5.     conn.setAutoCommit(false); 
  6.     // 執行多條SQL語句: 
  7.     insert();  
  8.     update();  
  9.     delete(); 
  10.     // 提交事務: 
  11.     conn.commit(); 
  12. } catch (SQLException e) { 
  13.     // 如果出現異常,回滾事務: 
  14.     conn.rollback(); 
  15. } finally { 
  16.     //釋放資源 
  17.     conn.close(); 

這是典型的編程式事務代碼流程:開始前先關閉自動提交,因為默認情況下,自動提交是開啟的,每條語句都會開啟新事務,執行完畢后自動提交。

關閉事務的自動提交,是為了讓多個 SQL 語句在同一個事務中。代碼正常運行,就提交事務,出現異常,就整體回滾,以此保證多條 SQL 語句的整體性。

除了事務提交,數據庫還支持保存點的概念,在一個物理事務中,可以設置多個保存點,方便回滾到指定保存點(其類似玩單機游戲時的存檔,你可以在角色掛掉后隨時回到上次的存檔)設置和回滾到保存點的代碼如下:

  1. //設置保存點     
  2. Savepoint savepoint = connection.setSavepoint(); 
  3. //回滾到指定的保存點 
  4. connection.rollback(savepoint); 
  5. //回滾到保存點后按需提交/回滾前面的事務 
  6. conn.commit();//conn.rollback(); 

Spring 聲明式事務所做的工作,就是圍繞著 提交/回滾 事務,設置/回滾到保存點 這兩對命令進行的。為了讓我們盡可能地少寫代碼,Spring 定義了幾種傳播屬性將事務做了進一步的抽象。注意哦,Spring 的事務傳播(Propagation) 只是 Spring 定義的一層抽象而已,和數據庫沒啥關系,不要和數據庫的事務隔離級別混淆。

3、Spring 的事務傳播(Transaction Propagation)

觀察傳統事務代碼:

  1. conn.setAutoCommit(false); 
  2.    // 執行多條SQL語句: 
  3.    insert();  
  4.    update();  
  5.    delete(); 
  6.    // 提交事務: 
  7.    conn.commit(); 

這段代碼表達的是三個 SQL 語句在同一個事務里。

他們可能是同一個類中的不同方法,也可能是不同類中的不同方法。如何來表達諸如事務方法加入別的事務、新建自己的事務、嵌套事務等等概念呢?這就要靠 Spring 的事務傳播機制了。

事務傳播(Transaction Propagation)就是字面意思:事務的傳播/傳遞 方式。

在 Spring 源碼的TransactionDefinition接口中,定義了 7 種傳播屬性,官網對其中的 3 個做了說明,我們只要搞懂了這 3 個,剩下的 4 個就是舉一反三的事了。

1)PROPAGATION_REQUIRED

字面意思:傳播-必須

PROPAGATION_REQUIRED是其默認傳播屬性,強制開啟事務,如果之前的方法已經開啟了事務,則加入前一個事務,二者在物理上屬于同一個事務。

一圖勝千言,下圖表示它倆物理上是在同一個事務內:

上圖翻譯成偽代碼是這樣的:

  1. try { 
  2.     conn.setAutoCommit(false); 
  3.     transactionalMethod1();  
  4.     transactionalMethod2(); 
  5.     conn.commit(); 
  6. } catch (SQLException e) { 
  7.     conn.rollback(); 
  8. } finally { 
  9.     conn.close(); 

既然在同一個物理事務中,那如果transactionalMethod2()發生了異常,導致需要回滾,那么請問transactionalMethod1()是否也要回滾呢?

得益于上面的圖解和偽代碼,我們可以很容易地得出答案,transactionalMethod1()肯定回滾了。

這里拋一個問題:

事務方法里面的異常被 try catch 吃了,事務還能回滾嗎?

先別著急出結論, 看下面兩段代碼示例。

示例一:不會回滾的情況(事務失效)

觀察下面的代碼,methodThrowsException()什么也沒干,就拋了個異常,調用方將其拋出的異常try catch 住了,該場景下是不會觸發回滾的

  1. @Transactional(rollbackFor = Exception.class) 
  2. public void tryCatchRollBackFail(String name) { 
  3.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  4.     try { 
  5.         methodThrowsException(); 
  6.     } catch (RollBackException e) { 
  7.         //do nothing 
  8.     } 
  9.  
  10. public void methodThrowsException() throws RollBackException { 
  11.     throw new RollBackException(ROLL_BACK_MESSAGE); 

示例二:會回滾的情況(事務生效)

再看這個例子,同樣是 try catch 了異常,結果卻截然相反

  1. @Transactional(rollbackFor = Throwable.class) 
  2. public void tryCatchRollBackSuccess(String name, String anotherName) { 
  3.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  4.     try { 
  5.         // 帶事務,拋異常回滾 
  6.         userService.insertWithTxThrowException(anotherName); 
  7.     } catch (RollBackException e) { 
  8.         // do nothing 
  9.     } 
  10.  
  11. @Transactional(rollbackFor = Throwable.class) 
  12. public void insertWithTxThrowException(String name) throws RollBackException { 
  13.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  14.     throw new RollBackException(ROLL_BACK_MESSAGE); 

本例中,兩個方法的事務都沒有設置propagation屬性,默認都是PROPAGATION_REQUIRED。即前者開啟事務,后者加入前面開啟的事務,二者同屬于一個物理事務。insertWithTxThrowException()方法拋出異常,將事務標記為回滾。既然大家是在一條船上,那么后者打翻了船,前者肯定也不能幸免。

所以tryCatchRollBackSuccess()所執行的SQL也必將回滾,執行此用例可以查看結果

訪問 http://localhost:8080/h2-console/ ,連接信息如下:

點擊Connect進入控制臺即可查看表中數據:

USER 表確實沒有插入數據,證明了我們的結論,并且可以看到日志報錯:

Transaction rolled back because it has been marked as rollback-only事務已經回滾,因為它被標記為必須回滾。

也就是后面方法觸發的事務回滾,讓前面方法的插入也回滾了。

看到這里,你應該能把默認的傳播類型PROPAGATION_REQUIRED理解透徹了,本例中是因兩個方法在同一個物理事務下,相互影響從而回滾。

你可能會問,那我如果想讓前后兩個開啟了事務的方法互不影響該怎么辦呢?

這就要用到下面要說的傳播類型了。

2)、PROPAGATION_REQUIRES_NEW

字面意思:傳播- 必須-新的

PROPAGATION_REQUIRES_NEW與PROPAGATION_REQUIRED不同的是,其總是開啟獨立的事務,不會參與到已存在的事務中,這就保證了兩個事務的狀態相互獨立,互不影響,不會因為一方的回滾而干擾到另一方。

一圖勝千言,下圖表示他倆物理上不在同一個事務內:

上圖翻譯成偽代碼是這樣的:

  1. //Transaction1 
  2. try { 
  3.     conn.setAutoCommit(false); 
  4.     transactionalMethod1();  
  5.     conn.commit(); 
  6. } catch (SQLException e) { 
  7.     conn.rollback(); 
  8. } finally { 
  9.     conn.close(); 
  10. //Transaction2 
  11. try { 
  12.     conn.setAutoCommit(false);  
  13.     transactionalMethod2(); 
  14.     conn.commit(); 
  15. } catch (SQLException e) { 
  16.     conn.rollback(); 
  17. } finally { 
  18.     conn.close(); 

TransactionalMethod1 開啟新事務,當他調用同樣需要事務的TransactionalMethod2時,由于后者的傳播屬性設置了PROPAGATION_REQUIRES_NEW,所以掛起前面的事務(至于如何掛起,后面我們會從源碼中窺見),并開啟一個物理上獨立于前者的新事務,這樣二者的事務回滾就不會相互干擾了。

還是前面的例子,只需要把insertWithTxThrowException()方法的事務傳播屬性設置為Propagation.REQUIRES_NEW就可以互不影響了:

  1. @Transactional(rollbackFor = Throwable.class) 
  2. public void tryCatchRollBackSuccess(String name, String anotherName) { 
  3.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  4.     try { 
  5.         // 帶事務,拋異常回滾 
  6.         userService.insertWithTxThrowException(anotherName); 
  7.     } catch (RollBackException e) { 
  8.         // do nothing 
  9.     } 
  10.  
  11. @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW) 
  12. public void insertWithTxThrowException(String name) throws RollBackException { 
  13.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  14.     throw new RollBackException(ROLL_BACK_MESSAGE); 

PROPAGATION_REQUIRED和Propagation.REQUIRES_NEW已經足以應對大部分應用場景了,這也是開發中常用的事務傳播類型。前者要求基于同一個物理事務,要回滾一起回滾,后者是大家使用獨立事務互不干涉。還有一個場景就是:外部方法和內部方法共享一個事務,但是內部事務的回滾不影響外部事務,外部事務的回滾可以影響內部事務。這就是嵌套這種傳播類型的使用場景。

3)、PROPAGATION_NESTED

字面意思:傳播-嵌套

PROPAGATION_NESTED可以在一個已存在的物理事務上設置多個供回滾使用的保存點。這種部分回滾可以讓內部事務在其自己的作用域內回滾,與此同時,外部事務可以在某些操作回滾后繼續執行。其底層實現就是數據庫的savepoint。

這種傳播機制比前面兩種都要靈活,看下面的代碼:

  1. @Transactional(rollbackFor = Throwable.class) 
  2. public void invokeNestedTx(String name,String otherName) { 
  3.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  4.     try { 
  5.         userService.insertWithTxNested(otherName); 
  6.     } catch (RollBackException e) { 
  7.         // do nothing 
  8.     } 
  9.     // 如果這里拋出異常,將導致兩個方法都回滾 
  10.     // throw new RollBackException(ROLL_BACK_MESSAGE); 
  11.  
  12. @Transactional(rollbackFor = Throwable.class,propagation = Propagation.NESTED) 
  13. public void insertWithTxNested(String name) throws RollBackException { 
  14.     jdbcTemplate.execute("INSERT INTO USER (NAME) VALUES ('" + name + "')"); 
  15.     throw new RollBackException(ROLL_BACK_MESSAGE); 

外部事務方法invokeNestedTx()開啟事務,內部事務方法insertWithTxNested標記為嵌套事務,內部事務的回滾通過保存點完成,不會影響外部事務。而外部方法的回滾,則會連帶內部方法一塊回滾。

小結:本小節介紹了 3 種常見的Spring 聲明式事務傳播屬性,結合樣例代碼,相信你也對其有所了解了,接下來我們從源碼層面看一看,Spring 是如何幫我們簡化事務樣板代碼,解放生產力的。

4、源碼窺探

在閱讀源碼前,先分析一個問題:我要給一個方法添加事務,需要做哪些工作呢?

就算我們自己手寫,也至少得需要這么四步:

  • 開啟事務
  • 執行方法
  • 遇到異常就回滾事務
  • 正常執行后提交事務

這不就是典型的AOP嘛~

沒錯,Spring 就是通過 AOP,將我們的事務方法增強,從而完成了事務的相關操作。下面給出幾個關鍵類及其關鍵方法的源碼走讀。

既然是 AOP 那肯定要給事務寫一個切面來做這個事,這個類就是 TransactionAspectSupport,從命名可以看出,這就是“事務切面支持類”,他的主要工作就是實現事務的執行流程,其主要實現方法為invokeWithinTransaction:

  1. protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, 
  2.       final InvocationCallback invocation) throws Throwable { 
  3.      
  4.  // 省略代碼... 
  5.     // Standard transaction demarcation with getTransaction and commit/rollback calls. 
  6.  // 1、開啟事務 
  7.     TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); 
  8.     try { 
  9.   // This is an around advice: Invoke the next interceptor in the chain. 
  10.   // This will normally result in a target object being invoked. 
  11.   //2、執行方法 
  12.   retVal = invocation.proceedWithInvocation(); 
  13.  } 
  14.  catch (Throwable ex) { 
  15.   // target invocation exception 
  16.   // 3、捕獲異常時的處理 
  17.   completeTransactionAfterThrowing(txInfo, ex); 
  18.   throw ex; 
  19.  } 
  20.  finally { 
  21.   cleanupTransactionInfo(txInfo); 
  22.  } 
  23.  
  24.  if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) { 
  25.   // Set rollback-only in case of Vavr failure matching our rollback rules... 
  26.   TransactionStatus status = txInfo.getTransactionStatus(); 
  27.   if (status != null && txAttr != null) { 
  28.    retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status); 
  29.   } 
  30.  } 
  31.  //4、執行成功,提交事務 
  32.  commitTransactionAfterReturning(txInfo); 
  33.  return retVal; 
  34.  // 省略代碼... 

結合課代表增加的這四步注釋,相信你很容易就能看明白。

搞懂了事務的主要流程,它的傳播機制又是怎么實現的呢?這就要看AbstractPlatformTransactionManager這個類了,從命名就能看出, 它負責事務管理,其中的handleExistingTransaction方法實現了事務傳播邏輯,這里挑PROPAGATION_REQUIRES_NEW的實現跟一下代碼:

  1. protected Object doSuspend(Object transaction) { 
  2.   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction
  3.   txObject.setConnectionHolder(null); 
  4.   return TransactionSynchronizationManager.unbindResource(obtainDataSource()); 
  5.  } 

前文我們知道PROPAGATION_REQUIRES_NEW會將前一個事務掛起,并開啟獨立的新事務,而數據庫是不支持事務的掛起的,Spring 是如何實現這一特性的呢?

通過源碼可以看到,這里調用了返回值為SuspendedResourcesHolder的suspend(transaction)方法,它的實際邏輯由其內部的doSuspend(transaction)抽象方法實現。這里我們使用的是JDBC連接數據庫,自然要選擇DataSourceTransactionManager這個子類去查看其實現,代碼如下:

  1. protected Object doSuspend(Object transaction) { 
  2.   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction
  3.   txObject.setConnectionHolder(null); 
  4.   return TransactionSynchronizationManager.unbindResource(obtainDataSource()); 
  5.  } 

這里是把已有事務的connection解除,并返回被掛起的資源。在接下來開啟事務時,會將該掛起資源一并傳入,這樣當內層事務執行完成后,可以繼續執行外層被掛起的事務。

那么,什么時候來繼續執行被掛起的事務呢?

事務的流程,雖然是由TransactionAspectSupport實現的,但是真正的提交,回滾,是由AbstractPlatformTransactionManager來完成,在其processCommit(DefaultTransactionStatus status)方法最后的finally塊中,執行了cleanupAfterCompletion(status):

  1. private void cleanupAfterCompletion(DefaultTransactionStatus status) { 
  2.   status.setCompleted(); 
  3.   if (status.isNewSynchronization()) { 
  4.    TransactionSynchronizationManager.clear(); 
  5.   } 
  6.   if (status.isNewTransaction()) { 
  7.    doCleanupAfterCompletion(status.getTransaction()); 
  8.   } 
  9.    // 有掛起事務則獲取掛起的資源,繼續執行 
  10.   if (status.getSuspendedResources() != null) { 
  11.    if (status.isDebug()) { 
  12.     logger.debug("Resuming suspended transaction after completion of inner transaction"); 
  13.    } 
  14.    Object transaction = (status.hasTransaction() ? status.getTransaction() : null); 
  15.             
  16.    resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources()); 
  17.   } 
  18.  } 

這里判斷有掛起的資源將會恢復執行,至此完成掛起和恢復事務的邏輯。

對于其他事務傳播屬性的實現,感興趣的同學使用課代表的樣例工程,打斷點自己去跟一下源碼。限于篇幅,這里只給出了大概處理流程,源碼里有大量細節,需要同學們自己去體驗,有了上文介紹的主邏輯框架基礎,跟蹤源碼查看其他實現應該不怎么費勁了。

5、常見失效場景

很多人(包括課代表本人)一開始使用聲明式事務,都會覺得這玩意兒真坑,使用起來那么多條條框框,一不小心就不生效了。為什么會有這種感覺呢?

爬了多次坑之后,課代表總結了兩條經驗:

  1. 沒看官方文檔
  2. 不會讀源碼

下面簡單列舉幾個失效場景:

1)非 public 方法不生效

官網有說明:

Method visibility and @Transactional

When you use transactional proxies with Spring’s standard configuration, you should apply the @Transactional annotation only to methods with public visibility.

2)Spring 不支持 redis 集群中的事務

redis事務開啟命令是multi,但是 Spring Data Redis 不支持 redis 集群中的 multi 命令,如果使用了聲明式事務,將會報錯:MULTI is currently not supported in cluster mode.

3)多數據源情況下需要為每個數據源配置TransactionManager,并指定transactionManager參數

第四部分源碼窺探中已經看到實際執行事務操作的是AbstractPlatformTransactionManager,其為TransactionManager的實現類,每個事務的connection連接都受其管理,如果沒有配置,無法完成事務操作。單數據源的情況下正常運行,是因為 SpringBoot 的DataSourceTransactionManagerAutoConfiguration為我們自動配置了。

4)rollbackFor 設置錯誤

默認情況下只回滾非受檢異常(也就是,java.lang.RuntimeException的子類)和java.lang.Error,如果明確知道拋異常就要回滾,建議設置為@Transactional(rollbackFor = Throwable.class)

5)AOP不生效問題

其他諸如 MyISAM 不支持,es 不支持等等就不一一列舉了。

如果感興趣,以上這些在源碼中都能找到解答。

6、結束語

關于 Spring 的聲明式事務,如果想用好,還真得多 Debug 幾遍源碼,由于 Spring 的源碼細節過于豐富,實在不適合全部貼到文章里,建議自己去跟一下源碼。熟悉之后就不怕再遇到失效情況了。

以下資料證明我不是在胡扯

1、文中測試用例代碼:https://github.com/zhengxl5566/springboot-demo/tree/master/transactional

2、Spring 官網事務文檔:https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#tx-propagation

3、Oracle官網JDBC文檔:https://docs.oracle.com/javase/tutorial/jdbc/basics/index.html

 

4、Spring Data Redis 源碼:https://github.com/spring-projects/spring-data-redis

 

責任編輯:武曉燕 來源: Java課代表
相關推薦

2009-06-22 09:01:57

Spring聲明式事務

2024-11-13 19:03:14

2009-02-11 13:08:29

事務提交事務管理Spring

2009-02-11 11:14:31

事務管理事務開始Spring

2009-06-22 11:01:12

2021-04-15 08:01:27

Spring聲明式事務

2025-01-16 08:45:48

2011-11-23 16:28:07

JavaSpring框架

2023-04-28 08:21:36

SpringBoot聲明式事務編程式事務

2021-03-03 14:09:57

API命令式聲明式

2020-12-17 07:59:46

聲明式代碼命令式代碼代碼

2022-06-21 08:12:17

K8sAPI對象Kubernetes

2009-06-17 14:57:11

Spring事務管理

2022-07-05 14:19:30

Spring接口CGLIB

2009-06-08 17:56:00

SpringJDBC事務

2009-06-29 17:54:47

Spring事務隔離

2023-05-26 07:19:49

Spring聲明式事務

2021-01-29 11:47:35

人工智能智能科學專業

2022-12-26 08:34:58

SpringHttp

2011-01-27 10:11:46

J2EEjavaspring
點贊
收藏

51CTO技術棧公眾號

久久久久久av无码免费网站下载| 成人久久久久久| 美女扒开腿免费视频| 成av人片在线观看www| 91在线高清观看| 国产精品网红直播| 久久久无码一区二区三区| 色天下一区二区三区| 欧美日韩国产一级二级| www.成年人视频| 成人在线二区| 丁香亚洲综合激情啪啪综合| 国产精品视频精品视频| 国产无套内射又大又猛又粗又爽| 精品国产一区二区三区噜噜噜 | 久久久久久久久久成人| 欧美高清不卡| 黄色成人一级片| 日本中文在线一区| 91精品国产777在线观看| 99久久久无码国产精品不卡| 亚洲成在人线免费观看| 精品免费日韩av| 亚洲综合婷婷久久| 欧美二三四区| 精品国产电影一区| 日韩视频一二三| 一级毛片视频在线| 久久久久久一级片| 精品中文字幕人| www.天堂在线| 精品一二线国产| 国产精品久久久久久久久久免费 | 欧美一级高清片| 在线观看免费的av| 户外露出一区二区三区| 精品日韩中文字幕| 久久国产精品网| 污视频在线免费观看网站| 国产精品久久久久一区二区三区共 | 男女猛烈激情xx00免费视频| gogo在线高清视频| 中文字幕在线观看不卡| 色婷婷精品国产一区二区三区| 亚洲av成人精品毛片| www.色精品| 成人免费在线看片| 国产三级精品在线观看| 精品中文字幕一区二区小辣椒| 国产精品女主播| 精品国产www| 奇米888四色在线精品| 国产精品电影网站| 亚洲精品一区二三区| 日本vs亚洲vs韩国一区三区二区 | 国产亚洲欧美日韩日本| 美日韩免费视频| 日本在线丨区| 久久久久久99精品| 日本中文不卡| 免费在线观看黄色| 亚洲激情成人在线| 久久av综合网| 丝袜诱惑一区二区| 亚洲第一色网站| 欧美国产一区二区三区激情无套| 一区二区av在线| 久久久视频6r| 欧美xxxxx视频| 久久亚洲影音av资源网| 黄页网站免费观看| 日韩午夜免费视频| 国产精品1区2区在线观看| 中文字幕你懂的| 精品一区二区三区免费毛片爱| 亚洲字幕在线观看| 无码国产精品一区二区免费16| 99精品国产91久久久久久| 欧美日韩国产精品一卡| a黄色在线观看| 日韩理论片在线| cao在线观看| 三上悠亚激情av一区二区三区| 欧美午夜宅男影院| 亚洲熟妇一区二区| 色老板在线视频一区二区| 色悠悠久久88| 国产午夜精品无码| 日本不卡123| aa成人免费视频| 免费动漫网站在线观看| 中文字幕一区二区在线播放| 成人在线免费观看视频网站| 在线女人免费视频| 欧美疯狂性受xxxxx喷水图片| 精品国产乱码久久久久夜深人妻| 国产精品嫩模av在线| 欧美xxxx做受欧美.88| 国产一级做a爱片久久毛片a| 久久国产精品无码网站| 九色91在线视频| 国产剧情在线| 色婷婷国产精品久久包臀| 国产一区二区在线观看免费视频| 牛牛影视久久网| 超碰91人人草人人干| 日韩视频在线观看一区| 国产一区在线看| 日本成人三级| 国产网红女主播精品视频| 欧美视频精品在线| 波多野结衣有码| 一区二区三区在线| 国产精品久久久| 三区在线视频| 亚洲国产精品久久久久秋霞影院| 一级黄色特级片| 午夜精品福利影院| 欧美激情视频网址| 136福利视频导航| 国产午夜三级一区二区三| 欧美中日韩在线| 亚洲我射av| 在线播放国产一区中文字幕剧情欧美| 国产乱码久久久久久| 国产揄拍国内精品对白| 亚洲精品日韩精品| 三级成人在线| 亚洲美女av电影| 久久高清免费视频| 国产成人午夜99999| 国产日本欧美在线| 日本久久二区| 日韩中文字在线| 中文字幕在线2018| 国产午夜精品美女毛片视频| 少妇高潮喷水久久久久久久久久| 影音先锋欧美激情| 久久777国产线看观看精品| 国产精品一级二级| 亚洲色图欧洲色图婷婷| www.天天射.com| 精品大片一区二区| 国产精品美女免费| 成人高清免费在线播放| 在线观看亚洲精品| 天天舔天天操天天干| 日本视频一区二区| 亚洲电影一二三区| 久久精品资源| yw.139尤物在线精品视频| 国产精品久久久久久免费播放| 国产精品麻豆视频| 老司机午夜性大片| 亚洲精品99| 国产伦精品一区二区三| 草草在线视频| 亚洲欧美日韩第一区| 波多野结衣在线电影| 中文字幕免费在线观看视频一区| 超碰在线人人爱| 91精品国产福利在线观看麻豆| 99久久国产免费免费| 91超碰在线| 亚洲男人天堂2024| 在线观看国产小视频| 国产精品日韩精品欧美在线| 1314成人网| 亚洲久久视频| 日韩欧美一区二区三区四区五区| 九九热这里有精品| 欧美日韩国产成人高清视频| 日韩永久免费视频| 91国产成人在线| 天天综合天天做| 99久久精品99国产精品| 玩弄japan白嫩少妇hd| 五月天综合网站| 国产伦精品一区| 久久xxx视频| 欧美国产一区二区三区| 欧美老女人性开放| 5566中文字幕一区二区电影| 日本五十路女优| 中文字幕不卡的av| 动漫美女无遮挡免费| 日韩av午夜在线观看| 免费的一级黄色片| sdde在线播放一区二区| 99伊人久久| 88xx成人免费观看视频库| 久久99久久99精品中文字幕 | 国产精品影视天天线| 日韩欧美视频网站| 99欧美视频| 国产亚洲一区二区三区在线播放| 亚洲四虎影院| 性欧美在线看片a免费观看| 1pondo在线播放免费| 日韩电影中文字幕| 国产伦精品一区二区三区四区| 精品二区三区线观看| 中文字幕在线观看2018| www激情久久| 精品久久久久久无码人妻| 美女高潮久久久| a√天堂在线观看| 欧美另类女人| 亚洲一区高清| 欧美有码在线| 国产成人av一区二区三区| 欧美高清你懂的| 日韩美女在线看| 鲁鲁在线中文| 久久久久久久久久久久av| 日本中文在线观看| 一区二区在线视频| 日本v片在线免费观看| 欧美成人vr18sexvr| 一级片一区二区三区| 欧美在线看片a免费观看| 99热只有这里有精品| 午夜日韩在线观看| 久久久久久久久久91| 亚洲欧美在线高清| 少妇愉情理伦三级| 国产亚洲人成网站| 全黄一级裸体片| 91视频你懂的| 噜噜噜在线视频| av亚洲产国偷v产偷v自拍| 国产精品偷伦视频免费观看了| 狠狠色狠狠色综合日日91app| 亚洲色图 在线视频| 日韩在线a电影| 男人的天堂日韩| 首页欧美精品中文字幕| 久久久久人妻精品一区三寸| 99伊人成综合| 一女被多男玩喷潮视频| 亚洲主播在线| 国产福利视频在线播放| 久久av一区| 成年人黄色片视频| 久久精品午夜| 国产三级三级三级看三级| 久久综合影音| 九色91popny| 麻豆精品久久精品色综合| 亚洲欧洲日本精品| 狠狠色狠狠色综合日日91app| 亚洲精品中文字幕乱码无线| 国产美女视频一区| 成人一区二区三区仙踪林| 成人午夜av电影| 在线观看国产网站| 国产日韩欧美精品综合| 国产又粗又长又黄的视频| 亚洲图片激情小说| 亚欧洲精品在线视频| 欧美视频在线观看 亚洲欧| 91麻豆精品在线| 欧美群妇大交群的观看方式| 国产jzjzjz丝袜老师水多| 亚洲电影在线看| 久青草国产在线| 日韩视频免费大全中文字幕| 1stkiss在线漫画| 91精品国产91久久久久福利| 少妇一区视频| 91精品久久久久久蜜桃| 婷婷五月色综合香五月| 水蜜桃一区二区三区| 最新国产精品| 成人免费观看毛片| 久久精品72免费观看| 色哟哟无码精品一区二区三区| 国产香蕉久久精品综合网| 国产一区二区三区在线视频观看| 亚洲h精品动漫在线观看| 国产在线一级片| 日韩欧美国产麻豆| 欧美视频综合| 欧美超级乱淫片喷水| 成人美女视频| 91九色在线观看| 国产免费久久| 国产专区在线视频| 美女日韩在线中文字幕| 久久精品亚洲天堂| 久久久久亚洲综合| 欧美日韩国产精品一区二区三区| 在线国产亚洲欧美| 欧美自拍第一页| 精品国产一区二区三区久久狼5月| f2c人成在线观看免费视频| 国产精品亚洲网站| 亚洲精品合集| 成人黄色片免费| 美女网站一区二区| 国产美女视频免费观看下载软件| 国产精品久线在线观看| 亚洲久久在线观看| 欧美v国产在线一区二区三区| 国产黄色免费在线观看| 91精品国产一区| 精品999日本久久久影院| 视频在线99| 亚洲制服av| 99久久免费看精品国产一区| 亚洲精品美国一| 一级黄在线观看| 在线成人中文字幕| 性爽视频在线| 国产精品国产三级欧美二区| 亚洲成人最新网站| 中文久久久久久| 久久久精品国产免费观看同学| 国产在线观看你懂的| 日韩一区二区影院| 美女羞羞视频在线观看| 国产精品久久久久久久久久久不卡| 神马香蕉久久| 日韩国产欧美亚洲| www..com久久爱| 国产极品美女高潮无套嗷嗷叫酒店| 制服丝袜亚洲播放| 毛片在线视频| 91精品啪在线观看麻豆免费| 色喇叭免费久久综合网| www欧美激情| 国产精品视频一二三区| 探花国产精品一区二区| 亚洲色图校园春色| 天天综合网站| 亚洲国产婷婷香蕉久久久久久99| 日韩电影一区二区三区| 欧美大波大乳巨大乳| 91福利国产成人精品照片| 国产专区在线播放| 国产精品国语对白| 日韩一区电影| 国产主播中文字幕| 国产精品久久久久aaaa樱花| 一区二区三区播放| 久久精品国产亚洲精品2020| 免费观看亚洲天堂| bt天堂新版中文在线地址| 不卡在线观看av| 成人毛片在线播放| 亚洲最新av在线网站| 欧美伊人亚洲伊人色综合动图| 桥本有菜av在线| 国产精品69久久久久水密桃 | 色天天综合色天天久久| 国产露出视频在线观看| 91精品久久久久久久久久入口 | 欧美成人午夜激情视频| 亚洲精品午夜| 日韩少妇内射免费播放18禁裸乳| 国产午夜精品一区二区三区嫩草| 亚洲性在线观看| 欧美精品在线网站| 女人抽搐喷水高潮国产精品| 久久久久久久久久久久久国产精品 | 国产一区二区自拍| 乱人伦精品视频在线观看| 内射毛片内射国产夫妻| 91精品国产91久久综合桃花| 国产在线xxx| 欧洲亚洲一区二区| 国产一区二区三区免费播放| 国产小视频在线观看免费| 亚洲欧美精品中文字幕在线| 亚洲欧美专区| 日韩国产一级片| 国产精品三级在线观看| 国产白浆在线观看| 国产成人精品日本亚洲| 亚洲色图二区| 黄色aaa视频| 欧美一级二级三级乱码| 亚洲最大成人| 玖玖精品在线视频| 久久蜜桃一区二区| 国产99久一区二区三区a片| 青青草原成人在线视频| 欧美激情成人在线| 亚洲理论片在线观看| 日韩欧美一区二区不卡| gogo亚洲高清大胆美女人体| 乱熟女高潮一区二区在线| 国产亚洲精品福利| 免费观看黄色av| 国产日韩精品在线| 国产精品普通话对白| 手机在线免费看毛片| 亚洲视频999| 欧美三级电影在线| 日韩 国产 一区|