久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring TX源码分析

發(fā)布時間:2025/3/15 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring TX源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、先思考一下

  • 什么是事務?
    事務是一系列數(shù)據(jù)庫操作的集合,在一個事務里,所有有關的數(shù)據(jù)庫操作一起提交或一起回滾
  • 事務用在什么地方?
    如果多個數(shù)據(jù)庫操作需要一起生效或一起失效,那么這些操作需要放在一個事務里面
  • 事務如何創(chuàng)建?
    用戶創(chuàng)建了針對數(shù)據(jù)庫操作的連接(java.sql.Connection)之后,就可以針對Connection進行事務的操作,事務依賴于連接
  • 事務的基本操作?
    1. 開啟事務:Connection.setAutoCommit(false);關閉自動提交則就開啟了事務
    2. 提交事務:Connection.commit();
    3. 回滾事務:Connection.rollback();

關于事務的各種概念:


更詳細的參考

看源碼之前,如果有看AOP源碼的經歷,會很有幫助,因為spring的事務就是基于AOP的

二、開啟事務

  • 基于XML
  • 我們在beans.xml中開啟事務的應用,需要添加

    <tx:annotation-driven transaction-manager="transactionManager"/>
    • tx:annotation-driven/注解的分析

    但凡這種注解,都有對應的解析器,跟AOP功能的源碼一樣,解析器都實現(xiàn)了NamespaceHandlerSupport類,我們來獲取下NamespaceHandlerSupport的實現(xiàn)類都有哪些


    看名字就是TxNamespaceHandler類,我們來看下這個類有哪些內容

    • TxNamespaceHandler
    public class TxNamespaceHandler extends NamespaceHandlerSupport {...@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());// 這句代碼負責解析annotation-drivenregisterBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());} }

    Spring會默認調用其init()方法,annotation-driven對應的是AnnotationDrivenBeanDefinitionParser解析器,我們來看下這個解析器的作用

    • AnnotationDrivenBeanDefinitionParser的作用分析
    public BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);}else {// 默認為proxy模式// 所以要執(zhí)行該句AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null; }
    • AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);// txAdvisorBeanName值為 org.springframework.transaction.config.internalTransactionAdvisorString txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);// 1.注冊類AnnotationTransactionAttributeSource到Spring中RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// 2.注冊類TransactionInterceptor到Spring中RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// 3.注冊類BeanFactoryTransactionAttributeSourceAdvisor到Spring中RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));parserContext.registerComponent(compositeDef);} }

    總結:通過以上的分析可知,tx:annotation-driven/的主要功能就是將以下四個類注冊到Spring容器中

    • AnnotationTransactionAttributeSource
    • TransactionInterceptor(主要的攔截功能都在這里實現(xiàn))
    • BeanFactoryTransactionAttributeSourceAdvisor(創(chuàng)建bean的代理類的時候該Advisor會被用上)
    • InfrastructureAdvisorAutoProxyCreator:用于創(chuàng)建事務代理
    • InfrastructureAdvisorAutoProxyCreator功能分析

    其實現(xiàn)了BeanPostProcessor接口,則Spring在創(chuàng)建bean的時候,會默認調用InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization()方法,然后就是wrapIfNecessary,跟AOP的流程完全一致

  • 基于注解的@EnableTransactionManagement

  • 可以看到,注冊了AutoProxyRegistrar(是一個BeanPostProcessor)和ProxyTransactionManagementConfiguration(用于解析事務屬性)

    • ProxyTransactionManagementConfiguration
    • 該類是一個配置Bean
    • 目的:創(chuàng)建事務的切面,跟AOP的區(qū)別就在這里,AOP的切面是我們自己定義的,而事務的切面是Spring給我們生成的
    @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {//想IOC容器中導入事務增強器(BeanFactoryTransactionAttributeSourceAdvisor),// 事務注解@Transactional的解析器(AnnotationTransactionAttributeSource)// 和事務方法攔截器(TransactionInterceptor);/**事務增強器(Advisor),在事務類創(chuàng)建的時候,被AutoProxyRegistrar導入的組件InfrastructureAdvisorAutoProxyCreator攔截,InfrastructureAdvisorAutoProxyCreator攔截的邏輯就是增強事務類的事務方法, 而BeanFactoryTransactionAttributeSourceAdvisor作為增強器,與需要增強的方法(這里是指被@Transactional標記的方法)進行匹配,匹配成功的增強器,最后轉成攔截器(MethodInterceptor,就是下面的TransactionInterceptor),然后與目標方法一起在攔截器鏈中被執(zhí)行,達到方法增強的效果;BeanFactoryTransactionAttributeSourceAdvisor的繼承關系如下:BeanFactoryTransactionAttributeSourceAdvisor--AbstractBeanFactoryPointcutAdvisor--AbstractPointcutAdvisor--PointcutAdvisor--AdvisorAOP中AspectJPointcutAdvisor的繼承關系如下,與AbstractPointcutAdvisor一樣,都實現(xiàn)PointcutAdvisor--AspectJPointcutAdvisor--PointcutAdvisor--Advisor*/@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());advisor.setOrder(this.enableTx.<Integer>getNumber("order"));return advisor;}/**@ Transactional注解的解析類;負責解析事務方法上@Transactional中的各個參數(shù)配置,解析的時機是在創(chuàng)建事務類之后被增強的時候,匹配事務方法的時候一起被解析了AnnotationTransactionAttributeSource的繼承關系如下:AnnotationTransactionAttributeSource--AbstractFallbackTransactionAttributeSource--TransactionAttributeSource通過方法org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>)解析出事務信息TransactionAttribute;AnnotationTransactionAttributeSource在方法findTransactionAttribute(Class<?>)中依賴于SpringTransactionAnnotationParser在解析事務類時,綁定事務方法與增強器的時候進行@Transactional注解解析;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}/**被@Transactional標記的事務方法的攔截器,實際是一個MethodInterceptor保存了事務屬性信息,事務管理器;在目標方法執(zhí)行的時候;執(zhí)行攔截器鏈;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;} }
    • AutoProxyRegistrar


    可以看到也注冊了一個InfrastructureAdvisorAutoProxyCreator


    跟xml的方式殊途同歸:也實現(xiàn)了BeanPostProcessor接口,則Spring在創(chuàng)建bean的時候,會默認調用InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization()方法,然后就是wrapIfNecessary,跟AOP的流程完全一致

    那么后置處理bean有了,切面也有了,就可以創(chuàng)建事務代理了

    三、執(zhí)行事務

    跟AOP一樣,以JdkDynamicProxy一樣,調用代理,觸發(fā)ReflectiveMethodInvocation的執(zhí)行方法

    retVal = invocation.proceed();

    進而執(zhí)行到

    代碼跟到這里,跟AOP又有一個不同的點,就是這個invoke的實現(xiàn)是TransactionInterceptor類,該類專門處理事務切面的執(zhí)行

    //TransactionInterceptorpublic Object invoke(MethodInvocation invocation) throws Throwable {//計算出目標類:可能是 {@code null}。 TransactionAttributeSource 應該傳遞目標類以及方法,該方法可能來自接口。Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);//適配TransactionAspectSupport的invokeWithinTransaction...return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);}

    進而進入invokeWithinTransaction

    @Nullable//TransactionAspectSupportprotected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,final InvocationCallback invocation) throws Throwable {// If the transaction attribute is null, the method is non-transactional.// 如果事務屬性為空,則該方法是非事務性的。TransactionAttributeSource tas = getTransactionAttributeSource();//拿到事務5個屬性的值,@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT )final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);//獲取事務管理器,由我們通過配置指定。事務管理的底層一定會與數(shù)據(jù)庫有關,所以會注入數(shù)據(jù)源等屬性final PlatformTransactionManager tm = determineTransactionManager(txAttr);//切入點,也就是需要控制事務的目的方法(update...)final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {// Standard transaction demarcation with getTransaction and commit/rollback calls.//使用 getTransaction 和 commitRollback 調用進行標準事務劃分,這一句是最難理解的//ifNecessary?其實就是根據(jù)事務屬性決定是否開啟事務TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal;try {// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.// 源方法運行retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {// target invocation exception//出現(xiàn)異常時則回滾事務,注意:如果是Exception不會回滾,只有RunTimeException或者Error來及其子類才會回滾completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {//重置 TransactionInfo ThreadLocal。 在所有情況下都調用它:異常或正常返回cleanupTransactionInfo(txInfo);}//提交事務//TransactionManager調用Connection.commit()commitTransactionAfterReturning(txInfo);return retVal;}

    進入createTransactionIfNecessary

    protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {// If no name specified, apply method identification as transaction name.// 如果未指定名稱,則應用方法標識作為事務名稱if (txAttr != null && txAttr.getName() == null) {txAttr = new DelegatingTransactionAttribute(txAttr) {@Overridepublic String getName() {return joinpointIdentification;}};}//記錄當前事務的狀態(tài),是否新事務,是否只讀事務,是否開啟同步?TransactionStatus status = null;if (txAttr != null) {if (tm != null) {//獲取事務的狀態(tài)status = tm.getTransaction(txAttr);}else {if (logger.isDebugEnabled()) {logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +"] because no transaction manager has been configured");}}}return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);}

    當TransactionAttribute為null,則創(chuàng)建一個TransactionInfo

    protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,@Nullable TransactionAttribute txAttr, String joinpointIdentification,@Nullable TransactionStatus status) {/** 根據(jù)給定的事務屬性、事務管理器、方法連接點描述字符串(全限定方法名)信息創(chuàng)建一個事務信息對象TransactionInfo*/TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);// 如果事務屬性不為nullif (txAttr != null) {// We need a transaction for this method...if (logger.isTraceEnabled()) {logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");}//那么設置事務狀態(tài),這里就表示為當前方法創(chuàng)建了一個事務txInfo.newTransactionStatus(status);}// 如果事務屬性為null,那么表示當前方法必須要創(chuàng)建事務else {if (logger.isTraceEnabled()) {logger.trace("No need to create transaction for [" + joinpointIdentification +"]: This method is not transactional.");}}//始終將最新的TransactionInfo綁定到當前線程,即使我們沒有在此處創(chuàng)建新的事務也是如此。//也就是將當前線程的最新事務棧設置為當前對象存入transactionInfoHolder中//這保證即使此方面未創(chuàng)建任何事務,也將正確管理TransactionInfo堆棧。txInfo.bindToThread();return txInfo; }
    • 這里要先介紹一下TransactionInfo,這是SpringTX的核心,TransactionInfo是TransactionAspectSupport的內部類,用來保存線程的執(zhí)行方法時的事務信息。內部保存了事務管理器transactionManager、事務屬性transactionAttribute、全路徑方法名joinpointIdentification。還保存了當前方法的事務transactionStatus,以及前一個方法的事務信息對象oldTransactionInfo。
    protected final class TransactionInfo {@Nullable//事務管理器private final PlatformTransactionManager transactionManager;@Nullable//事務屬性private final TransactionAttribute transactionAttribute;//連接點描述字符串(方法的全限定名),主要用于記錄日志private final String joinpointIdentification;@Nullable//事務狀態(tài)private TransactionStatus transactionStatus;@Nullable//老的事務信息對象private TransactionInfo oldTransactionInfo;public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,@Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {this.transactionManager = transactionManager;this.transactionAttribute = transactionAttribute;this.joinpointIdentification = joinpointIdentification;}public PlatformTransactionManager getTransactionManager() {Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");return this.transactionManager;}@Nullablepublic TransactionAttribute getTransactionAttribute() {return this.transactionAttribute;}/*** Return a String representation of this joinpoint (usually a Method call)* for use in logging.*///返回此連接點的String表示形式(通常是方法調用),以用于日志記錄。public String getJoinpointIdentification() {return this.joinpointIdentification;}public void newTransactionStatus(@Nullable TransactionStatus status) {this.transactionStatus = status;}@Nullablepublic TransactionStatus getTransactionStatus() {return this.transactionStatus;}/*** Return whether a transaction was created by this aspect,* or whether we just have a placeholder to keep ThreadLocal stack integrity.*///返回是否是通過此切面創(chuàng)建的事務,或者是否只是一個占位符以保持ThreadLocal堆棧完整性。即當前方法是否新建了事務。public boolean hasTransaction() {return (this.transactionStatus != null);}private void bindToThread() {向線程公開當前的TransactionStatus,并保留所有現(xiàn)有的老的TransactionStatus,以在此事務完成后恢復。// Expose current TransactionStatus, preserving any existing TransactionStatus// for restoration after this transaction is complete.this.oldTransactionInfo = transactionInfoHolder.get();transactionInfoHolder.set(this);}private void restoreThreadLocalStatus() {// Use stack to restore old transaction TransactionInfo.// Will be null if none was set.// 使用堆棧還原舊的事務TransactionInfo。如果未設置,則為null。transactionInfoHolder.set(this.oldTransactionInfo);}@Overridepublic String toString() {return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction");}}

    如果事務屬性不為空,那么走getTransaction獲取/開啟事務分支。在createTransactionIfNecessary方法中,如果存在事務屬性TransactionAttribute,并且存在事務管理器PlatformTransactionManager,那么將調用事務管理器的getTransaction方法根據(jù)為當前方法配置的事務定義的屬性嘗試獲取事務,將返回一個TransactionStatus對象。該方法是事務管理的核心方法,其骨干實現(xiàn)位于抽象實現(xiàn)類AbstractPlatformTransactionManager中,該方法根據(jù)配置的各種事務傳播行為做出不同的處理,方法執(zhí)行完畢將可能開啟了新事物,也可能沒有開啟,甚至拋出異常。AbstractPlatformTransactionManager的設計基于模版方法模式,他提供了處理流程,并且提供了一系列的do……模版方法供子類來實現(xiàn)自己的邏輯。

    getTransaction方法的大概邏輯為:

  • 首先通過doGetTransaction方法獲取一個內部事務對象,該方法由具體的事務管理器子類自己實現(xiàn),返回的對象也是不一樣的,對于DataSourceTransactionManager這里獲取的實際上是一個DataSourceTransactionObject,其內部可能會包含當前數(shù)據(jù)的連接以及當前的事務信息,也可能沒有(比如首次進入事務方法)。
  • 通過isExistingTransaction方法判斷事物對象內部的數(shù)據(jù)庫連接connectionHolder是否不為null并且是否已經開啟過了事務。
      • 如果條件都滿足,那么表示此前已經開啟過了事務,即存在外層事務,隨后調用handleExistingTransaction方法統(tǒng)一處理這種情況,比如加入當前事務、新建事務、拋出異常等等邏輯。
  • 如果不都滿足,即不存在外層事務,那么說明當前的事務方法就是最外層的事務方法,那么走下面的邏輯。
      • 校驗為當前事務方法設置的事務超時時間,如果小于默認超時時間(-1),將會拋出異常。
      • 如果為當前事務方法設置的傳播行為PROPAGATION_MANDATORY,該傳播行為的含義是:如果當前存在事務,則當前方法加入到該事務中去,如果當前不存在事務,則當前方法直接拋出異常。這里由于不存在外層事務,那么這里就直接拋出異常:“No existing transaction found for transaction marked with propagation ‘mandatory’”。
      • 如果為當前事務方法設置的傳播行為是PROPAGATION_REQUIRED或者PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED,這些傳播行為的含義的共同點之一就是:如果當前不存在事務,就創(chuàng)建一個新事務運行。這里由于不存在外層事務,那么這里就直接創(chuàng)建一個新事物。
        • 首先調用suspend方法首先掛起事務同步,然后再委派給doSuspend模板方法掛起事務,將返回被掛起的資源,用于后續(xù)恢復,如果沒有事務同步也沒有事務,那么將返回null。這里由于沒有已存在的事務,那么參數(shù)傳遞null,一般也會將返回null。
        • 調用startTransaction方法,內部依次調用newTransactionStatus方法創(chuàng)建TransactionStatus、doBegin方法真正的開啟新的事務、prepareSynchronization方法準備事務同步,最終返回TransactionStatus,該對象包含了創(chuàng)建的內部事務對象,以及其他事務信息。
  • 否則,配置的事務的傳播行為就是剩下的三種:PROPAGATION_SUPPORTS或PROPAGATION_NEVER或PROPAGATION_NOT_SUPPORTED,這幾個傳播行為的含義的共同點之一就是:當前方法一定以非事務的方式運行。那么這里仍然會創(chuàng)建TransactionStatus對象,但是不會開啟事物,相當于一個空事務。
      • 調用prepareTransactionStatus方法返回一個TransactionStatus,和上面的startTransaction方法相比,其內部會調用newTransactionStatus和prepareSynchronization,但不會調用doBegin方法,因此不會真正的開啟事物。這里它的newTransaction參數(shù)為false,suspendedResources參數(shù)為null。
    @Overridepublic final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {//獲取當前事務,該方法由具體的事務管理器子類自己實現(xiàn),比如DataSourceTransactionManager、JtaTransactionManager//一般都使用DataSourceTransactionManager這個事務管理器//對于DataSourceTransactionManager這里獲取的實際上是一個數(shù)據(jù)庫的事務連接對象,即DataSourceTransactionObjectObject transaction = doGetTransaction();// Cache debug flag to avoid repeated checks.boolean debugEnabled = logger.isDebugEnabled();if (definition == null) {// Use defaults if no transaction definition given.definition = new DefaultTransactionDefinition();}// isExistingTransaction,默認返回false,同樣被具體的事務管理器子類重寫// DataSourceTransactionManager的方法將會判斷上面獲取的DataSourceTransactionObject內部的數(shù)據(jù)庫連接connectionHolder屬性是否不為null,// 并且是否已經開啟了事務。我們說過如果當前線程是第一次進來,那么connectionHolder就是null。if (isExistingTransaction(transaction)) {// Existing transaction found -> check propagation behavior to find out how to behave.//如果已經存在事務,那么將檢查傳播行為并進行不同的處理,隨后返回return handleExistingTransaction(definition, transaction, debugEnabled);}//到這里表示沒有已存在的事務,進入第一個事務方法時將會走這個邏輯//設置的事務超時時間如果小于默認超時時間(-1),將會拋出異常// Check definition settings for new transaction.if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());}//如果配置的事務的傳播行為是PROPAGATION_MANDATORY,該傳播行為的含義是://如果當前存在事務,則當前方法加入到該事務中去,如果當前不存在事務,則當前方法直接拋出異常。//這里就直接拋出異常。// No existing transaction found -> check propagation behavior to find out how to proceed.if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");}//否則,如果配置的事務的傳播行為是PROPAGATION_REQUIRED或者PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED,//這幾個傳播行為的含義的共同點之一就是:如果當前不存在事務,就創(chuàng)建一個新事務運行。//那么這里將開啟一個新事物。else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {//暫停給定的事務。首先掛起事務同步,然后再委派給doSuspend模板方法。由于此前沒有事務,所以參數(shù)事務為nullSuspendedResourcesHolder suspendedResources = suspend(null);if (debugEnabled) {logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);}try {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);//開啟一個新事務并返回DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}catch (RuntimeException | Error ex) {//喚醒此前掛起的事務和資源resume(null, suspendedResources);throw ex;}}//否則,配置的事務的傳播行為就是剩下的三種:PROPAGATION_SUPPORTS或PROPAGATION_NEVER或PROPAGATION_NOT_SUPPORTED,//這幾個傳播行為的含義的共同點之一就是:當前方法一定以非事務的方式運行。else {//將會創(chuàng)建“空”事務:即沒有實際的事務,但是有潛在的同步性。//如果配置的事務的隔離級別不是默認的隔離級別,那么輸出警告://雖然指定了自定義的隔離級別,但是由于未啟動任何事物,那么隔離級別也就不會生效了// Create "empty" transaction: no actual transaction, but potentially synchronization.if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {logger.warn("Custom isolation level specified but no actual transaction initiated; " +"isolation level will effectively be ignored: " + definition);}boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);//為給定參數(shù)創(chuàng)建一個新的TransactionStatus,并在適當時初始化事務同步,但是不會真正開啟事務。//和startTransaction相比,其內部會調用newTransactionStatus和prepareSynchronization,但不會調用doBegin方法return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);}}
    • doGetTransaction獲取事務連接

    返回當前已存在的事務對象,返回的對象應包含有關任何現(xiàn)有事務的信息,即,在事務管理器上的當前getTransaction方法調用之前已經啟動的事務。因此,doGetTransaction的實現(xiàn)通常是將查找現(xiàn)有事務并將相應的狀態(tài)存儲在返回的事務對象中。返回的對象通常特定于具體的事務管理器子類自己實現(xiàn)。一般都使用DataSourceTransactionManager這個事務管理器,它的doGetTransaction方法邏輯如下:

  • 創(chuàng)建一個DataSourceTransactionObject對象,由DataSourceTransactionManager用作內部事務對象。可能會持有一個ConnectionHolder對象,還具有創(chuàng)建、回滾、釋放保存點的功能。
  • 設置是否允許保存點,DataSourceTransactionManager默認會允許,一般用于實現(xiàn)嵌套事務。
  • obtainDataSource方法用于獲取配置的數(shù)據(jù)源,就是我們自己配置的數(shù)據(jù)源,getResource用于獲取此線程在當前數(shù)據(jù)源中已擁有JDBC連接資源持有者。如果此前沒有獲取過連接,則返回null;如果此前開啟了過事務(外層事務),那么肯定不會獲取null。
  • 設置連接信息,newConnectionHolder屬性設置為false,這表示默認此前已經存在ConnectionHolder,但實際上可能并沒有,因此后面的步驟中會再次判斷該值。
  • 最后返回DataSourceTransactionObject。
  • @Override//DataSourceTransactionManagerprotected Object doGetTransaction() {//創(chuàng)建一個DataSourceTransactionObject,由DataSourceTransactionManager用作內部事務對象。//內部可能會持有一個ConnectionHolder對象,還具有創(chuàng)建、回滾、釋放保存點的功能DataSourceTransactionObject txObject = new DataSourceTransactionObject();//設置是否允許保存點,DataSourceTransactionManager默認會允許,用于實現(xiàn)嵌套事務txObject.setSavepointAllowed(isNestedTransactionAllowed());//obtainDataSource方法用于獲取配置的數(shù)據(jù)源,就是我們自己配置的數(shù)據(jù)源//getResource用于獲取此線程在當前數(shù)據(jù)源中已擁有JDBC連接資源持有者ConnectionHolder//如果此前沒有獲取過連接,則返回null;如果此前開啟了過事務(外層事務),那么肯定不會獲取nullConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());//設置連接信息,newConnectionHolder屬性設置為false,這表示默認此前已經存在ConnectionHolder//但實際上可能并沒有,因此后面的步驟中會再次判斷該值txObject.setConnectionHolder(conHolder, false);return txObject;}
    • 這里也要介紹一個類TransactionSynchronizationManager事務同步管理器

      這個類比較特別,雖然它的名字帶有Transaction以及Manager,但卻不是TransactionManager體系,它沒有任何繼承樹,因此它可以看作一個很特別的工具類。該類被稱為事務同步管理器。主要用于管理每一個線程當前所使用的數(shù)據(jù)庫事務連接資源和事務同步器(TransactionSynchronization)。
      ??一個線程在當前只能激活一個連接資源,因此如果需要綁定新的連接資源,那么需要將此前綁定的資源刪除(或者說保存起來,等新資源使用完畢之后再恢復此前的連接資源)。另外還能支持事務同步列表,事務同步必須由事務管理器通過initSynchronization()和clearSynchronization()來進行激活和停用,使用isSynchronizationActive()檢測當前是否具有事務同步。
      ??TransactionSynchronizationManager內部是通過很多ThreadLocal(線程本地變量)類型的屬性來實現(xiàn)為當前線程維護自己的資源的功能的,實現(xiàn)資源隔離。

    部分屬性:

    public abstract class TransactionSynchronizationManager {private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);// 事務資源// 一個ThreadLocal屬性,用于存放線程當前使用的數(shù)據(jù)庫資源// value是一個Map<Object, Object>,key為某個數(shù)據(jù)源DataSource ,value實際上就是連接ConnectionHolderprivate static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");/*** 事務同步* <p>* 一個ThreadLocal屬性,用于存放線程當前激活的事務同步器TransactionSynchronization* 每個線程都可以開啟多個事物同步,用于在處理事務的各個階段進行自定義擴展或者回調* <p>* TransactionSynchronization的同步回調功能類似于此前學習的@TransactionalEventListener*/private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =new NamedThreadLocal<>("Transaction synchronizations");//一個ThreadLocal屬性,用于存放線程當前的事務的名稱private static final ThreadLocal<String> currentTransactionName =new NamedThreadLocal<>("Current transaction name");//一個ThreadLocal屬性,用于存放線程當前的事務的只讀狀態(tài)private static final ThreadLocal<Boolean> currentTransactionReadOnly =new NamedThreadLocal<>("Current transaction read-only status");//一個ThreadLocal屬性,用于存放線程當前的當前事務的隔離級別private static final ThreadLocal<Integer> currentTransactionIsolationLevel =new NamedThreadLocal<>("Current transaction isolation level");//一個ThreadLocal屬性,用于存放線程當前是否開啟了事務private static final ThreadLocal<Boolean> actualTransactionActive =new NamedThreadLocal<>("Actual transaction active");
    • obtainDataSource獲取數(shù)據(jù)源

    獲取當前DataSourceTransactionManager實際使用的數(shù)據(jù)源,就是我們配置給事務管理器的DataSource

    /*** @return 數(shù)據(jù)源(絕不為null)*/ protected DataSource obtainDataSource() {DataSource dataSource = getDataSource();Assert.state(dataSource != null, "No DataSource set");return dataSource; } /*** 就是我們配置的數(shù)據(jù)源*/ @Nullable private DataSource dataSource; /*** 返回此事務管理器內部的JDBC DataSource。*/ @Nullable public DataSource getDataSource() {return this.dataSource; }
    • getResource獲取已存在的連接

    TransactionSynchronizationManager的方法,該方法檢索給定key綁定到當前線程的資源,實際上就是嘗試從resources屬性中獲綁定當前線程的從給定數(shù)據(jù)源獲已取到的連接資源ConnectionHolder。如果此前沒有獲取過此數(shù)據(jù)源的連接,那么將會得到一個null值,即如果是第一次進入事務方法,那么將返回null。這里resources屬性的value是一個Map<Object, Object>,這說明一個線程可以從不同的數(shù)據(jù)源中獲取資源,但是對于同一個數(shù)據(jù)源,只能保存一個的數(shù)據(jù)源。

    public static Object getResource(Object key) {//如有必要,解開給定的資源句柄,否則按原樣返回給定的句柄,常用于從各種代理對象中獲取原始對象Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);//真正獲取當前綁定的資源Object value = doGetResource(actualKey);if (value != null && logger.isTraceEnabled()) {logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +Thread.currentThread().getName() + "]");}return value;}
    • isExistingTransaction是否已存在事務

    檢查是否已經開啟過事務,默認返回false,被具體的事務管理器子類重寫。
    DataSourceTransactionManager的邏輯很簡單,判斷通過doGetTransaction方法獲取的DataSourceTransactionObject內部的數(shù)據(jù)庫連接connectionHolder屬性是否不為null,并且是否已經開啟了事務。我們說過如果當前線程是第一次進來,那么connectionHolder就是null。

    @Overrideprotected boolean isExistingTransaction(Object transaction) {強轉為DataSourceTransactionObjectDataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;判斷內部的數(shù)據(jù)庫連接connectionHolder是否不為null并且已經開啟了事務return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());}
    • suspend掛起事務

    掛起給定的事務。首先掛起當前線程的事務同步回調,然后再委派給doSuspend模板方法由子類來實現(xiàn)掛起當前事務,并且還會清空TransactionSynchronizationManager中保存的當前線程的事務信息。最終將會返回會被掛起的資源只有者SuspendedResourcesHolder。如果沒有事務同步也沒有事務,那么將會返回null。當前線程第一次進入事務方法時,默認將會返回null。

    //AbstractPlatformTransactionManagerprotected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {//如果當前線程的事務同步處于活動狀態(tài),即存在綁定的TransactionSynchronization,則返回true。//如果是第一次因為進來,那么自然為falseif (TransactionSynchronizationManager.isSynchronizationActive()) {//掛起當前線程的所有事務同步回調,這類似于@TransactionalEventListener,并返回"被掛起"的回調List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();try {Object suspendedResources = null;if (transaction != null) {//掛起事務,由具體的子類實現(xiàn)suspendedResources = doSuspend(transaction);}//獲取當前事務的信息,并且清空各個ThreadLocal緩存中的當前線程的當前事務信息(恢復為默認值)//獲取并清空(設置為null)事物名稱String name = TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);//獲取并清空(設置為false)事物只讀狀態(tài)boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);//獲取并清空(設置為null)事物隔離級別Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);//獲取并清空(設置為false)事物是否激活boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);//將獲取的當前事物的信息存入一個SuspendedResourcesHolder對象中返回return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}catch (RuntimeException | Error ex) {// doSuspend failed - original transaction is still active...doResumeSynchronization(suspendedSynchronizations);throw ex;}}//如果沒有事務同步但是開啟了事務,那么掛起事務else if (transaction != null) {// Transaction active but no synchronization active.//掛起事務,由具體的子類實現(xiàn)Object suspendedResources = doSuspend(transaction);//將掛起的資源存入一個SuspendedResourcesHolder對象中返回return new SuspendedResourcesHolder(suspendedResources);}else {// Neither transaction nor synchronization active.//事務或者事務同步均未激活,返回null,什么也不干return null;}}
    • isSynchronizationActive是否激活事務同步
      ?
      TransactionSynchronizationManager的方法,用來判斷線程在當前是否已激活事務同步TransactionSynchronization。實際上就是synchronizations屬性中是否有綁定到當前線程的Set集合,如果有(不為null),那就說明存在事務同步。
    /*** TransactionSynchronizationManager的屬性* <p>* 一個ThreadLocal類型的屬性,每個線程都可以開啟事物同步,用于在處理事務的各個階段進行自定義擴展或者回調* TransactionSynchronization的同步回調功能類似于此前學習的@TransactionalEventListener*/ private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =new NamedThreadLocal<>("Transaction synchronizations"); /*** TransactionSynchronizationManager的方法* <p>* 判斷當前線程的是否注冊了事務同步*/ public static boolean isSynchronizationActive() {//獲取當前線程綁定的TransactionSynchronization,如果不為null就說明注冊了事務同步return (synchronizations.get() != null); }
    • doSuspendSynchronization掛起事務同步
      ??
      ??該方法掛起當前線程在TransactionSynchronizationManager的synchronize并且將屬性中為當前線程保持的事務同步列表引用移除,最后返回被掛起的事務同步列表!
    /*** AbstractPlatformTransactionManager的方法* <p>* 掛起所有當前同步,并停用當前線程的事務同步。** @return 掛起的TransactionSynchronization對象的列表*/ private List<TransactionSynchronization> doSuspendSynchronization() {//獲取線程的當前的所有事務同步列表List<TransactionSynchronization> suspendedSynchronizations =TransactionSynchronizationManager.getSynchronizations();//遍歷,依次掛起每一個事務同步for (TransactionSynchronization synchronization : suspendedSynchronizations) {synchronization.suspend();}//清除synchronizations屬性中保存的的當前線程的當前事務同步集合的引用TransactionSynchronizationManager.clearSynchronization();//返回被掛起的事務同步return suspendedSynchronizations; }/*** TransactionSynchronizationManager的方法* 調用該方法時一定要保證當前線程存在事務同步,否則將拋出異常* 因此需要先調用isSynchronizationActive方法來校驗* <p>* 返回當前線程的所有已注冊的事務同步的無法修改的快照列表** @return 無法修改的TransactionSynchronization實例列表* @throws IllegalStateException 如果同步未激活*/ public static List<TransactionSynchronization> getSynchronizations() throws IllegalStateException {//獲取當前線程的事務同步列表Set<TransactionSynchronization> synchs = synchronizations.get();//為null就拋出IllegalStateException異常if (synchs == null) {throw new IllegalStateException("Transaction synchronization is not active");}// 返回不可修改的快照,以避免在迭代和調用可能進一步注冊同步的同步回調時拋出ConcurrentModificationExceptions。if (synchs.isEmpty()) {return Collections.emptyList();} else {//在獲取的之后對快照進行排序List<TransactionSynchronization> sortedSynchs = new ArrayList<>(synchs);AnnotationAwareOrderComparator.sort(sortedSynchs);return Collections.unmodifiableList(sortedSynchs);} }/*** TransactionSynchronizationManager的方法* 調用該方法時一定要保證當前線程存在事務同步,否則將拋出異常* 因此需要先調用isSynchronizationActive方法來校驗* <p>* 停用當前線程的事務同步,由事務管理器在事務清理中調用。** @throws IllegalStateException 如果同步未激活*/ public static void clearSynchronization() throws IllegalStateException {//如果沒有激活事務同步,同樣拋出異常if (!isSynchronizationActive()) {throw new IllegalStateException("Cannot deactivate transaction synchronization - not active");}logger.trace("Clearing transaction synchronization");//移除當前線程綁定到synchronizations屬性的值synchronizations.remove(); }
    • doSuspend掛起事務

    其核心就是doSuspend方法,該方法默認拋出異常,由子類自己實現(xiàn)!DataSourceTransactionManager重寫的方法很簡單,就是將DataSourceTransactionObject中的connectionHolder設置為null,并且將給定數(shù)據(jù)源綁定到當前線程的連接資源從TransactionSynchronizationManager的resources屬性中移除并返回,這就是DataSourceTransactionManager被掛起的連接資源,就是此前獲取的連接。從這里能夠看出,所謂的“掛起”,就是將當前的連接從綁定的線程本地變量中移除!

    /*** DataSourceTransactionManager的方法* <p>* 掛起當前事務,返回當前的連接資源** @param transaction 掛起事務* @return 被掛起的資源*/ @Override protected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;//將當前的事務對象的connectionHolder設置為nulltxObject.setConnectionHolder(null);//將當前線程的綁定的當前數(shù)據(jù)源對應的連接同樣移除,并且返回被移除的連接資源return TransactionSynchronizationManager.unbindResource(obtainDataSource()); }/*** TransactionSynchronizationManager的方法* <p>* 移除當前線程中給定key綁定的資源的值** @param key 就是當前數(shù)據(jù)源* @return 被移除的資源,就是連接*/ public static Object unbindResource(Object key) throws IllegalStateException {Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);//真正的移除指定的key對應的連接Object value = doUnbindResource(actualKey);if (value == null) {throw new IllegalStateException("No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");}return value; }/*** 事務資源*/ private static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");/*** TransactionSynchronizationManager的方法* <p>* 移除當前線程中給定key綁定的資源的值。** @param actualKey 就是當前數(shù)據(jù)源* @return 被移除的資源,就是連接*/ @Nullable private static Object doUnbindResource(Object actualKey) {//獲取和當前線程綁定的數(shù)據(jù)庫資源mapMap<Object, Object> map = resources.get();if (map == null) {return null;}//從map中移除從當前數(shù)據(jù)源對應的連接緩存Object value = map.remove(actualKey);//如果map為空,則刪除整個ThreadLocal。if (map.isEmpty()) {resources.remove();}// Transparently suppress a ResourceHolder that was marked as void...if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {value = null;}if (value != null && logger.isTraceEnabled()) {logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +Thread.currentThread().getName() + "]");}//返回被移除的資源return value; }
    • newTransactionStatus開啟新事物

    新建一個DefaultTransactionStatus實現(xiàn)并返回,內部持有我們?yōu)楫斍胺椒ㄅ渲玫氖聞諏傩曰蛘吣J屬性,以及保存著此前掛起的其他資源。新建一個DefaultTransactionStatus實現(xiàn)并返回,內部持有我們?yōu)楫斍胺椒ㄅ渲玫氖聞諏傩曰蛘吣J屬性,以及保存著此前掛起的其他資源。

    /*** AbstractPlatformTransactionManager的方法* <p>* 為給定參數(shù)新創(chuàng)建一個TransactionStatus實例,實際類型為DefaultTransactionStatus** @param definition 為當前方法配置的事務定義* @param transaction 獲取的事務對象* @param newTransaction 是否是新事物* @param newSynchronization 是否開啟事務同步* @param debug 是否支持debug級別的日志* @param suspendedResources 被掛起的資源,比如此前的事務同步* @return DefaultTransactionStatus對象*/ protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {//如果newSynchronization為true并且當前線程沒有綁定的事務同步,那么確定開啟新事物同步//由于此前調用了suspend方法清理了此前的事務同步,因此一般都是需要開啟新事務同步,即為trueboolean actualNewSynchronization = newSynchronization &&!TransactionSynchronizationManager.isSynchronizationActive();//返回一個新建的DefaultTransactionStatus對象,該對象被用來表示新開啟的事務,是TransactionStatus的默認實現(xiàn)//內部包括了各種新開啟的事務狀態(tài),當然包括此前掛起的事務的資源return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization,definition.isReadOnly(), debug, suspendedResources); } /*DefaultTransactionStatus的屬性*/ /*** 從事務管理器獲取的內部事務* 對于DataSourceTransactionManager來說就是DataSourceTransactionObject*/ @Nullable private final Object transaction; /*** 是否是新事物*/ private final boolean newTransaction; /*** 是否開啟新事務同步*/ private final boolean newSynchronization; /*** 是否開啟新事務同步*/ private final boolean readOnly; /*** 是否支持debug日志級別*/ private final boolean debug; /*** 此前被掛起的事務資源*/ @Nullable private final Object suspendedResources; public DefaultTransactionStatus(@Nullable Object transaction, boolean newTransaction, boolean newSynchronization,boolean readOnly, boolean debug, @Nullable Object suspendedResources) {this.transaction = transaction;this.newTransaction = newTransaction;this.newSynchronization = newSynchronization;this.readOnly = readOnly;this.debug = debug;this.suspendedResources = suspendedResources; }
    • doBegin真正開啟事務

    該方法是核心方法,當事務管理器決定實際開始新事務時,將調用此方法。此時之前可能沒有任何事務,或者先前的事務已被暫停。根據(jù)給定的事務定義TransactionDefinition,以及此前通過doGetTransaction方法返回的事務對象(也就是DataSourceTransactionObject),使用給定的語義開始一個新事務。不必關心應用傳播行為,因為抽象事務管理器已經處理了該行為。
    ??
    大概步驟為:

  • 從數(shù)據(jù)源中獲取一個新連接Connection,并且包裝為一個ConnectionHolder對象。ConnectionHolder設置為DataSourceTransactionObject事務對象的connectionHolder屬性,并且將newConnectionHolder屬性設置為true。
  • 初始化連接的各種屬性,比如隔離級別、只讀標志等。
  • 通過con.setAutoCommit(false),設置當前連接為手動提交,真正開啟事務!
  • 設置ConnectionHolder的transactionActive屬性為true,表示激活當前連接的事務。
  • 設置超時時間。如果不是默認超時時間-1,那么將根據(jù)設置的值和當前時間轉換為未來的毫秒值并創(chuàng)建新Date配置給ConnectionHolder的deadline屬性,在其他數(shù)據(jù)庫操作框架操作時將會獲取該參數(shù)。
  • 如果是新連接,即newConnectionHolder屬性為true,綁定ConnectionHolder資源到TransactionSynchronizationManager的resources屬性中,就是前面說的事務資源,key就是當前的屬性源dataSource,value就是ConnectionHolder。
  • //開啟新事物,并不會處理事務的傳播行為,因為傳播行為是Spring提供的特性,在事務管理器中就被直接處理了@Override//DataSourceTransactionManagerprotected void doBegin(Object transaction, TransactionDefinition definition) {//強制轉型DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;Connection con = null;try {//如果不存在事務連接資源持有者屬性,或者資源標記為與事務同步//簡單的說就還沒有獲取連接,那么這里從數(shù)據(jù)源中獲取一個新連接//第一次進入事務方法時默認就會走該邏輯if (!txObject.hasConnectionHolder() ||txObject.getConnectionHolder().isSynchronizedWithTransaction()) {//從我們配置的數(shù)據(jù)源中獲取一個新連接Connection newCon = obtainDataSource().getConnection();if (logger.isDebugEnabled()) {logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");}/** 新建一個ConnectionHolder對象,其內部保存這獲取的連接,* 將使用SimpleConnectionHandle包裝獲取的連接并且設置為connectionHandle屬性** 該ConnectionHolder被設置給txObject的connectionHolder屬性* 以及將newConnectionHolder屬性設置為true,表示是一個新連接** 到這里,事務對象就已經獲得了一個新連接*/txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}//獲取事務對象的連接持有者,將synchronizedWithTransaction設置為true,即資源標記為與事務同步。txObject.getConnectionHolder().setSynchronizedWithTransaction(true);//獲取內部保存的連接con = txObject.getConnectionHolder().getConnection();/** 使用給定的事務語義準備給定的Connection,就是設置數(shù)據(jù)庫事務的隔離級別,只讀標志屬性** 如果我們配置的隔離級別屬性是ISOLATION_DEFAULT,即采用默認隔離級別,或者不是默認的隔離級別但是與連接的隔離級別一致,那么將返回null* 否則將返回從連接中直接獲取的隔離級別(如果有)*/Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);//此前的隔離級別設置給事務對象的previousIsolationLevel屬性txObject.setPreviousIsolationLevel(previousIsolationLevel);// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,// so we don't want to do it unnecessarily (for example if we've explicitly// configured the connection pool to set it already).//如有必要,切換為手動提交。//從Druid數(shù)據(jù)源中獲取的連接DruidPooledConnection就是默認自動提交,即getAutoCommit返回trueif (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);if (logger.isDebugEnabled()) {logger.debug("Switching JDBC Connection [" + con + "] to manual commit");}/** 如果上面判斷是自動提交,那么切換為手動提交,為什么呢?如果不手動提交,* 那么一個方法中執(zhí)行多個sql語句時將會每執(zhí)行一個提交一次,無法實現(xiàn)事務的控制* 開啟手動提交就能實現(xiàn)方法級別的整體事務控制** 并且,開啟手動提交時,將會自動開啟事物*/con.setAutoCommit(false);}//事務已經開啟,此后的sql語句,如果沒有手動commit,那么將不會真正的提交給數(shù)據(jù)庫//用戶本次對數(shù)據(jù)庫開始進行操作到用戶執(zhí)行commit命令之間的一系列操作為一個完整的事務周期。/*** 事務開始后立即準備事務連接,主要是對于只讀事務的優(yōu)化操作(需要手動開啟)* 如果將"enforceReadOnly"標志設置為true(默認為false),并且事務定義指示只讀事務,* 則默認實現(xiàn)將執(zhí)行"SET TRANSACTION READ ONLY"這一個sql語句。* 請注意mysql只讀事務不要開啟,oracle的只讀事務可以開啟*/prepareTransactionalConnection(con, definition);//設置事務ConnectionHolder的transactionActive屬性為true,表示激活當前連接的事務//此前判斷是否有開啟事務的isExistingTransaction方法就會判斷這個屬性txObject.getConnectionHolder().setTransactionActive(true);//設置實際超時時間int timeout = determineTimeout(definition);//如果不是默認超時時間-1,那么將if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {//那么設置超時時間,實際上就是根據(jù)設置的值和當前時間轉換為未來的毫秒值并創(chuàng)建新Date配置給deadline屬性//在其他數(shù)據(jù)庫操作框架操作時將會獲取該參數(shù)txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}// Bind the connection holder to the thread.//如果是新的連接持有者,即newConnectionHolder屬性為trueif (txObject.isNewConnectionHolder()) {//綁定ConnectionHolder資源到TransactionSynchronizationManager的resources屬性中//key就是當前的屬性源,value就是ConnectionHolderTransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());}}catch (Throwable ex) {//如果是新連接,那么釋放鏈接if (txObject.isNewConnectionHolder()) {DataSourceUtils.releaseConnection(con, obtainDataSource());txObject.setConnectionHolder(null, false);}throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);}}
    • prepareConnectionForTransaction準備事務連接

    使用給定的事務語義準備給定的Connection,就是將我們設置的隔離級別isolationLevel,只讀標志readOnly屬性賦給當前事務連接。如果我們配置的隔離級別屬性是ISOLATION_DEFAULT,即采用默認隔離級別,或者不是默認的隔離級別但是與連接的隔離級別一致,那么將返回null,否則將設置連接的隔離級別為指定的級別,并且返回從連接中獲取的隔離級別(如果有)。

    /*** DataSourceUtils的方法* <p>* 使用給定的事務語義準備給定的Connection。** @param con 需要準備的連接* @param definition 適用的事務定義* @return 連接先前的隔離級別,可能為null*/ @Nullable public static Integer prepareConnectionForTransaction(Connection con, @Nullable TransactionDefinition definition)throws SQLException {Assert.notNull(con, "No Connection specified");boolean debugEnabled = logger.isDebugEnabled();// 設置只讀標志。if (definition != null && definition.isReadOnly()) {try {if (debugEnabled) {logger.debug("Setting JDBC Connection [" + con + "] read-only");}//設置連接只讀屬性con.setReadOnly(true);} catch (SQLException | RuntimeException ex) {Throwable exToCheck = ex;while (exToCheck != null) {if (exToCheck.getClass().getSimpleName().contains("Timeout")) {// Assume it's a connection timeout that would otherwise get lost: e.g. from JDBC 4.0throw ex;}exToCheck = exToCheck.getCause();}// "read-only not supported" SQLException -> ignore, it's just a hint anywaylogger.debug("Could not set JDBC Connection read-only", ex);}}// 應用特定的隔離級別(如果有)。Integer previousIsolationLevel = null;//如果存在隔離級別并且不等于默認配置,即不等于ISOLATION_DEFAULT(該級別的意思是使用數(shù)據(jù)庫的默認級別)if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {if (debugEnabled) {logger.debug("Changing isolation level of JDBC Connection [" + con + "] to " +definition.getIsolationLevel());}//獲取當前連接的隔離級別int currentIsolation = con.getTransactionIsolation();//如果手動設置的隔離級別不等于連接的隔離級別if (currentIsolation != definition.getIsolationLevel()) {//記錄連接的隔離級別previousIsolationLevel = currentIsolation;//連接的隔離級別手動設置為我們配置的隔離級別con.setTransactionIsolation(definition.getIsolationLevel());}}//返回此前的連接的隔離級別,可能為nullreturn previousIsolationLevel; }
    • prepareTransactionalConnection優(yōu)化只讀事務
      ??事務開始后立即準備事務連接,主要是對于只讀事務的優(yōu)化操作(需要手動開啟)。如果將事務管理器的"enforceReadOnly"標志設置為true(默認為false),并且事務定義指示只讀事務,則默認實現(xiàn)將執(zhí)行"SET TRANSACTION READ ONLY"這一個sql語句。
      ??"SET TRANSACTION READ ONLY"這個sql的意思就是告訴數(shù)據(jù)庫,此事務中的后續(xù)sql語句將只有查詢操作,不能進行DML操作。在"SET TRANSACTION READ ONLY"之后的查詢語句將不會查詢到該事物期間提交的內容,只能查詢到事務開始之前提交的內容,相當于查詢一個快照。進行只讀事務設置之后,將有效減輕數(shù)據(jù)庫壓力。對于同一個表進行更新操作時,只讀事務不會被阻塞,可以正常的執(zhí)行查詢操作,在只讀事務操作期間也不會影響其他事務!
    /*** DataSourceTransactionManager的方法* 如果將"enforceReadOnly"標志設置為true,并且事務定義指示只讀事務,* 則默認實現(xiàn)將執(zhí)行"SET TRANSACTION READ ONLY"sql語句。** @param con 當前連接* @param definition 為當前方法配置的事務定義*/ protected void prepareTransactionalConnection(Connection con, TransactionDefinition definition)throws SQLException {//如果將"enforceReadOnly"標志設置為true,并且事務定義指示只讀事務if (isEnforceReadOnly() && definition.isReadOnly()) {//那么獲取Statement,并且執(zhí)行"SET TRANSACTION READ ONLY"sql語句try (Statement stmt = con.createStatement()) {stmt.executeUpdate("SET TRANSACTION READ ONLY");}} }/*** DataSourceTransactionManager的屬性* <p>* 表示是否通過對事務連接顯式執(zhí)行sql語句強制執(zhí)行事務的只讀性質,默認為false*/ private boolean enforceReadOnly = false;/*** 返回是否通過對事務連接顯式執(zhí)行sql語句強制執(zhí)行事務的只讀性質。*/ public boolean isEnforceReadOnly() {return this.enforceReadOnly; }

    上面說了這么多好處,很遺憾的是DataSourceTransactionManager的enforceReadOnly屬性默認為false,并且大部分開發(fā)者也不知道這個優(yōu)化,因此大多數(shù)情況下并不會執(zhí)行該sql語句,即不會進行優(yōu)化。如果要開啟,那么可以這么設置:

    /*** 配置DataSourceTransactionManager* 用于管理某一個數(shù)據(jù)庫的事務*/ @Bean public DataSourceTransactionManager transactionManager() {DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(druidDataSource());//設置只讀事務優(yōu)化dataSourceTransactionManager.setEnforceReadOnly(true);//傳入一個數(shù)據(jù)源return dataSourceTransactionManager; }

    當然如果你真的這么開啟了,并且你通過@Transactional注解設置了某個方法的事務的readOnly屬性為true,那么確實會執(zhí)行該方法,但是你講將會收到一個異常:“Connection is read-only. Queries leading to data modification are not allowed”。原因是什么呢?很簡單,在前面的prepareConnectionForTransaction方法中,連接被設置為只讀,然而在隨后的prepareTransactionalConnection方法中,執(zhí)行該sql語句的卻是executeUpdate方法,自然會拋出異常!所以說,這個優(yōu)化還不能隨便開。或者說,是因為不同的數(shù)據(jù)庫對于Spring的readOnly屬性的支持是不一樣的,mysql支持Spring的readOnly參數(shù),即支持JDBC的con.setReadOnly(true),因此就沒必要再設置enforceReadOnly為true,而oracle則僅支持在Oracle server的設置而非JDBC驅動的配置,因此不支持con.setReadOnly(true),所以實際上Spring的readOnly配置對于Oracle無效,所以Oracle數(shù)據(jù)庫可以開啟此優(yōu)化,mysql則不必要。

    • determineTimeout確定超時時間

    確定給定事務定義的實際超時時間。如果事務定義未指定非默認值,則將使用默認超時。

    /*** AbstractPlatformTransactionManager的方法* <p>* 確定給定事務定義的實際超時時間。* 如果事務定義未指定非默認值,則將使用默認超時。** @param definition 事務定義* @return 實際使用的超時時間*/ protected int determineTimeout(TransactionDefinition definition) {//如果不是默認超時時間,那么使用指定的事件if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {return definition.getTimeout();}//否則使用默認超時return getDefaultTimeout(); }/*** AbstractPlatformTransactionManager的屬性* <p>* 默認超時時間(秒),默認值為-1,表示使用基礎事務系統(tǒng)的默認超時;*/ private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT;public final int getDefaultTimeout() {return this.defaultTimeout; }
    • setTimeoutInSeconds設置超時deadline

    這里實際上就是根據(jù)設置的值和當前時間轉換為未來的毫秒值并創(chuàng)建新Date配置給deadline屬性,在其他數(shù)據(jù)庫操作框架具體操作時將會獲取并應用該參數(shù)。比如mybatis,在執(zhí)行sql之前會獲取到超時時間,計算之后會通過Statement.setQueryTimeout方法來設置,也就是說這個超時時間是執(zhí)行sql之前的代碼執(zhí)行時間+sql執(zhí)行時間,如果執(zhí)行時間超過了設置時間就會拋出異常,這個異常就會被spring事務切面捕獲到最終導致事務回滾,而如果在sql執(zhí)行完畢之后的方法處理時間超過了這個超時時間,那么是不會進行回滾的,事務將會正常提交。

    /*** ConnectionHolder的父類ResourceHolderSupport的方法* <p>* 設置此對象的超時(以秒為單位)。** @param seconds 到期前的秒數(shù)*/ public void setTimeoutInSeconds(int seconds) {setTimeoutInMillis(seconds * 1000L); }/*** ConnectionHolder的父類ResourceHolderSupport的屬性*/ @Nullable private Date deadline;/*** 設置此對象的超時(以毫秒為單位)。** @param millis 到期前的毫秒數(shù)*/ public void setTimeoutInMillis(long millis) {//根據(jù)當前時間和超時時間計算出到期的Datethis.deadline = new Date(System.currentTimeMillis() + millis); }
    • bindResource綁定資源到resources

    對于新獲取的連接資源會被綁定到TransactionSynchronizationManager的resources線程本地變量屬性中(resources我們在此前就見過了)。key就是當前的屬性源DataSource,value就是ConnectionHolder。

    /*** 事務資源*/ private static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");/*** TransactionSynchronizationManager的方法* <p>* 將給定key的給定資源value綁定到當前線程。* 對于DataSourceTransactionManager,key就是DataSource實例,value就是ConnectionHolder** @param key 將值綁定到的鍵(通常是資源工廠,比如dataSource)* @param value 要綁定的值(通常是活動資源對象,比如數(shù)據(jù)庫連接)* @throws IllegalStateException 如果已經有綁定到線程的值*/ public static void bindResource(Object key, Object value) throws IllegalStateException {Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);Assert.notNull(value, "Value must not be null");//獲取當前線程的本地資源mapMap<Object, Object> map = resources.get();//如果找不到,則設置一個Mapif (map == null) {map = new HashMap<>();resources.set(map);}//將actualKey和value存入map中,返回舊的valueObject oldValue = map.put(actualKey, value);// Transparently suppress a ResourceHolder that was marked as void...if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {oldValue = null;}//如果已經有綁定到線程的當前key的值,則拋出異常if (oldValue != null) {throw new IllegalStateException("Already value [" + oldValue + "] for key [" +actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");}if (logger.isTraceEnabled()) {logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +Thread.currentThread().getName() + "]");} }
    • prepareSynchronization準備事務同步
      ??
      該方法通常用在doBegin開啟新事物之后,用于準備事務同步,就是將當前事務的一系列屬性綁定到TransactionSynchronizationManager的對應的線程本地變量中。
    /*** AbstractPlatformTransactionManager的方法* <p>* 適當?shù)爻跏蓟聞胀健?/ protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {//是否是新同步,在真正的開啟新事務的時候(比如第一次進入事務方法或者傳播行為是REQUIRES_NEW),一般都是trueif (status.isNewSynchronization()) {//配置當前事務的一系列屬性//是否具有事務TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());//傳播行為TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?definition.getIsolationLevel() : null);//只讀狀態(tài)TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());//事務名TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());//初始化同步TransactionSynchronizationManager.initSynchronization();} }private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =new NamedThreadLocal<>("Transaction synchronizations");/*** TransactionSynchronizationManager的方法* <p>* 激活當前線程的事務同步。由事務管理器在事務開始時調用。** @throws IllegalStateException 如果同步已處于活動狀態(tài)*/ public static void initSynchronization() throws IllegalStateException {//如果同步已處于活動狀態(tài),即synchronizations保存的線程本地變量不為null,則拋出異常if (isSynchronizationActive()) {throw new IllegalStateException("Cannot activate transaction synchronization - already active");}logger.trace("Initializing transaction synchronization");//否則就為當前初始化一個線程本地變量,這是一個空的LinkedHashSet//雖然沒有任何的TransactionSynchronization,但是已經不為null了synchronizations.set(new LinkedHashSet<>()); }
    • prepareTransactionStatus準備事務狀態(tài)
    • prepareTransactionStatus方法和上面的startTransaction方法相比,其內部會調用newTransactionStatus和prepareSynchronization,但不會調用doBegin方法,因此不會真正的開啟事物。返回的TransactionStatus,其內部保存了其他的資源,比如被掛起的事務信息。
    • 如果是第一次進入事務方法,即當前方法是最外層事務方法,并且傳播行為是PROPAGATION_SUPPORTS或PROPAGATION_NEVER或PROPAGATION_NOT_SUPPORTED,那么會調用該方法,它的newTransaction參數(shù)為false,suspendedResources參數(shù)為null。即這些傳播行為都不會真正的開啟數(shù)據(jù)庫級別的事務(不會獲取新的連接)。
    • 如果是已存在外層事務,即當前方法是內層事務方法,并且傳播行為是PROPAGATION_NOT_SUPPORTED或者PROPAGATION_NESTED或者PROPAGATION_SUPPORTS或者PROPAGATION_REQUIRED或者PROPAGATION_MANDATORY,那么也有可能調用這個方法,它的newTransaction參數(shù)為false,suspendedResources參數(shù)為被掛起的外層事務資源。即這些傳播行為都不會真正的開啟數(shù)據(jù)庫級別的事務(不會獲取新的連接,對于普通事物來說)。
    /**1. 根據(jù)給定參數(shù)創(chuàng)建一個新的TransactionStatus,并在適當時初始化事務同步,不會真正開啟新事物。2. 3. @param definition 為當前方法設置的事務定義4. @param transaction 當前已存在的事務5. @param newTransaction 是否是新事物,如果是外層事務方法,則為true,如果是內層方法則為false6. @param newSynchronization 是否是新事務同步7. @param debug 是否支持debug日志8. @param suspendedResources 被掛起的資源9. @return 一個TransactionStatus的實現(xiàn)*/ protected final DefaultTransactionStatus prepareTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {//通過newTransactionStatus創(chuàng)建一個DefaultTransactionStatusDefaultTransactionStatus status = newTransactionStatus(definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);//中間缺少了doBegin真正開啟事務的訪法,所以僅僅是創(chuàng)建了一個簡單的TransactionStatus//包存了一些其他信息,比如被掛起的資源信息//準備事務同步prepareSynchronization(status, definition);return status;

    }

    • 如果當前已存在事務,則handleExistingTransaction處理已存在事務
      ??
      如果進入事務切面之后,獲取到了已存在的連接并且開啟了事務(通過isExistingTransaction方法判斷),那么將會執(zhí)行handleExistingTransaction方法執(zhí)行已存在事務時的邏輯,并返回一個TransactionStatus。該方法同樣將會根據(jù)此事務切面設置的事務傳播行為走不同的執(zhí)行流程,比如加入當前事務、新建事務、拋出異常等等邏輯。
      ??大概邏輯是:
  • 如果當前配置的傳播行為是PROPAGATION_NEVER,該行為的特點是:當前方法一定以非事務的方式運行,并且如果當前存在事務,則直接拋出異常,所以這里由于存在外部事務,那么直接拋出異常:“Existing
    transaction found for transaction marked with propagation ‘never’”。
  • 如果當前配置的傳播行為是PROPAGATION_NOT_SUPPORTED,該行為的特點是:當前方法一定以非事務的方式運行,如果當前存在事務,則把當前事務掛起,直到當前方法執(zhí)行完畢,才恢復外層事務。
      • 首先調用suspend方法掛起外層事務,返回被掛起的資源。由于存在外層事務,所以這里的參數(shù)就是獲取的外層事務參數(shù)。
      • 隨后調用prepareTransactionStatus方法返回一個新的TransactionStatus,并在適當時初始化事務同步。同樣,該方法和上面的startTransaction方法相比,其內部會調用newTransactionStatus和prepareSynchronization,但不會調用doBegin方法,因此不會真正的開啟事物。這里它的newTransaction參數(shù)為false,transaction參數(shù)為null,suspendedResources參數(shù)為被掛起的外層事務資源。
  • 如果當前配置的傳播行為是PROPAGATION_REQUIRES_NEW,該行為的特點是:當前方法開啟一個新事物獨立運行,從不參與外部的現(xiàn)有事務。則當內部事務開始執(zhí)行時,外部事務(如果存在)將被掛起,內務事務結束時,外部事務將繼續(xù)執(zhí)行。
      • 首先調用suspend方法掛起外層事務,返回被掛起的資源。由于存在外層事務,所以這里的參數(shù)就是獲取的外層事務參數(shù)。
      • 隨后調用startTransaction方法真正的開啟一個數(shù)據(jù)庫級別的事務(將會獲取新的連接開啟一個新事物,舊的連接和事務則在上面的suspend方法中被掛起保存)。
  • 如果當前配置的傳播行為是PROPAGATION_NESTED,該行為的特點是:
    如果當前存在事務,則創(chuàng)建一個新“事務”作為當前事務的嵌套事務來運行;如果當前沒有事務,則等價于PROPAGATION_REQUIRED,即會新建一個事務運行。
      • 調用isNestedTransactionAllowed方法判斷是否允許PROPAGATION_NESTED行為,默認不允許,但是DataSourceTransactionManager重寫為允許。不允許就拋出異常:“Transaction manager does not allow nested transactions……”。
      • 調用useSavepointForNestedTransaction方法判斷是否對“嵌套事務”使用保存點Savepoint來實現(xiàn):
        • 如果允許,那么首先調用prepareTransactionStatus方法返回一個新的TransactionStatus,并在適當時初始化事務同步。這里它的newTransaction參數(shù)為false,transaction參數(shù)為外層事務,suspendedResources參數(shù)為null,newSynchronization參數(shù)為false。隨后調用createAndHoldSavepoint創(chuàng)建保存點,將使用數(shù)據(jù)庫的保存點的特性來實現(xiàn)“嵌套事務”,這是用語大部分普通事務。
        • 否則將調用startTransaction方法通過在外層事務中嵌套的begin和commit/rollback調用來開啟真正的嵌套事務,不過通常僅用于JTA:如果存在預先存在的JTA事務,則可以在此處激活Spring同步。
  • 剩下的傳播行為就是PROPAGATION_SUPPORTS或者PROPAGATION_REQUIRED或者PROPAGATION_MANDATORY,如果是這些行為,那么它們的一個共同的特性就是:參與到當前事務中去,也是默認傳播行為的邏輯。
      • 那么這里同樣調用prepareTransactionStatus方法,這里它的newTransaction參數(shù)為false,transaction參數(shù)為外層事務,suspendedResources參數(shù)為null。

    從源碼中我們能夠看到,如果傳播行為是PROPAGATION_NESTED:

  • 對于普通事務(比如DataSourceTransactionManager處理的事務),它的“嵌套事務”是通過SavePoint保存點來實現(xiàn)的,實際上就是同一個事務。基于保存點的特性,此時,“內層事務”依賴“外層事物”:層事務操作失敗時只是自身回到到保存點的位置,不會引起外層事務的回滾,而外層事務因失敗而回滾時,內層事務所做的所有動作也會回滾。在提交時,在外層事務提交之后內層事務才能提交,僅需要提交外層事務即可。由于實際上只有一個物理事務,那么內層事務會繼承外層外層事務的隔離級別和超時設置等屬性。
  • 對于JTA事務(分布式事務),我們能看到是調用了startTransaction方法,因此將會在原本的事務中通過嵌套的begin和commit/rollback調用來開啟的嵌套事務,這是真正的嵌套事務。
  • /*** AbstractPlatformTransactionManager的方法* <p>* 根據(jù)現(xiàn)有事務創(chuàng)建一個TransactionStatus,處理事務的傳播行為** @param definition 當前事務定義* @param transaction 事物對象,內部包含此前的事務信息* @param debugEnabled 日志級別支持* @return 事務狀態(tài)對象*/ private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)throws TransactionException {/** 1 如果當前配置的傳播行為是PROPAGATION_NEVER,該行為的特點是:* 當前方法一定以非事務的方式運行,并且如果當前存在事務,則直接拋出異常* 所以這里直接拋出異常*/if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}/** 2 如果當前配置的傳播行為是PROPAGATION_NOT_SUPPORTED,該行為的特點是:* 當前方法一定以非事務的方式運行,如果當前存在事務,則把當前事務掛起,直到當前方法執(zhí)行完畢,才恢復外層事務。*/if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {if (debugEnabled) {logger.debug("Suspending current transaction");}//那么這里掛起外層事務Object suspendedResources = suspend(transaction);//判斷是否需要進行新同步,默認都是需要的boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);//為給定參數(shù)創(chuàng)建一個新的TransactionStatus,并在適當時初始化事務同步。//這里的第二個參數(shù)事務屬性為null,表示當前方法以非事務的方式執(zhí)行return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);}/** 3 如果當前配置的傳播行為是PROPAGATION_REQUIRES_NEW,該行為的特點是:* 當前方法開啟一個新事物獨立運行,從不參與外部的現(xiàn)有事務。則當內部事務開始執(zhí)行時,* 外部事務(如果存在)將被掛起,內務事務結束時,外部事務將繼續(xù)執(zhí)行。*/if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {if (debugEnabled) {logger.debug("Suspending current transaction, creating new transaction with name [" +definition.getName() + "]");}//那么這里掛起外層事務,返回被掛起的資源SuspendedResourcesHolder suspendedResources = suspend(transaction);try {//開啟一個新事務并返回return startTransaction(definition, transaction, debugEnabled, suspendedResources);} catch (RuntimeException | Error beginEx) {//恢復被掛起的事務resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;}}/** 4 如果當前配置的傳播行為是PROPAGATION_NESTED,該行為的特點是:* 如果當前存在事務,則創(chuàng)建一個新“事務”作為當前事務的嵌套事務來運行;* 如果當前沒有事務,則等價于PROPAGATION_REQUIRED,即會新建一個事務運行。**/if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {//判斷是否允許PROPAGATION_NESTED行為,默認不允許,但是DataSourceTransactionManager重寫為為允許if (!isNestedTransactionAllowed()) {throw new NestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - " +"specify 'nestedTransactionAllowed' property with value 'true'");}if (debugEnabled) {logger.debug("Creating nested transaction with name [" + definition.getName() + "]");}//返回是否對嵌套事務使用保存點,默認true,JtaTransactionManager設置為false//PROPAGATION_NESTED就是通過Savepoint保存點來實現(xiàn)的if (useSavepointForNestedTransaction()) {//并沒有掛起當前事務,創(chuàng)建TransactionStatus,transaction參數(shù)就是當前事務DefaultTransactionStatus status =prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);/** 通過TransactionStatus實現(xiàn)的SavepointManager API在現(xiàn)有的Spring管理的事務中創(chuàng)建保存點,通常使用JDBC 3.0保存點。*/status.createAndHoldSavepoint();return status;} else {// 通過在事務中嵌套的begin和commit / rollback調用開啟的嵌套事務。// 通常僅用于JTA:如果存在預先存在的JTA事務,則可以在此處激活Spring同步。return startTransaction(definition, transaction, debugEnabled, null);}}//剩下的傳播行為就是PROPAGATION_SUPPORTS或者PROPAGATION_REQUIRED或者PROPAGATION_MANDATORY。if (debugEnabled) {logger.debug("Participating in existing transaction");}//是否在參與現(xiàn)有事務之前進行驗證,默認falseif (isValidateExistingTransaction()) {if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {Constants isoConstants = DefaultTransactionDefinition.constants;throw new IllegalTransactionStateException("Participating transaction with definition [" +definition + "] specifies isolation level which is incompatible with existing transaction: " +(currentIsolationLevel != null ?isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :"(unknown)"));}}if (!definition.isReadOnly()) {if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {throw new IllegalTransactionStateException("Participating transaction with definition [" +definition + "] is not marked as read-only but existing transaction is");}}}//并沒有掛起當前事務,而是直接參與到當前事務中去,transaction參數(shù)就是當前的事務boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); }
    • createAndHoldSavepoint創(chuàng)建保存點

    該方法很簡單,最終會調用當前的JDBC連接Connection的setSavepoint方法創(chuàng)建一個保存點,并且被設置給當前TransactionStatus對象的savepoint屬性。

    /*** AbstractTransactionStatus的方法* <p>* 創(chuàng)建一個保存點并將其保存在事務中。** @throws NestedTransactionNotSupportedException 如果基礎事務不支持保存點*/ public void createAndHoldSavepoint() throws TransactionException {setSavepoint(getSavepointManager().createSavepoint()); } /*** AbstractTransactionStatus的屬性*/ @Nullable private Object savepoint;/*** AbstractTransactionStatus的方法* <p>* 設置此事務的保存點,對PROPAGATION_NESTED有用。*/ protected void setSavepoint(@Nullable Object savepoint) {this.savepoint = savepoint; }

    getSavepointManager獲取獲取保存點管理器,實際上創(chuàng)建的內部事務對象都是SavepointManager接口的實現(xiàn),具有獲取保存點的方法!因此返回的實際上就是內部的事務對象,對于DataSourceTransactionManager來說創(chuàng)建的內部事務就是DataSourceTransactionObject。

    /*** DefaultTransactionStatus的屬性* <p>* 獲取基礎事務對象的SavepointManager,實際上就是獲取的內部事務對象*/ @Nullable private final Object transaction;/*** DefaultTransactionStatus的方法* <p>* 獲取基礎事務對象的SavepointManager,實際上就是獲取的內部事務對象*/ @Override protected SavepointManager getSavepointManager() {//獲取內部事務,對于DataSourceTransactionManager來說創(chuàng)建的內部事務就是DataSourceTransactionObjectObject transaction = this.transaction;if (!(transaction instanceof SavepointManager)) {throw new NestedTransactionNotSupportedException("Transaction object [" + this.transaction + "] does not support savepoints");}return (SavepointManager) transaction; }

    createSavepoint用于從當前保存點管理器(事務對象)中創(chuàng)建一個保存點,實際上就是獲取事務對象里面的ConnectionHolder,然后在獲取ConnectionHolder里面的Connection,最后調用Connection.setSavepoint方法創(chuàng)建并獲取保存點。

    /*** DataSourceTransactionObject的父類JdbcTransactionObjectSupport的方法* <p>* 創(chuàng)建一個JDBC 3.0保存點并返回它。*/ @Override public Object createSavepoint() throws TransactionException {//校驗規(guī)則并獲取,此前創(chuàng)建的ConnectionHolder,其內部保存了獲取的連接ConnectionConnectionHolder conHolder = getConnectionHolderForSavepoint();try {//如果不允許保存點,那么拋出異常,默認允許if (!conHolder.supportsSavepoints()) {throw new NestedTransactionNotSupportedException("Cannot create a nested transaction because savepoints are not supported by your JDBC driver");}//如果被設置為僅回滾,那么拋出異常if (conHolder.isRollbackOnly()) {throw new CannotCreateTransactionException("Cannot create savepoint for transaction which is already marked as rollback-only");}return conHolder.createSavepoint();} catch (SQLException ex) {throw new CannotCreateTransactionException("Could not create JDBC savepoint", ex);} }/*** DataSourceTransactionObject的父類JdbcTransactionObjectSupport的方法* <p>* 為了創(chuàng)建一個JDBC 3.0保存而獲取ConnectionHolder。*/ protected ConnectionHolder getConnectionHolderForSavepoint() throws TransactionException {//如果不允許保存點,那么拋出異常,默認允許if (!isSavepointAllowed()) {throw new NestedTransactionNotSupportedException("Transaction manager does not allow nested transactions");}//如果沒有ConnectionHolder,那么拋出異常,默認允許if (!hasConnectionHolder()) {throw new TransactionUsageException("Cannot create nested transaction when not exposing a JDBC transaction");}//返回此前創(chuàng)建的ConnectionHolder,其內部保存了獲取的連接return getConnectionHolder(); }//ConnectionHolder的方法的屬性/*** 保存點名稱的前綴。*/ public static final String SAVEPOINT_NAME_PREFIX = "SAVEPOINT_";/*** 從此連接中獲取的保存點的數(shù)量*/ private int savepointCounter = 0;/*** ConnectionHolder的方法* 為當前連接創(chuàng)建一個新的JDBC 3.0保存點,只用SAVEPOINT_+savepointCounter作為保存點的名稱** @return 新的保存點* @throws SQLException if thrown by the JDBC driver*/ public Savepoint createSavepoint() throws SQLException {//獲取數(shù)量自增1this.savepointCounter++;//獲取內部的JDBC連接,并通過連接設置一個保存點,返回創(chuàng)建的Savepointreturn getConnection().setSavepoint(SAVEPOINT_NAME_PREFIX + this.savepointCounter); }

    四、小結

  • createTransactionIfNecessary方法創(chuàng)建并返回一個TransactionInfo對象,并且在此過程中,將會調用getTransaction方法獲取事務TransactionStatus。

  • getTransaction方法就是Spring事務處理的核心方法之一,該方法根據(jù)配置的各種事務傳播行為以及是否存在外層事務做出不同的處理,方法執(zhí)行完畢將可能開啟了新事物,也可能沒有開啟,甚至拋出異常。

  • TransactionInfo內部保存了事務管理器transactionManager、事務屬性transactionAttribute、全路徑方法名joinpointIdentification。還保存了當前方法的事務transactionStatus,以及前一個方法的事務信息對象oldTransactionInfo。

  • TransactionStatus實際類型為DefaultTransactionStatus,它持有一個transaction內部事務對象、被掛起的事務資源以及一些事務的屬性,這個內部事務對象由事務管理器的實現(xiàn)各自創(chuàng)建,不同的事務管理器將會創(chuàng)建不同的類型,因此使用Object來表示,對于DataSourceTransactionManager來說,它創(chuàng)建的事務對象就是DataSourceTransactionObject。

  • DataSourceTransactionObject內部持有一個ConnectionHolder對象以及一些事務的屬性,ConnectionHolder對象內部持有一個為了配置數(shù)據(jù)庫事務而獲取的JDBC連接Connection,以及是否開啟了事務的標志transactionActive,以及其他屬性,比如保存點計數(shù)。

  • 最終,我們?yōu)槟硞€方法定義的事務屬性,除了傳播行為之外(Spring提供的特性并自行處理),都會反應到Connection的對應操作上,比如隔離級別、超時時間,是否只讀等等,關鍵方法就是doBegin,該方法用于真正的開啟數(shù)據(jù)庫層面的事務。

  • 我們用了很長的文章講解了createTransactionIfNecessary方法的邏輯和源碼,這是Spring 事務開啟的核心處理方法(可能并未真正的開啟事務),剩下的方法比如proceedWithInvocation、completeTransactionAfterThrowing、cleanupTransactionInfo、commitTransactionAfterReturning就是在開啟事物之后的處理方法,比如回滾、提交、恢復事務等等。

  • 參考文章

    總結

    以上是生活随笔為你收集整理的Spring TX源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    少妇被粗大的猛进出69影院 | 国产办公室秘书无码精品99 | 中文字幕中文有码在线 | 亚洲精品一区二区三区在线 | a在线观看免费网站大全 | 久久这里只有精品视频9 | 免费人成网站视频在线观看 | 综合网日日天干夜夜久久 | 久久亚洲日韩精品一区二区三区 | av无码不卡在线观看免费 | a在线亚洲男人的天堂 | 日本成熟视频免费视频 | 亚洲欧洲无卡二区视頻 | 国内揄拍国内精品人妻 | 欧美日韩一区二区免费视频 | 无码成人精品区在线观看 | 在教室伦流澡到高潮hnp视频 | 亚洲欧美精品aaaaaa片 | 国产又爽又黄又刺激的视频 | 久久国产精品偷任你爽任你 | 亚洲精品一区二区三区在线观看 | 青春草在线视频免费观看 | 亚洲欧美精品伊人久久 | 婷婷五月综合激情中文字幕 | 久久综合网欧美色妞网 | 东京热无码av男人的天堂 | 亚洲国产精品无码久久久久高潮 | 国产小呦泬泬99精品 | 久久久av男人的天堂 | 精品偷自拍另类在线观看 | 妺妺窝人体色www在线小说 | 999久久久国产精品消防器材 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 青青草原综合久久大伊人精品 | 久久97精品久久久久久久不卡 | 日日碰狠狠丁香久燥 | 成 人影片 免费观看 | 欧美性猛交内射兽交老熟妇 | 国产在线精品一区二区高清不卡 | 亚洲综合久久一区二区 | 麻豆精品国产精华精华液好用吗 | 久久婷婷五月综合色国产香蕉 | 日韩人妻无码中文字幕视频 | 国产精品久久精品三级 | 纯爱无遮挡h肉动漫在线播放 | 国产成人综合美国十次 | 久久99精品国产麻豆蜜芽 | 人妻少妇精品无码专区二区 | 欧美刺激性大交 | 亚洲人亚洲人成电影网站色 | 大肉大捧一进一出视频出来呀 | 性做久久久久久久久 | 国产特级毛片aaaaaa高潮流水 | 台湾无码一区二区 | 久久亚洲中文字幕精品一区 | 天天av天天av天天透 | 中文字幕无码免费久久99 | 性啪啪chinese东北女人 | 福利一区二区三区视频在线观看 | 国产超碰人人爽人人做人人添 | 久久亚洲中文字幕无码 | 伊人色综合久久天天小片 | 亚洲欧美日韩综合久久久 | 国产欧美亚洲精品a | 精品人妻人人做人人爽 | 久久99精品国产.久久久久 | 亚洲阿v天堂在线 | 大肉大捧一进一出好爽视频 | 性色欲网站人妻丰满中文久久不卡 | 亚洲一区二区三区无码久久 | 日韩亚洲欧美精品综合 | 亚洲国产精品久久人人爱 | 狠狠色欧美亚洲狠狠色www | 国产精品爱久久久久久久 | 成年美女黄网站色大免费全看 | 国产精品怡红院永久免费 | 美女张开腿让人桶 | 亚洲狠狠婷婷综合久久 | 国产偷自视频区视频 | 日韩精品乱码av一区二区 | 人人妻人人澡人人爽欧美一区九九 | 国产办公室秘书无码精品99 | av在线亚洲欧洲日产一区二区 | 澳门永久av免费网站 | 午夜精品一区二区三区在线观看 | 国产莉萝无码av在线播放 | 久久伊人色av天堂九九小黄鸭 | 国产色xx群视频射精 | 国产人妻大战黑人第1集 | 国内老熟妇对白xxxxhd | 国产精品无码久久av | 精品无码国产一区二区三区av | 亚洲欧美日韩国产精品一区二区 | 欧美日韩人成综合在线播放 | 国产成人无码a区在线观看视频app | 内射爽无广熟女亚洲 | 久久久久久a亚洲欧洲av冫 | 丰满肥臀大屁股熟妇激情视频 | 婷婷六月久久综合丁香 | 久久熟妇人妻午夜寂寞影院 | 国产av人人夜夜澡人人爽麻豆 | 一本大道伊人av久久综合 | 中文无码成人免费视频在线观看 | 国精产品一区二区三区 | 欧美午夜特黄aaaaaa片 | 国产av无码专区亚洲awww | 中文字幕无码视频专区 | 国产精品18久久久久久麻辣 | 男女下面进入的视频免费午夜 | 国产午夜精品一区二区三区嫩草 | 成人aaa片一区国产精品 | 精品乱子伦一区二区三区 | 丰满护士巨好爽好大乳 | 日韩人妻系列无码专区 | 精品欧美一区二区三区久久久 | 亚洲人成影院在线无码按摩店 | 国产偷国产偷精品高清尤物 | 中文字幕无码av波多野吉衣 | 日韩精品成人一区二区三区 | 熟女体下毛毛黑森林 | 午夜福利电影 | 成熟女人特级毛片www免费 | 丰满少妇弄高潮了www | 性欧美熟妇videofreesex | 99er热精品视频 | 亚洲一区av无码专区在线观看 | 亚洲成av人影院在线观看 | 国产片av国语在线观看 | 99久久无码一区人妻 | 亚洲人成网站在线播放942 | 天堂在线观看www | 5858s亚洲色大成网站www | 熟妇人妻无码xxx视频 | 亚洲乱码中文字幕在线 | 四十如虎的丰满熟妇啪啪 | 亚洲欧洲无卡二区视頻 | 亚洲精品久久久久久久久久久 | 成人性做爰aaa片免费看不忠 | 亚洲成在人网站无码天堂 | 男人的天堂2018无码 | 亚洲精品久久久久久久久久久 | 国产综合在线观看 | 午夜福利试看120秒体验区 | 丝袜人妻一区二区三区 | 人妻无码αv中文字幕久久琪琪布 | 麻花豆传媒剧国产免费mv在线 | 久久这里只有精品视频9 | 亚洲人成人无码网www国产 | 久久无码专区国产精品s | 国产偷自视频区视频 | 中文字幕人妻无码一区二区三区 | 久久精品人妻少妇一区二区三区 | 人妻少妇精品无码专区动漫 | 久在线观看福利视频 | 一本色道久久综合亚洲精品不卡 | 97久久国产亚洲精品超碰热 | 人人妻人人澡人人爽精品欧美 | 亚洲午夜无码久久 | 东京热男人av天堂 | 久久久国产一区二区三区 | 欧美怡红院免费全部视频 | 成熟妇人a片免费看网站 | 天天做天天爱天天爽综合网 | 久久久久久亚洲精品a片成人 | 中文字幕人成乱码熟女app | 日韩人妻无码中文字幕视频 | 中文字幕av无码一区二区三区电影 | 中文字幕人妻无码一区二区三区 | 成人亚洲精品久久久久软件 | 玩弄少妇高潮ⅹxxxyw | 丰满妇女强制高潮18xxxx | 亚洲gv猛男gv无码男同 | 久久国内精品自在自线 | 中文无码伦av中文字幕 | 亚洲精品国偷拍自产在线观看蜜桃 | 娇妻被黑人粗大高潮白浆 | 久久久精品成人免费观看 | 日日天日日夜日日摸 | 亚洲 日韩 欧美 成人 在线观看 | 伊人久久大香线蕉av一区二区 | 性欧美videos高清精品 | 久久久久99精品成人片 | 国产精品久久久一区二区三区 | 日本护士xxxxhd少妇 | 国产成人无码av片在线观看不卡 | 少女韩国电视剧在线观看完整 | 窝窝午夜理论片影院 | 日韩少妇白浆无码系列 | 国产精品资源一区二区 | 欧美人与物videos另类 | 亚洲人成网站色7799 | 无码人中文字幕 | 在教室伦流澡到高潮hnp视频 | 亚洲一区二区三区含羞草 | 久久午夜夜伦鲁鲁片无码免费 | 亚洲色偷偷偷综合网 | 日本丰满护士爆乳xxxx | 成人一在线视频日韩国产 | 男女作爱免费网站 | 中文字幕av伊人av无码av | 特级做a爰片毛片免费69 | 免费人成在线观看网站 | 国产精品无码成人午夜电影 | 国产猛烈高潮尖叫视频免费 | 爽爽影院免费观看 | 国产成人av免费观看 | 精品国产青草久久久久福利 | v一区无码内射国产 | 性做久久久久久久免费看 | 人妻插b视频一区二区三区 | 日韩亚洲欧美中文高清在线 | 国产精品沙发午睡系列 | 日本爽爽爽爽爽爽在线观看免 | 国产真实伦对白全集 | 在线a亚洲视频播放在线观看 | 在线精品亚洲一区二区 | 人妻无码久久精品人妻 | 日本xxxx色视频在线观看免费 | 色婷婷av一区二区三区之红樱桃 | 久久国产36精品色熟妇 | 亚洲欧美精品伊人久久 | 67194成是人免费无码 | 国产小呦泬泬99精品 | 99久久久国产精品无码免费 | 国产精品亚洲一区二区三区喷水 | 国产美女精品一区二区三区 | 亚洲日韩乱码中文无码蜜桃臀网站 | 强伦人妻一区二区三区视频18 | 黑人大群体交免费视频 | 久久久久se色偷偷亚洲精品av | 色一情一乱一伦一视频免费看 | 国产无套粉嫩白浆在线 | 亚洲欧美中文字幕5发布 | 1000部夫妻午夜免费 | 性欧美牲交xxxxx视频 | 亚洲色无码一区二区三区 | 亚洲日韩精品欧美一区二区 | 国产精品久久久久久亚洲影视内衣 | 日日碰狠狠丁香久燥 | 国产精品亚洲综合色区韩国 | 在线观看国产一区二区三区 | 久在线观看福利视频 | 久久综合色之久久综合 | 日本欧美一区二区三区乱码 | 中文字幕人妻无码一夲道 | 午夜精品久久久久久久 | 天堂亚洲2017在线观看 | 久久国产自偷自偷免费一区调 | 女人色极品影院 | 国产亚洲精品久久久久久久 | 最近中文2019字幕第二页 | 国产一区二区三区四区五区加勒比 | 2020久久超碰国产精品最新 | 亚洲大尺度无码无码专区 | 丰满少妇高潮惨叫视频 | 中文字幕av日韩精品一区二区 | 蜜桃视频插满18在线观看 | 欧美丰满熟妇xxxx性ppx人交 | 久久熟妇人妻午夜寂寞影院 | 国产国产精品人在线视 | 无码人妻黑人中文字幕 | 国产亚洲美女精品久久久2020 | 精品亚洲成av人在线观看 | 国产偷国产偷精品高清尤物 | 国产电影无码午夜在线播放 | 欧美自拍另类欧美综合图片区 | 成人影院yy111111在线观看 | 波多野42部无码喷潮在线 | 国产亚洲精品久久久ai换 | 午夜福利不卡在线视频 | 一二三四在线观看免费视频 | 奇米影视7777久久精品人人爽 | 久久久久久a亚洲欧洲av冫 | 亚洲s色大片在线观看 | 久9re热视频这里只有精品 | 亚洲综合无码久久精品综合 | 精品熟女少妇av免费观看 | 亚洲精品鲁一鲁一区二区三区 | 爆乳一区二区三区无码 | www成人国产高清内射 | 在线看片无码永久免费视频 | 国产手机在线αⅴ片无码观看 | 国内少妇偷人精品视频免费 | 正在播放老肥熟妇露脸 | 在线播放免费人成毛片乱码 | 巨爆乳无码视频在线观看 | 国产真人无遮挡作爱免费视频 | 国内精品一区二区三区不卡 | 国语自产偷拍精品视频偷 | 精品国产一区av天美传媒 | 人人爽人人爽人人片av亚洲 | 日本va欧美va欧美va精品 | 久久国产精品偷任你爽任你 | 久久久久久久女国产乱让韩 | 亚洲人交乣女bbw | 久久99精品久久久久婷婷 | 初尝人妻少妇中文字幕 | 成人aaa片一区国产精品 | 久久久国产精品无码免费专区 | 九九热爱视频精品 | 亚洲熟妇自偷自拍另类 | 久久久久久国产精品无码下载 | 亚洲娇小与黑人巨大交 | 无码人妻少妇伦在线电影 | 国产成人精品必看 | 香港三级日本三级妇三级 | 99久久无码一区人妻 | 精品夜夜澡人妻无码av蜜桃 | 中文字幕人妻无码一夲道 | 久久国语露脸国产精品电影 | 久久午夜夜伦鲁鲁片无码免费 | 无码人中文字幕 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久精品丝袜高跟鞋 | 色综合久久88色综合天天 | 奇米影视7777久久精品 | 亚洲男人av香蕉爽爽爽爽 | 亚洲第一网站男人都懂 | 无码国模国产在线观看 | 我要看www免费看插插视频 | 国产av一区二区精品久久凹凸 | 性啪啪chinese东北女人 | 狂野欧美激情性xxxx | 日本饥渴人妻欲求不满 | 未满成年国产在线观看 | 国产精品内射视频免费 | 成人免费视频在线观看 | 3d动漫精品啪啪一区二区中 | 强开小婷嫩苞又嫩又紧视频 | 久久亚洲中文字幕无码 | 真人与拘做受免费视频一 | 亚洲中文字幕无码中字 | 国产成人精品三级麻豆 | 国产精品美女久久久 | 动漫av一区二区在线观看 | 精品人妻人人做人人爽 | 中文字幕无线码免费人妻 | 久久久精品欧美一区二区免费 | 国产熟女一区二区三区四区五区 | 国产肉丝袜在线观看 | 欧美丰满老熟妇xxxxx性 | 国产亚洲精品久久久久久国模美 | 久久国产自偷自偷免费一区调 | 亚洲精品鲁一鲁一区二区三区 | 国内综合精品午夜久久资源 | 日韩精品无码一区二区中文字幕 | 国产精品99爱免费视频 | 国产亚洲精品久久久久久久 | 午夜时刻免费入口 | 久久久久久久女国产乱让韩 | 水蜜桃av无码 | 久久综合狠狠综合久久综合88 | а天堂中文在线官网 | 精品熟女少妇av免费观看 | 久久精品人人做人人综合试看 | 精品国产一区二区三区四区在线看 | 性啪啪chinese东北女人 | 人妻人人添人妻人人爱 | 精品无人区无码乱码毛片国产 | 国产农村乱对白刺激视频 | 男女超爽视频免费播放 | 高清国产亚洲精品自在久久 | 精品国产精品久久一区免费式 | 玩弄中年熟妇正在播放 | 1000部啪啪未满十八勿入下载 | 精品久久久无码人妻字幂 | 中文字幕 亚洲精品 第1页 | 亚洲春色在线视频 | 午夜丰满少妇性开放视频 | 国产精品久久久久久亚洲毛片 | 亚洲国产欧美日韩精品一区二区三区 | 国产精品亚洲lv粉色 | 亚洲中文字幕av在天堂 | 久久 国产 尿 小便 嘘嘘 | 亚洲精品午夜国产va久久成人 | 亚洲 a v无 码免 费 成 人 a v | 亚洲乱码日产精品bd | 中文字幕无码日韩欧毛 | 国产亚洲精品久久久久久久久动漫 | 国产人成高清在线视频99最全资源 | 国产真实乱对白精彩久久 | 波多野结衣高清一区二区三区 | 国产激情精品一区二区三区 | 亚洲欧美中文字幕5发布 | 国产精品亚洲专区无码不卡 | 亚洲欧洲中文日韩av乱码 | 日本肉体xxxx裸交 | 狠狠噜狠狠狠狠丁香五月 | 内射后入在线观看一区 | 国产激情一区二区三区 | 美女黄网站人色视频免费国产 | a国产一区二区免费入口 | 欧洲极品少妇 | 水蜜桃亚洲一二三四在线 | 亚洲国产精品一区二区美利坚 | 天天摸天天碰天天添 | 2019nv天堂香蕉在线观看 | 国产精品无码一区二区三区不卡 | 成人性做爰aaa片免费看 | 国产 精品 自在自线 | 正在播放老肥熟妇露脸 | 曰韩少妇内射免费播放 | 性欧美videos高清精品 | 无码纯肉视频在线观看 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 久热国产vs视频在线观看 | 熟妇激情内射com | 国产人妻精品一区二区三区不卡 | 午夜精品久久久内射近拍高清 | 午夜时刻免费入口 | 老熟女重囗味hdxx69 | 在线天堂新版最新版在线8 | 67194成是人免费无码 | а天堂中文在线官网 | 一区二区三区乱码在线 | 欧洲 | 中文字幕 亚洲精品 第1页 | 人人妻人人澡人人爽精品欧美 | 国产性生交xxxxx无码 | 日韩av无码一区二区三区不卡 | 中文字幕 人妻熟女 | 亚洲中文字幕va福利 | 国产亚洲精品久久久久久久 | 日本大香伊一区二区三区 | 国产精品久久久久久久影院 | 亚洲日本在线电影 | 色婷婷欧美在线播放内射 | 强开小婷嫩苞又嫩又紧视频 | 精品国产成人一区二区三区 | 精品无码成人片一区二区98 | 熟妇人妻中文av无码 | 国产精品第一区揄拍无码 | 国产成人一区二区三区别 | 日日鲁鲁鲁夜夜爽爽狠狠 | 狠狠躁日日躁夜夜躁2020 | 东京热无码av男人的天堂 | 97夜夜澡人人双人人人喊 | 乱人伦中文视频在线观看 | 亚无码乱人伦一区二区 | 四虎影视成人永久免费观看视频 | 欧美肥老太牲交大战 | 国产亲子乱弄免费视频 | 人人澡人人透人人爽 | 国产av剧情md精品麻豆 | 无码国产激情在线观看 | 国产精品免费大片 | 亚洲乱码中文字幕在线 | 麻花豆传媒剧国产免费mv在线 | 免费观看的无遮挡av | 男女猛烈xx00免费视频试看 | 国产真实夫妇视频 | 97资源共享在线视频 | 国产亚洲精品精品国产亚洲综合 | 又粗又大又硬毛片免费看 | 久久精品中文字幕大胸 | 红桃av一区二区三区在线无码av | 亚洲国产精华液网站w | 亚洲综合无码一区二区三区 | 九月婷婷人人澡人人添人人爽 | 亚洲精品一区二区三区在线 | 中文无码成人免费视频在线观看 | 麻豆精产国品 | 亚洲精品www久久久 | 国产一精品一av一免费 | 无码乱肉视频免费大全合集 | 亚洲色偷偷男人的天堂 | 欧美熟妇另类久久久久久不卡 | 国产精品久久久久7777 | 色婷婷香蕉在线一区二区 | 日日麻批免费40分钟无码 | 黑人巨大精品欧美一区二区 | 天堂无码人妻精品一区二区三区 | 国产精品久久久久久亚洲毛片 | 欧美性猛交xxxx富婆 | 99精品视频在线观看免费 | 亚洲国产精品成人久久蜜臀 | 最近免费中文字幕中文高清百度 | 中文字幕人妻无码一区二区三区 | 亚洲一区二区三区香蕉 | 波多野结衣乳巨码无在线观看 | 国产精品久久久久久久影院 | 亚洲色欲色欲欲www在线 | 日日噜噜噜噜夜夜爽亚洲精品 | 秋霞成人午夜鲁丝一区二区三区 | 中文字幕无码人妻少妇免费 | 久久综合给合久久狠狠狠97色 | 欧美性生交活xxxxxdddd | 无码成人精品区在线观看 | 美女张开腿让人桶 | 国产精品美女久久久网av | 55夜色66夜色国产精品视频 | 自拍偷自拍亚洲精品10p | 鲁大师影院在线观看 | a片在线免费观看 | 曰韩无码二三区中文字幕 | 无码人妻少妇伦在线电影 | 牛和人交xxxx欧美 | 激情综合激情五月俺也去 | 国产真实乱对白精彩久久 | 亚洲中文字幕va福利 | 成人精品天堂一区二区三区 | 欧美丰满老熟妇xxxxx性 | 麻豆md0077饥渴少妇 | 99久久人妻精品免费一区 | 人人妻人人澡人人爽欧美一区 | 亚洲综合无码久久精品综合 | 人人澡人人妻人人爽人人蜜桃 | 蜜桃视频插满18在线观看 | 久久精品人妻少妇一区二区三区 | 亚洲精品国产第一综合99久久 | 高清国产亚洲精品自在久久 | 欧美人妻一区二区三区 | 久久亚洲中文字幕无码 | 国产午夜视频在线观看 | 一区二区三区乱码在线 | 欧洲 | 熟妇人妻无码xxx视频 | 欧美野外疯狂做受xxxx高潮 | 久久综合狠狠综合久久综合88 | 高潮毛片无遮挡高清免费视频 | 国产国语老龄妇女a片 | 亚洲伊人久久精品影院 | 人妻少妇精品无码专区二区 | 131美女爱做视频 | 国产午夜精品一区二区三区嫩草 | 巨爆乳无码视频在线观看 | 99久久久无码国产精品免费 | 国产一区二区三区精品视频 | 亚洲码国产精品高潮在线 | 久久精品国产一区二区三区 | 日本饥渴人妻欲求不满 | 精品国产一区二区三区四区在线看 | 日本www一道久久久免费榴莲 | 青青草原综合久久大伊人精品 | 久久精品人人做人人综合试看 | 国产亚洲人成在线播放 | 377p欧洲日本亚洲大胆 | 欧美 丝袜 自拍 制服 另类 | 人妻人人添人妻人人爱 | 欧美性猛交xxxx富婆 | 国产人妻人伦精品 | 男人和女人高潮免费网站 | 熟女少妇在线视频播放 | 国产熟妇高潮叫床视频播放 | 天天做天天爱天天爽综合网 | 日本精品人妻无码免费大全 | 久久久久久久人妻无码中文字幕爆 | 国产香蕉尹人综合在线观看 | 国产乱人伦偷精品视频 | 无码av免费一区二区三区试看 | 精品人妻人人做人人爽夜夜爽 | 日本www一道久久久免费榴莲 | 性欧美videos高清精品 | 最新国产麻豆aⅴ精品无码 | 中国女人内谢69xxxxxa片 | 娇妻被黑人粗大高潮白浆 | 青草青草久热国产精品 | 蜜桃无码一区二区三区 | 日韩人妻无码中文字幕视频 | 呦交小u女精品视频 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 97精品国产97久久久久久免费 | 亚洲精品中文字幕乱码 | 蜜臀aⅴ国产精品久久久国产老师 | 99久久人妻精品免费二区 | 午夜精品一区二区三区的区别 | 98国产精品综合一区二区三区 | 丁香花在线影院观看在线播放 | 在线精品亚洲一区二区 | www国产亚洲精品久久网站 | 国产农村妇女高潮大叫 | 天天躁夜夜躁狠狠是什么心态 | 97se亚洲精品一区 | 午夜无码人妻av大片色欲 | 精品国产乱码久久久久乱码 | 55夜色66夜色国产精品视频 | 亚洲区小说区激情区图片区 | 亚洲综合久久一区二区 | 色狠狠av一区二区三区 | 中文字幕av日韩精品一区二区 | 亚洲 日韩 欧美 成人 在线观看 | 国产成人精品三级麻豆 | 亚洲gv猛男gv无码男同 | 国产精品亚洲专区无码不卡 | 国产av人人夜夜澡人人爽麻豆 | 秋霞特色aa大片 | 久久久久亚洲精品男人的天堂 | 欧美高清在线精品一区 | 中文字幕久久久久人妻 | 国产午夜精品一区二区三区嫩草 | 日本一区二区更新不卡 | 国产成人无码午夜视频在线观看 | 国产精品久久久久9999小说 | 高清无码午夜福利视频 | 97久久精品无码一区二区 | 国产九九九九九九九a片 | av无码久久久久不卡免费网站 | 欧美成人家庭影院 | 美女黄网站人色视频免费国产 | 小泽玛莉亚一区二区视频在线 | 亚洲一区二区三区在线观看网站 | 最近的中文字幕在线看视频 | 男人扒开女人内裤强吻桶进去 | 欧美老妇交乱视频在线观看 | 国产免费久久精品国产传媒 | 狠狠综合久久久久综合网 | 夫妻免费无码v看片 | 色综合久久久无码中文字幕 | 四虎永久在线精品免费网址 | 欧美激情综合亚洲一二区 | 午夜福利电影 | 六十路熟妇乱子伦 | 久久久精品欧美一区二区免费 | 日日天干夜夜狠狠爱 | 日韩av无码一区二区三区 | 久久亚洲中文字幕无码 | 亚洲中文字幕成人无码 | 国产亚洲精品久久久久久久久动漫 | 99精品国产综合久久久久五月天 | 图片小说视频一区二区 | 日韩欧美中文字幕在线三区 | 久久无码专区国产精品s | 全黄性性激高免费视频 | 帮老师解开蕾丝奶罩吸乳网站 | 性史性农村dvd毛片 | 国产av人人夜夜澡人人爽麻豆 | 无码av中文字幕免费放 | 水蜜桃亚洲一二三四在线 | 色婷婷香蕉在线一区二区 | 天堂久久天堂av色综合 | 亚洲国产精华液网站w | 久久精品国产亚洲精品 | 成人免费视频一区二区 | 国产激情综合五月久久 | 成人亚洲精品久久久久软件 | 性欧美大战久久久久久久 | 最近的中文字幕在线看视频 | 久久精品一区二区三区四区 | 无码国内精品人妻少妇 | 国产成人无码区免费内射一片色欲 | 草草网站影院白丝内射 | 最新国产麻豆aⅴ精品无码 | 97久久精品无码一区二区 | a国产一区二区免费入口 | 无码午夜成人1000部免费视频 | 性生交大片免费看l | 波多野结衣av一区二区全免费观看 | 欧美阿v高清资源不卡在线播放 | 久久午夜无码鲁丝片 | 日本精品少妇一区二区三区 | 婷婷综合久久中文字幕蜜桃三电影 | 性做久久久久久久久 | 亚洲熟妇自偷自拍另类 | 天天躁日日躁狠狠躁免费麻豆 | 亚洲成av人影院在线观看 | 国产精品igao视频网 | 青青久在线视频免费观看 | 午夜精品久久久久久久 | 亚洲国产av美女网站 | 亚洲中文字幕久久无码 | 日本一卡2卡3卡四卡精品网站 | 久久久久av无码免费网 | 亚洲精品一区二区三区四区五区 | 亚洲精品综合一区二区三区在线 | 亚洲va欧美va天堂v国产综合 | 人妻天天爽夜夜爽一区二区 | 四虎影视成人永久免费观看视频 | 午夜精品久久久久久久 | 国产做国产爱免费视频 | 国産精品久久久久久久 | 国产精品va在线观看无码 | 日韩视频 中文字幕 视频一区 | 99riav国产精品视频 | 亚洲乱码国产乱码精品精 | 强开小婷嫩苞又嫩又紧视频 | 欧美变态另类xxxx | 99久久精品无码一区二区毛片 | 波多野结衣乳巨码无在线观看 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲精品成人av在线 | 亚洲男人av天堂午夜在 | 国产性生交xxxxx无码 | 欧美色就是色 | 国产办公室秘书无码精品99 | 中文字幕精品av一区二区五区 | 国产激情综合五月久久 | 在教室伦流澡到高潮hnp视频 | 免费国产成人高清在线观看网站 | 蜜桃臀无码内射一区二区三区 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 四虎4hu永久免费 | 一个人免费观看的www视频 | 中国女人内谢69xxxxxa片 | 国产人妻久久精品二区三区老狼 | 99国产精品白浆在线观看免费 | 亚洲中文字幕av在天堂 | 精品欧洲av无码一区二区三区 | 国内精品人妻无码久久久影院 | 国产精华av午夜在线观看 | 久久综合网欧美色妞网 | 中国女人内谢69xxxxxa片 | 美女极度色诱视频国产 | 无码av岛国片在线播放 | 蜜臀aⅴ国产精品久久久国产老师 | 欧美日韩人成综合在线播放 | 国产手机在线αⅴ片无码观看 | 久久国产36精品色熟妇 | 2020久久香蕉国产线看观看 | 国产激情艳情在线看视频 | 少妇一晚三次一区二区三区 | 欧美一区二区三区 | 亚洲国产精品一区二区第一页 | 久久综合给合久久狠狠狠97色 | 极品尤物被啪到呻吟喷水 | 黑森林福利视频导航 | 国产精品二区一区二区aⅴ污介绍 | 日本精品久久久久中文字幕 | 亚洲gv猛男gv无码男同 | 久久综合九色综合97网 | 丰满护士巨好爽好大乳 | 麻花豆传媒剧国产免费mv在线 | 色婷婷欧美在线播放内射 | 免费观看又污又黄的网站 | 免费国产黄网站在线观看 | 最新国产麻豆aⅴ精品无码 | 国产一区二区三区四区五区加勒比 | 性色欲情网站iwww九文堂 | 成人性做爰aaa片免费看不忠 | 麻豆md0077饥渴少妇 | 中文字幕无码日韩欧毛 | 日本熟妇乱子伦xxxx | 无码人中文字幕 | 一个人看的www免费视频在线观看 | 国产偷国产偷精品高清尤物 | 国产亚洲精品久久久ai换 | 在线播放无码字幕亚洲 | 精品无码一区二区三区爱欲 | 久久精品国产日本波多野结衣 | 99视频精品全部免费免费观看 | 国产精品视频免费播放 | 国产成人精品久久亚洲高清不卡 | 久久这里只有精品视频9 | 永久免费观看美女裸体的网站 | 中文毛片无遮挡高清免费 | 男人的天堂2018无码 | 亚洲色欲色欲天天天www | 国产特级毛片aaaaaaa高清 | 99久久精品午夜一区二区 | 国产激情综合五月久久 | 日韩av无码一区二区三区 | 正在播放老肥熟妇露脸 | 中文久久乱码一区二区 | 九九综合va免费看 | 天堂无码人妻精品一区二区三区 | 国产乱人无码伦av在线a | 国产精品无码一区二区三区不卡 | 露脸叫床粗话东北少妇 | аⅴ资源天堂资源库在线 | 免费无码的av片在线观看 | 在线观看免费人成视频 | 久久久精品成人免费观看 | 亚洲男人av香蕉爽爽爽爽 | 国产无套粉嫩白浆在线 | 中文无码成人免费视频在线观看 | 成 人影片 免费观看 | 久久久中文字幕日本无吗 | 爆乳一区二区三区无码 | 国产精品无套呻吟在线 | 亚洲男女内射在线播放 | 亚洲精品美女久久久久久久 | 精品国产国产综合精品 | 亚洲精品国产第一综合99久久 | 18禁止看的免费污网站 | 欧美成人高清在线播放 | 又紧又大又爽精品一区二区 | 网友自拍区视频精品 | yw尤物av无码国产在线观看 | 久久99精品久久久久久 | 欧美国产日韩久久mv | 国产特级毛片aaaaaa高潮流水 | 人妻少妇精品久久 | 日日躁夜夜躁狠狠躁 | 精品 日韩 国产 欧美 视频 | 内射后入在线观看一区 | 熟妇人妻无乱码中文字幕 | 美女极度色诱视频国产 | 51国偷自产一区二区三区 | 色噜噜亚洲男人的天堂 | 国产一精品一av一免费 | 亚洲国产精品无码久久久久高潮 | 人人爽人人爽人人片av亚洲 | 日日碰狠狠躁久久躁蜜桃 | 少妇无码一区二区二三区 | 国产suv精品一区二区五 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 图片区 小说区 区 亚洲五月 | 天堂在线观看www | 少妇无套内谢久久久久 | 免费无码肉片在线观看 | 国产手机在线αⅴ片无码观看 | 国产熟妇高潮叫床视频播放 | 久久久久久久人妻无码中文字幕爆 | 国产莉萝无码av在线播放 | 无码吃奶揉捏奶头高潮视频 | 久久精品人人做人人综合试看 | www一区二区www免费 | 99精品视频在线观看免费 | 欧美成人高清在线播放 | 成人无码精品1区2区3区免费看 | 在线天堂新版最新版在线8 | 免费人成在线观看网站 | 精品久久久久久人妻无码中文字幕 | 国产精品久久久久无码av色戒 | 国产精品人妻一区二区三区四 | 国产激情无码一区二区 | 亚洲 a v无 码免 费 成 人 a v | 国产手机在线αⅴ片无码观看 | 色一情一乱一伦一视频免费看 | 亚洲日韩av一区二区三区四区 | 九九久久精品国产免费看小说 | 精品国产av色一区二区深夜久久 | 亚洲精品国产品国语在线观看 | 亚洲人成人无码网www国产 | 久久国内精品自在自线 | 国产精品美女久久久 | www国产亚洲精品久久网站 | 久久久中文久久久无码 | 国产熟妇高潮叫床视频播放 | 乱人伦人妻中文字幕无码久久网 | 亚洲精品一区二区三区四区五区 | 久激情内射婷内射蜜桃人妖 | 永久黄网站色视频免费直播 | 亚洲 a v无 码免 费 成 人 a v | 亚洲自偷精品视频自拍 | 亚洲人成影院在线无码按摩店 | 亚洲国产精品成人久久蜜臀 | 亚洲精品国偷拍自产在线观看蜜桃 | 午夜精品一区二区三区的区别 | 性欧美熟妇videofreesex | 乱中年女人伦av三区 | 狠狠色欧美亚洲狠狠色www | 无码av最新清无码专区吞精 | 成人免费视频在线观看 | 亚洲七七久久桃花影院 | 99久久精品国产一区二区蜜芽 | 红桃av一区二区三区在线无码av | 无码人中文字幕 | 亚洲aⅴ无码成人网站国产app | 中文字幕乱码人妻二区三区 | 无码人妻丰满熟妇区五十路百度 | 无码av最新清无码专区吞精 | 少妇性l交大片欧洲热妇乱xxx | 国产激情精品一区二区三区 | 精品无码av一区二区三区 | 精品国产精品久久一区免费式 | 国产69精品久久久久app下载 | 亚洲最大成人网站 | 香港三级日本三级妇三级 | 日韩在线不卡免费视频一区 | 午夜免费福利小电影 | 国产精品永久免费视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | a国产一区二区免费入口 | 国产乱人偷精品人妻a片 | 久久亚洲中文字幕精品一区 | 在教室伦流澡到高潮hnp视频 | 成人片黄网站色大片免费观看 | 亚洲欧洲日本无在线码 | 国产三级精品三级男人的天堂 | 99久久人妻精品免费二区 | 亚洲成色在线综合网站 | 美女黄网站人色视频免费国产 | 四虎影视成人永久免费观看视频 | 黑人巨大精品欧美黑寡妇 | 精品无码国产自产拍在线观看蜜 | 国产亚洲精品久久久久久久 | 亚洲色偷偷偷综合网 | 中文久久乱码一区二区 | 亚洲成熟女人毛毛耸耸多 | 亚洲乱码国产乱码精品精 | 国产极品美女高潮无套在线观看 | 爱做久久久久久 | 99麻豆久久久国产精品免费 | 欧美第一黄网免费网站 | 国产激情综合五月久久 | 无码精品国产va在线观看dvd | aa片在线观看视频在线播放 | 亚洲乱码中文字幕在线 | 亚洲自偷自拍另类第1页 | 亚洲一区二区三区无码久久 | 久久国产精品萌白酱免费 | 蜜桃视频插满18在线观看 | 日韩精品久久久肉伦网站 | 亚洲精品www久久久 | 东京热无码av男人的天堂 | 在线 国产 欧美 亚洲 天堂 | 免费无码av一区二区 | 午夜福利一区二区三区在线观看 | 国语精品一区二区三区 | 亚洲欧美中文字幕5发布 | 国产黑色丝袜在线播放 | 无码人妻丰满熟妇区五十路百度 | 中文字幕乱码中文乱码51精品 | 国产猛烈高潮尖叫视频免费 | 大乳丰满人妻中文字幕日本 | 亚洲精品一区二区三区婷婷月 | 特黄特色大片免费播放器图片 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 鲁鲁鲁爽爽爽在线视频观看 | 中文字幕乱码人妻无码久久 | 全黄性性激高免费视频 | 久久综合色之久久综合 | 男人扒开女人内裤强吻桶进去 | 国产精品手机免费 | 亚洲熟熟妇xxxx | 精品无码一区二区三区的天堂 | 国内精品九九久久久精品 | 美女极度色诱视频国产 | 亚洲成熟女人毛毛耸耸多 | 国产欧美熟妇另类久久久 | 天堂а√在线地址中文在线 | 天堂а√在线地址中文在线 | 极品嫩模高潮叫床 | 国产无av码在线观看 | 中文久久乱码一区二区 | 亚洲 另类 在线 欧美 制服 | 久久精品视频在线看15 | 少妇厨房愉情理9仑片视频 | 欧美喷潮久久久xxxxx | 午夜精品久久久内射近拍高清 | 人妻有码中文字幕在线 | 天天爽夜夜爽夜夜爽 | 在线亚洲高清揄拍自拍一品区 | 九九久久精品国产免费看小说 | 国内揄拍国内精品人妻 | 亚洲啪av永久无码精品放毛片 | 亚洲欧美色中文字幕在线 | 欧美丰满老熟妇xxxxx性 | 黑人巨大精品欧美黑寡妇 | 国产午夜亚洲精品不卡 | 一本久久a久久精品vr综合 | av在线亚洲欧洲日产一区二区 | 内射老妇bbwx0c0ck | 色情久久久av熟女人妻网站 | 一个人看的www免费视频在线观看 | 无码午夜成人1000部免费视频 | 97夜夜澡人人双人人人喊 | 欧美日韩在线亚洲综合国产人 | 国产高清av在线播放 | 一个人看的www免费视频在线观看 | 久久天天躁狠狠躁夜夜免费观看 | 国产精品久久久久无码av色戒 | 纯爱无遮挡h肉动漫在线播放 | 水蜜桃av无码 | 亚洲大尺度无码无码专区 | 久久午夜无码鲁丝片午夜精品 | 亚洲码国产精品高潮在线 | 免费人成在线视频无码 | 日韩 欧美 动漫 国产 制服 | 国产一区二区三区精品视频 | 亚洲欧洲无卡二区视頻 | 天堂亚洲2017在线观看 | 大乳丰满人妻中文字幕日本 | 国产精品第一国产精品 | 乱人伦人妻中文字幕无码久久网 | 国产卡一卡二卡三 | 久激情内射婷内射蜜桃人妖 | 美女毛片一区二区三区四区 | 精品无码一区二区三区爱欲 | 99精品无人区乱码1区2区3区 | 亚洲精品欧美二区三区中文字幕 | 国产美女极度色诱视频www | 国产精品久久久av久久久 | 亚洲色欲色欲欲www在线 | 婷婷丁香六月激情综合啪 | 天天综合网天天综合色 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲欧洲日本无在线码 | 免费男性肉肉影院 | 欧美人与动性行为视频 | 98国产精品综合一区二区三区 | 久久国产劲爆∧v内射 | 亚洲日本在线电影 | 人人妻在人人 | 日韩无码专区 | 久久国产36精品色熟妇 | 国产偷自视频区视频 | 丝袜 中出 制服 人妻 美腿 | 国产三级久久久精品麻豆三级 | 中文字幕人妻无码一区二区三区 | 蜜桃无码一区二区三区 | 国产精品美女久久久网av | 中文无码成人免费视频在线观看 | 狂野欧美性猛xxxx乱大交 | 人人妻人人藻人人爽欧美一区 | 无码成人精品区在线观看 | 亚洲一区二区三区无码久久 | 奇米影视7777久久精品人人爽 | 初尝人妻少妇中文字幕 | 日韩无套无码精品 | 少妇邻居内射在线 | 亚洲国产成人av在线观看 | 国产亚洲视频中文字幕97精品 | 国产精品二区一区二区aⅴ污介绍 | 精品无码av一区二区三区 | 免费网站看v片在线18禁无码 | 波多野结衣一区二区三区av免费 | 日欧一片内射va在线影院 | 中文字幕人妻无码一区二区三区 | 亚洲色成人中文字幕网站 | 国产精品国产自线拍免费软件 | 久久久久久久人妻无码中文字幕爆 | 中文字幕乱妇无码av在线 | 夫妻免费无码v看片 | 一本久久伊人热热精品中文字幕 | 久久综合九色综合欧美狠狠 | 亚洲精品无码人妻无码 | 亚洲中文字幕在线观看 | 日韩成人一区二区三区在线观看 | 亚洲精品一区二区三区在线观看 | 久久综合给合久久狠狠狠97色 | 999久久久国产精品消防器材 | 亚洲国产欧美国产综合一区 | 蜜桃av抽搐高潮一区二区 | 精品一区二区三区波多野结衣 | 国产午夜亚洲精品不卡 | 一区二区三区乱码在线 | 欧洲 | 99精品久久毛片a片 | 久久zyz资源站无码中文动漫 | 女人被男人爽到呻吟的视频 | 国产精品无码一区二区桃花视频 | 中文字幕乱码人妻二区三区 | 国内揄拍国内精品人妻 | 亚洲国产成人a精品不卡在线 | 欧美兽交xxxx×视频 | 国产一精品一av一免费 | 欧美 日韩 人妻 高清 中文 | 成人无码视频免费播放 | 人人妻人人澡人人爽人人精品 | 成人影院yy111111在线观看 | 精品偷拍一区二区三区在线看 | 理论片87福利理论电影 | 亚洲国产综合无码一区 | 波多野结衣 黑人 | 免费看少妇作爱视频 | 久久国内精品自在自线 | 亚洲欧洲无卡二区视頻 | 黑人粗大猛烈进出高潮视频 | 99国产精品白浆在线观看免费 | 欧美 丝袜 自拍 制服 另类 | 国产综合色产在线精品 | 国产超碰人人爽人人做人人添 | 精品无码av一区二区三区 | 在线观看欧美一区二区三区 | 兔费看少妇性l交大片免费 | 中文字幕无码av波多野吉衣 | a片免费视频在线观看 | 婷婷综合久久中文字幕蜜桃三电影 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 亚洲精品一区二区三区在线 | 男人和女人高潮免费网站 | 精品久久久无码人妻字幂 | 熟妇人妻激情偷爽文 | 福利一区二区三区视频在线观看 | 波多野结衣高清一区二区三区 | 亚洲中文字幕av在天堂 | 亚洲中文字幕无码中文字在线 | 欧美人与动性行为视频 | 亚洲国产精品成人久久蜜臀 | 狠狠色丁香久久婷婷综合五月 | 亚洲乱码国产乱码精品精 | 久久精品国产亚洲精品 | 在线 国产 欧美 亚洲 天堂 | 内射欧美老妇wbb | 综合人妻久久一区二区精品 | 一本色道久久综合亚洲精品不卡 | 国产熟妇另类久久久久 | 亚洲男人av香蕉爽爽爽爽 | 久久久中文久久久无码 | 成熟妇人a片免费看网站 | 国产精品无码永久免费888 | 伊人久久婷婷五月综合97色 | 中文字幕无码av波多野吉衣 | 久久精品国产亚洲精品 | 久久精品中文字幕大胸 | 国产精品沙发午睡系列 | 亚洲va欧美va天堂v国产综合 | 夜夜高潮次次欢爽av女 | 中文精品久久久久人妻不卡 | 内射欧美老妇wbb | 7777奇米四色成人眼影 | 日韩在线不卡免费视频一区 | 亚洲а∨天堂久久精品2021 | 国内精品人妻无码久久久影院蜜桃 | 狠狠色噜噜狠狠狠狠7777米奇 | 一本色道婷婷久久欧美 | 中文字幕无码热在线视频 | 国产激情艳情在线看视频 | 精品无码国产一区二区三区av | 国产午夜视频在线观看 | 人妻少妇精品久久 | 亚洲精品国产a久久久久久 | 日本精品人妻无码免费大全 | 丰满人妻翻云覆雨呻吟视频 | 自拍偷自拍亚洲精品10p | 亚洲成av人片在线观看无码不卡 | 国产成人无码av一区二区 | 国产精品怡红院永久免费 | 未满小14洗澡无码视频网站 | 色综合天天综合狠狠爱 | 国产无遮挡又黄又爽又色 | 久久精品国产精品国产精品污 | 少妇人妻av毛片在线看 | 精品一区二区不卡无码av | 奇米影视7777久久精品 | 国产人妻精品一区二区三区不卡 | 国产舌乚八伦偷品w中 | 风流少妇按摩来高潮 | 国产一区二区三区精品视频 | 国产激情综合五月久久 | 成 人 网 站国产免费观看 | 国产99久久精品一区二区 | 亚洲精品国产第一综合99久久 | 国产亚洲精品久久久久久久 | 免费无码一区二区三区蜜桃大 | 欧美成人高清在线播放 | 娇妻被黑人粗大高潮白浆 | 国产超级va在线观看视频 | 又色又爽又黄的美女裸体网站 | 300部国产真实乱 | 人人澡人摸人人添 | 18精品久久久无码午夜福利 | 久久久www成人免费毛片 | 精品国产一区av天美传媒 | 麻豆国产人妻欲求不满谁演的 | 国产精品怡红院永久免费 | 亚洲精品中文字幕久久久久 | 亚洲精品国产第一综合99久久 | 红桃av一区二区三区在线无码av | 波多野结衣av一区二区全免费观看 | 国产精品多人p群无码 | 啦啦啦www在线观看免费视频 | 97精品国产97久久久久久免费 | 久久久久99精品成人片 | 久久久精品人妻久久影视 | 中文字幕乱妇无码av在线 | 国产无套粉嫩白浆在线 | 国产午夜精品一区二区三区嫩草 | 欧美人与禽zoz0性伦交 | 狠狠综合久久久久综合网 | а√资源新版在线天堂 | 露脸叫床粗话东北少妇 | 婷婷五月综合缴情在线视频 | 久久国产精品偷任你爽任你 | 内射白嫩少妇超碰 | 欧美性猛交内射兽交老熟妇 | 成人无码精品1区2区3区免费看 | 中国大陆精品视频xxxx | 中文字幕无码热在线视频 | 国产亚洲精品久久久久久久久动漫 | 精品国产成人一区二区三区 | 久久精品国产一区二区三区肥胖 | 国产免费久久久久久无码 | 真人与拘做受免费视频一 | 色噜噜亚洲男人的天堂 | 日韩亚洲欧美中文高清在线 | 国内精品人妻无码久久久影院蜜桃 | 色老头在线一区二区三区 | 国色天香社区在线视频 | 中文字幕人妻无码一区二区三区 | 天堂а√在线地址中文在线 | 国产熟妇高潮叫床视频播放 | 99er热精品视频 | 国产亲子乱弄免费视频 | 亚洲国产高清在线观看视频 | 日本丰满熟妇videos | 国产精品丝袜黑色高跟鞋 | 99久久99久久免费精品蜜桃 | 初尝人妻少妇中文字幕 | 久久亚洲国产成人精品性色 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲日韩一区二区三区 | 日本www一道久久久免费榴莲 | 国产人妻精品一区二区三区不卡 | 天堂久久天堂av色综合 | 欧洲vodafone精品性 | 日本精品久久久久中文字幕 | 一区二区三区乱码在线 | 欧洲 | 亚洲一区二区三区无码久久 | 免费无码午夜福利片69 | 在线精品亚洲一区二区 | 亚洲娇小与黑人巨大交 | 中文字幕人妻无码一区二区三区 | 中文字幕人妻丝袜二区 | 成 人 网 站国产免费观看 | 亚洲 欧美 激情 小说 另类 | 国产熟妇高潮叫床视频播放 | 99er热精品视频 | 免费观看的无遮挡av | 成熟人妻av无码专区 | 亚洲午夜福利在线观看 | 特黄特色大片免费播放器图片 | 九九久久精品国产免费看小说 | 亚洲成av人片天堂网无码】 | 久久精品中文闷骚内射 | 久久久亚洲欧洲日产国码αv | 色综合久久久无码中文字幕 | 日韩精品无码免费一区二区三区 | 性欧美大战久久久久久久 | 国产精品高潮呻吟av久久4虎 | 成人片黄网站色大片免费观看 | 亚洲成av人片天堂网无码】 | 午夜精品一区二区三区的区别 | 少妇高潮一区二区三区99 | 蜜臀av在线播放 久久综合激激的五月天 | 一本久久伊人热热精品中文字幕 | 国产精品.xx视频.xxtv | 最新国产麻豆aⅴ精品无码 | 少妇人妻大乳在线视频 | 日韩av无码中文无码电影 | 少妇激情av一区二区 | 中文字幕乱妇无码av在线 | 亚洲伊人久久精品影院 | 久久国产劲爆∧v内射 | 少妇人妻偷人精品无码视频 | 免费无码肉片在线观看 | 在线观看国产一区二区三区 | 欧美丰满熟妇xxxx | 无码av中文字幕免费放 | 亚洲aⅴ无码成人网站国产app | 中文字幕无码日韩欧毛 | 一本久久a久久精品亚洲 | 欧美刺激性大交 | 无码人妻黑人中文字幕 | 大地资源中文第3页 | 天堂亚洲2017在线观看 | 国产口爆吞精在线视频 | 国产精品理论片在线观看 | 亚洲精品国产精品乱码不卡 | 亚洲经典千人经典日产 | 东北女人啪啪对白 | 我要看www免费看插插视频 | 国产国语老龄妇女a片 | 亚洲精品一区二区三区在线观看 | 老熟女乱子伦 | 少妇被黑人到高潮喷出白浆 | 香港三级日本三级妇三级 | 色综合久久久无码中文字幕 | 乱码av麻豆丝袜熟女系列 | 精品偷自拍另类在线观看 | 精品无码国产自产拍在线观看蜜 | 久久综合香蕉国产蜜臀av | 亚洲综合另类小说色区 | 欧美人与物videos另类 | 精品久久久中文字幕人妻 | 国语自产偷拍精品视频偷 | 自拍偷自拍亚洲精品被多人伦好爽 | 377p欧洲日本亚洲大胆 | 精品久久久久久人妻无码中文字幕 | 99久久精品无码一区二区毛片 | 在线观看国产一区二区三区 | 亚洲区欧美区综合区自拍区 | 国产超级va在线观看视频 | 国产精品亚洲一区二区三区喷水 | 亚洲日韩一区二区三区 | 亚洲区小说区激情区图片区 | 久久精品中文字幕一区 | 国产亚洲精品久久久久久久久动漫 | 精品久久久久久人妻无码中文字幕 | 亚洲熟妇色xxxxx欧美老妇 | aa片在线观看视频在线播放 | 图片区 小说区 区 亚洲五月 | 88国产精品欧美一区二区三区 | 国产美女精品一区二区三区 | 高潮毛片无遮挡高清免费视频 | 性生交大片免费看女人按摩摩 | 丝袜足控一区二区三区 | 国产日产欧产精品精品app | 亚洲中文字幕无码中字 | 成年美女黄网站色大免费全看 | 国产精品自产拍在线观看 | 波多野结衣乳巨码无在线观看 | 国产亚av手机在线观看 | 午夜福利不卡在线视频 | 一本精品99久久精品77 | 亚洲综合在线一区二区三区 | 7777奇米四色成人眼影 | 国产亚洲欧美在线专区 | 小sao货水好多真紧h无码视频 | 日韩亚洲欧美精品综合 | 好屌草这里只有精品 | 无码精品人妻一区二区三区av | 婷婷综合久久中文字幕蜜桃三电影 | 青青青手机频在线观看 | 丝袜美腿亚洲一区二区 | 久久久精品欧美一区二区免费 | 久久久精品欧美一区二区免费 | 免费观看的无遮挡av | 久久人人97超碰a片精品 | 国产真人无遮挡作爱免费视频 | 久久人妻内射无码一区三区 | 成人片黄网站色大片免费观看 | 无套内谢的新婚少妇国语播放 | 男人的天堂av网站 | 77777熟女视频在线观看 а天堂中文在线官网 | 国产精品嫩草久久久久 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 久久国产精品_国产精品 | 2020久久超碰国产精品最新 | 久久久久se色偷偷亚洲精品av | 丝袜 中出 制服 人妻 美腿 | 亚洲国产成人a精品不卡在线 | 国产精品福利视频导航 | 中文无码成人免费视频在线观看 | 久久久久久a亚洲欧洲av冫 | 99久久久无码国产aaa精品 | 超碰97人人做人人爱少妇 | 国产三级精品三级男人的天堂 | 国产猛烈高潮尖叫视频免费 | 久久99精品久久久久久 | 人妻体内射精一区二区三四 | 国产精品无码永久免费888 | 色婷婷综合激情综在线播放 | 国产精品亚洲а∨无码播放麻豆 | 欧美野外疯狂做受xxxx高潮 | 久久久久久九九精品久 | 国产女主播喷水视频在线观看 | 搡女人真爽免费视频大全 | 成人一区二区免费视频 | 亚洲一区二区三区四区 | 草草网站影院白丝内射 | 偷窥日本少妇撒尿chinese | 无码人妻黑人中文字幕 | 精品国偷自产在线视频 | 丰满人妻被黑人猛烈进入 | 国产麻豆精品一区二区三区v视界 | 日日碰狠狠躁久久躁蜜桃 | 巨爆乳无码视频在线观看 | 欧美性猛交内射兽交老熟妇 | 天天燥日日燥 | 免费国产成人高清在线观看网站 | 欧美日韩亚洲国产精品 | 高清国产亚洲精品自在久久 | 国产精品a成v人在线播放 | 性欧美牲交在线视频 | 中文字幕人成乱码熟女app | 久久久国产一区二区三区 | av无码久久久久不卡免费网站 | 又大又硬又爽免费视频 | 午夜肉伦伦影院 | 漂亮人妻洗澡被公强 日日躁 | 无码中文字幕色专区 | 亚洲国产精品久久人人爱 | 伊人久久大香线蕉午夜 | 九九在线中文字幕无码 | 久久国产劲爆∧v内射 | 国产精品国产自线拍免费软件 | 波多野结衣 黑人 | 欧洲vodafone精品性 | 性欧美疯狂xxxxbbbb | 日日麻批免费40分钟无码 | 在线 国产 欧美 亚洲 天堂 | 国产av一区二区三区最新精品 | 77777熟女视频在线观看 а天堂中文在线官网 | 婷婷综合久久中文字幕蜜桃三电影 | 免费播放一区二区三区 | 在线a亚洲视频播放在线观看 | 国产亚洲精品久久久久久久 | 麻豆av传媒蜜桃天美传媒 | 国产人妻人伦精品1国产丝袜 | 无码人妻久久一区二区三区不卡 | 国产精品igao视频网 | 国精产品一区二区三区 | 欧美日韩久久久精品a片 | 黑人玩弄人妻中文在线 | 免费看少妇作爱视频 | 久久久精品欧美一区二区免费 | 妺妺窝人体色www在线小说 | 国产精品国产自线拍免费软件 | 久久久中文字幕日本无吗 | 日韩av无码一区二区三区 | 丝袜人妻一区二区三区 | 欧美自拍另类欧美综合图片区 | 亚洲精品久久久久久一区二区 | 国产无av码在线观看 | 亚洲精品一区二区三区四区五区 | 日本熟妇人妻xxxxx人hd | 亚洲一区二区三区无码久久 | 色婷婷欧美在线播放内射 | 亚拍精品一区二区三区探花 | 久久久久99精品成人片 | 午夜成人1000部免费视频 | 精品一区二区三区无码免费视频 | 一个人免费观看的www视频 | 大地资源网第二页免费观看 | 影音先锋中文字幕无码 | 亚洲日韩一区二区 | 亚洲中文字幕av在天堂 | 人人妻人人澡人人爽人人精品 | 国内精品一区二区三区不卡 | 国产精品久久久av久久久 | 国产精品久久久久9999小说 | 亚洲va中文字幕无码久久不卡 | 97se亚洲精品一区 | 爱做久久久久久 | 成人欧美一区二区三区黑人免费 | aⅴ在线视频男人的天堂 | 日韩视频 中文字幕 视频一区 | 综合人妻久久一区二区精品 | 无套内谢老熟女 | 国产综合在线观看 | 精品一区二区三区波多野结衣 | 国产免费久久精品国产传媒 | 131美女爱做视频 | 性欧美疯狂xxxxbbbb | 人妻无码αv中文字幕久久琪琪布 | 鲁鲁鲁爽爽爽在线视频观看 | 久久人人爽人人爽人人片av高清 | 免费人成网站视频在线观看 | 人妻熟女一区 | 亚洲日本一区二区三区在线 | 性色欲情网站iwww九文堂 | 无码av最新清无码专区吞精 | 国产一区二区三区四区五区加勒比 | 巨爆乳无码视频在线观看 | 精品人妻中文字幕有码在线 | 成人性做爰aaa片免费看 | av无码不卡在线观看免费 | 亚洲无人区一区二区三区 | 99在线 | 亚洲 | 色综合久久久无码网中文 | 999久久久国产精品消防器材 | 无码人中文字幕 | 欧美日韩综合一区二区三区 | 国产色精品久久人妻 | 亚洲色欲色欲天天天www | 日本精品人妻无码免费大全 | 在线а√天堂中文官网 | 久久久亚洲欧洲日产国码αv | 亚洲国产精品一区二区第一页 | 亚洲精品中文字幕久久久久 | 久久97精品久久久久久久不卡 | 国产午夜亚洲精品不卡下载 | 无码人妻av免费一区二区三区 | 麻豆av传媒蜜桃天美传媒 | 亚洲精品中文字幕乱码 | 任你躁在线精品免费 | 377p欧洲日本亚洲大胆 | 午夜成人1000部免费视频 | 97久久超碰中文字幕 | 国产成人精品优优av | 最新版天堂资源中文官网 | 熟女俱乐部五十路六十路av | 婷婷丁香五月天综合东京热 | 国产一区二区三区日韩精品 | 免费人成网站视频在线观看 | 国产av人人夜夜澡人人爽麻豆 | 欧美人与动性行为视频 | 天天燥日日燥 | 亚洲性无码av中文字幕 | 国语自产偷拍精品视频偷 | 国精产品一区二区三区 | 色偷偷人人澡人人爽人人模 | 久久精品国产亚洲精品 | 国产日产欧产精品精品app | 疯狂三人交性欧美 | 国产口爆吞精在线视频 | 乱码午夜-极国产极内射 | 男人和女人高潮免费网站 | 亚洲自偷自拍另类第1页 | 久久精品女人天堂av免费观看 | 国产办公室秘书无码精品99 | 久久精品国产日本波多野结衣 | 免费无码一区二区三区蜜桃大 | 久久久久99精品国产片 | 亚洲第一网站男人都懂 | 激情国产av做激情国产爱 | 无码人中文字幕 | 亚洲一区二区观看播放 | 国产欧美熟妇另类久久久 | 夜夜高潮次次欢爽av女 | 欧美自拍另类欧美综合图片区 | 激情综合激情五月俺也去 | 国产熟妇另类久久久久 | 99久久久无码国产aaa精品 | 波多野结衣av一区二区全免费观看 | 男女性色大片免费网站 | 欧美喷潮久久久xxxxx | 国产高清av在线播放 | 性欧美牲交在线视频 | 国产又粗又硬又大爽黄老大爷视 | 国产极品美女高潮无套在线观看 | 红桃av一区二区三区在线无码av | 国产一区二区三区日韩精品 | 国内精品一区二区三区不卡 | 少妇无套内谢久久久久 | 亚洲色欲色欲欲www在线 | 免费人成在线观看网站 | 久久久中文久久久无码 | 精品午夜福利在线观看 | 国内丰满熟女出轨videos | 扒开双腿疯狂进出爽爽爽视频 | 欧美兽交xxxx×视频 | 国产真实夫妇视频 | 亚洲一区二区三区在线观看网站 | 久久无码中文字幕免费影院蜜桃 | 成人性做爰aaa片免费看 | 亚洲精品午夜国产va久久成人 | 无码国产乱人伦偷精品视频 | 国产精品国产三级国产专播 | 强辱丰满人妻hd中文字幕 | 人人妻人人澡人人爽人人精品浪潮 | 婷婷综合久久中文字幕蜜桃三电影 | 午夜理论片yy44880影院 | 国产卡一卡二卡三 | 真人与拘做受免费视频 | 性欧美疯狂xxxxbbbb | 国产真人无遮挡作爱免费视频 | 国产精品手机免费 | 国产一区二区三区日韩精品 | 日本乱人伦片中文三区 | 7777奇米四色成人眼影 | 亚洲中文字幕av在天堂 | 国产av一区二区三区最新精品 | 又大又紧又粉嫩18p少妇 | 蜜臀av无码人妻精品 | 青春草在线视频免费观看 | 无码人妻出轨黑人中文字幕 | 一区二区传媒有限公司 | 中文字幕人妻丝袜二区 | 国产精品久久国产三级国 | 麻花豆传媒剧国产免费mv在线 | 亚洲精品国偷拍自产在线麻豆 | 日本护士xxxxhd少妇 | 一本色道久久综合亚洲精品不卡 | 国内揄拍国内精品少妇国语 | 成熟妇人a片免费看网站 | 国产精品久久久久久亚洲影视内衣 | 国产网红无码精品视频 | 亚洲精品综合五月久久小说 | 7777奇米四色成人眼影 | 六月丁香婷婷色狠狠久久 | 亚洲人成人无码网www国产 | 国产无套粉嫩白浆在线 | 亚洲人成人无码网www国产 | 国产成人综合在线女婷五月99播放 | 国产精品成人av在线观看 | 白嫩日本少妇做爰 | 国产亚洲人成a在线v网站 | av无码不卡在线观看免费 | 中文字幕久久久久人妻 | 久久精品成人欧美大片 | 国产农村妇女高潮大叫 | 国产黄在线观看免费观看不卡 | 亚洲人交乣女bbw | 成人一在线视频日韩国产 | 丰满肥臀大屁股熟妇激情视频 | 亚洲va中文字幕无码久久不卡 | 久久精品国产99久久6动漫 | 男女作爱免费网站 | 夜夜夜高潮夜夜爽夜夜爰爰 | 在线精品亚洲一区二区 | 亚洲色欲色欲天天天www | 国产电影无码午夜在线播放 | 人妻少妇精品无码专区二区 | 欧美 日韩 人妻 高清 中文 | 国产av一区二区三区最新精品 | 婷婷综合久久中文字幕蜜桃三电影 | 日韩视频 中文字幕 视频一区 | 色一情一乱一伦 | 精品熟女少妇av免费观看 | 红桃av一区二区三区在线无码av | 最新国产乱人伦偷精品免费网站 | 久久久久久国产精品无码下载 | 国产在线aaa片一区二区99 | 综合网日日天干夜夜久久 | 久久人人97超碰a片精品 | 亚洲精品综合五月久久小说 | 国产区女主播在线观看 | 亚洲国产高清在线观看视频 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲精品久久久久久一区二区 | 十八禁真人啪啪免费网站 | 久久国产精品萌白酱免费 | 狠狠色噜噜狠狠狠7777奇米 | 精品国精品国产自在久国产87 | 国产舌乚八伦偷品w中 | а√资源新版在线天堂 | 日本丰满熟妇videos | 人人妻人人藻人人爽欧美一区 | 午夜精品一区二区三区的区别 | 1000部啪啪未满十八勿入下载 | 国产人妻人伦精品 | 国产精品高潮呻吟av久久 | 国产av久久久久精东av | 性欧美牲交在线视频 | 久久精品成人欧美大片 | 亚洲另类伦春色综合小说 | 国产av久久久久精东av | 欧美喷潮久久久xxxxx | 精品无码一区二区三区的天堂 | 图片区 小说区 区 亚洲五月 | 乱码午夜-极国产极内射 | 国产亚洲精品久久久久久大师 | 成人欧美一区二区三区黑人 | 我要看www免费看插插视频 | 乌克兰少妇性做爰 | 色综合久久中文娱乐网 | 天干天干啦夜天干天2017 | 色婷婷综合中文久久一本 | ass日本丰满熟妇pics | 中文字幕+乱码+中文字幕一区 | 精品国产麻豆免费人成网站 | 色噜噜亚洲男人的天堂 | 欧美日韩一区二区三区自拍 | 无码纯肉视频在线观看 | 亚洲欧美中文字幕5发布 | 国内丰满熟女出轨videos | 国产精品美女久久久网av | 亚洲一区二区三区无码久久 | 国产成人无码专区 | 好男人社区资源 | 成熟妇人a片免费看网站 | 欧美日韩一区二区综合 | 在线精品国产一区二区三区 | 黑人大群体交免费视频 | 久久精品国产一区二区三区 | 玩弄少妇高潮ⅹxxxyw | 欧美日韩亚洲国产精品 | 少妇厨房愉情理9仑片视频 | 亚洲精品一区二区三区在线 | 欧美人与牲动交xxxx | 天堂在线观看www | 欧美 日韩 人妻 高清 中文 | 中文字幕 亚洲精品 第1页 | 亚洲精品久久久久久久久久久 | 性色欲网站人妻丰满中文久久不卡 | 久久久精品国产sm最大网站 | 一本大道久久东京热无码av | 国产激情精品一区二区三区 | 99re在线播放 | 国产精品美女久久久久av爽李琼 | 日本又色又爽又黄的a片18禁 | 白嫩日本少妇做爰 | 无码人妻av免费一区二区三区 | 色一情一乱一伦 | 精品人人妻人人澡人人爽人人 | 精品无码一区二区三区的天堂 | 国模大胆一区二区三区 | 久久97精品久久久久久久不卡 | 日韩精品无码一本二本三本色 | 日本精品人妻无码77777 天堂一区人妻无码 | 欧美日本免费一区二区三区 | 亚洲欧美日韩国产精品一区二区 | 黑人玩弄人妻中文在线 | 亚洲gv猛男gv无码男同 | 亚洲成熟女人毛毛耸耸多 | 丰腴饱满的极品熟妇 | 2019nv天堂香蕉在线观看 | 国内老熟妇对白xxxxhd | 中文字幕无码av波多野吉衣 | 日韩欧美中文字幕公布 | а天堂中文在线官网 | 国产激情精品一区二区三区 | 国产精品资源一区二区 | 亚洲一区二区三区播放 | 亚洲一区二区三区无码久久 | 久久人妻内射无码一区三区 | 亚洲娇小与黑人巨大交 | 欧美日韩一区二区综合 | 中文无码精品a∨在线观看不卡 | 婷婷六月久久综合丁香 | 伊人久久大香线焦av综合影院 | 亚洲色欲色欲天天天www | 中文字幕人妻丝袜二区 | 国内少妇偷人精品视频免费 | aa片在线观看视频在线播放 | 国产热a欧美热a在线视频 |