欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

如何從SpringBoot整合Mybatis來(lái)自動(dòng)配置

這篇文章將為大家詳細(xì)講解有關(guān)如何從SpringBoot整合Mybatis來(lái)自動(dòng)配置,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

創(chuàng)新互聯(lián)是一家業(yè)務(wù)范圍包括IDC托管業(yè)務(wù),雅安服務(wù)器托管、主機(jī)租用、主機(jī)托管,四川、重慶、廣東電信服務(wù)器租用,四川雅安服務(wù)器托管,成都網(wǎng)通服務(wù)器托管,成都服務(wù)器租用,業(yè)務(wù)范圍遍及中國(guó)大陸、港澳臺(tái)以及歐美等多個(gè)國(guó)家及地區(qū)的互聯(lián)網(wǎng)數(shù)據(jù)服務(wù)公司。

前言

SpringBoot憑借"約定大于配置"的理念,已經(jīng)成為最流行的web開發(fā)框架,所以有必須對(duì)其進(jìn)行深入的了解;本文通過(guò)整合Mybatis類來(lái)分析SpringBoot提供的自動(dòng)配置(AutoConfigure)功能,在此之前首先看一個(gè)整合Mybatis的實(shí)例。

SpringBoot整合Mybatis

提供SpringBoot整合Mybatis的實(shí)例,通過(guò)Mybatis實(shí)現(xiàn)簡(jiǎn)單的增刪改查功能;

1.表數(shù)據(jù)

CREATE TABLE `role` (
  `note` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
  `role_name` varchar(255) DEFAULT NULL,
  `id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

提供創(chuàng)建role表相關(guān)的sql,對(duì)表進(jìn)行增刪改查操作;

2.整合Mybatis的依賴

主要是mybatis-spring-boot-starter和使用的MySQL驅(qū)動(dòng):

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.29</version>
</dependency>

3.配置application.properties

提供連接mysql相關(guān)的信息:url,驅(qū)動(dòng),用戶名,密碼;

spring.datasource.url=jdbc:mysql://localhost/mybatis
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

4.提供bean和Dao

分別提供表對(duì)應(yīng)的bean類和操作數(shù)據(jù)庫(kù)的dao類;

public class Role {

    private long id;
    private String roleName;
    private String note;
    //省略get/set方法
}
@Mapper
public interface RoleDao {

    @Select("SELECT id,role_name as roleName,note FROM role WHERE id = #{id}")
    Role findRoleById(@Param("id") long id);
}

5.提供Service和Controller

public interface RoleService {

    public Role findRoleById(long roleId);

}

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleDao roleDao;

    @Override
    public Role findRoleById(long roleId) {
        return roleDao.findRoleById(roleId);
    }

}
@RestController
public class RoleController {

    @Autowired
    private RoleService roleService;

    @RequestMapping("/role")
    public String getRole(long id) {
        return roleService.findRoleById(id).toString();
    }

}

啟動(dòng)服務(wù),進(jìn)行簡(jiǎn)單的測(cè)試:http://localhost:8888/role?id=111
結(jié)果如下:

Role [id=111, roleName=zhaohui, note=hello]

6.提出問(wèn)題

如上實(shí)例中,我們使用了很少的配置,就通過(guò)mybatis實(shí)現(xiàn)了操作數(shù)據(jù)庫(kù);正常使用mybatis需要的SqlSessionFactory和SqlSession沒有看到被實(shí)例化,同時(shí)mybatis依賴的數(shù)據(jù)源也沒有看到被引用,那SpringBoot是如何幫我們自動(dòng)配置的,下面重點(diǎn)分析一下;

SpringBoot自動(dòng)配置

1.自動(dòng)配置注解

要想使用自動(dòng)配置功能,SpringBoot提供了注解@EnableAutoConfiguration,當(dāng)然不需要我們配置因?yàn)樵贎SpringBootApplication注解中默認(rèn)以及啟用了;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//...省略...
}

可以看到@SpringBootApplication注解本身也有注解@EnableAutoConfiguration:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
//...省略...
}

在注解@EnableAutoConfiguration中重點(diǎn)看一下@Import注解中使用的AutoConfigurationImportSelector類,此類是自動(dòng)注解的核心類,會(huì)有條件的加載我們默認(rèn)指定的配置類;這里有兩個(gè)概念一個(gè)是有條件,一個(gè)是配置類,分別簡(jiǎn)單介紹一下:配置類可以簡(jiǎn)單理解就是相關(guān)組件對(duì)接SpringBoot的對(duì)接類,此類可以做一些初始化的工作;有條件表示并不是有配置類就能被對(duì)接上,是有條件的,SpringBoot默認(rèn)提供了大量配置類,但并不是所有配置類都能被加載初始化的,是有條件的,比如mybatis在沒有數(shù)據(jù)源的情況下,沒有mybatis基礎(chǔ)包的情況下是不能被對(duì)接的;下面首先看一下SpringBoot提供的哪些條件類;

2.條件類

SpringBoot提供了很多條件類,可以在配置中上配置注解條件類,相關(guān)條件類可以在spring-boot-autoconfigure包下的org.springframework.boot.autoconfigure.condition下找到,主要包含如下:

  • ConditionalOnBean:當(dāng)前容器有指定Bean的條件下;

  • ConditionalOnClass:當(dāng)前類路徑下有指定類的條件下;

  • ConditionalOnCloudPlatform:當(dāng)指定了云平臺(tái)的時(shí)候;

  • ConditionalOnExpression:SpEL表達(dá)式作為判斷條件;

  • ConditionalOnJava:JVM版本作為判斷條件;

  • ConditionalOnJndi:在JNDI存在的條件下查找指定的位置;

  • ConditionalOnMissingBean:當(dāng)容器里沒有指定Bean的情況下;

  • ConditionalOnMissingClass:當(dāng)類路徑下沒有指定的類的條件下;

  • ConditionalOnNotWebApplication:當(dāng)前項(xiàng)目不是WEB項(xiàng)目的條件下;

  • ConditionalOnProperty:當(dāng)前應(yīng)用是否配置了指定屬性指定的值;

  • ConditionalOnResource:只有當(dāng)指定的資源位于類路徑下;

  • ConditionalOnSingleCandidate:bean工廠中只有一個(gè)或者有多個(gè)情況下是主要的候選bean;

  • ConditionalOnWebApplication:當(dāng)前項(xiàng)目是WEB項(xiàng)目的條件下。

以上是注解類,注解本身沒有功能,只是提供標(biāo)記的功能,具體功能在@Conditional中指定的,比如ConditionalOnBean注解如下所示:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
//...省略...
}

相關(guān)功能的實(shí)現(xiàn)就在OnBeanCondition類中,同樣其他注解類的實(shí)現(xiàn)類也在包org.springframework.boot.autoconfigure.condition下找到;

3.自動(dòng)配置過(guò)程

Springboot應(yīng)用啟動(dòng)過(guò)程中使用ConfigurationClassParser分析配置類,此類中有一個(gè)processImports方法,此方法用來(lái)處理@Import注解,在@EnableAutoConfiguration注解存在@Import注解,這時(shí)候會(huì)實(shí)例化注解中的AutoConfigurationImportSelector,在其內(nèi)部有一個(gè)AutoConfigurationGroup內(nèi)部類,內(nèi)部類有兩個(gè)核心方法分別是:process和selectImports;

        @Override
        public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
            Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
                    () -> String.format("Only %s implementations are supported, got %s",
                            AutoConfigurationImportSelector.class.getSimpleName(),
                            deferredImportSelector.getClass().getName()));
            AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
                    .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
            this.autoConfigurationEntries.add(autoConfigurationEntry);
            for (String importClassName : autoConfigurationEntry.getConfigurations()) {
                this.entries.putIfAbsent(importClassName, annotationMetadata);
            }
        }

此方法主要獲取經(jīng)過(guò)條件過(guò)濾之后可用的自動(dòng)配置類,主要調(diào)用AutoConfigurationImportSelector中的getAutoConfigurationEntry完成的:

    protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }

首先獲取了所有備選的自動(dòng)配置類,然后刪除了重復(fù)和被排除的類,最后通過(guò)條件進(jìn)行篩選出可用的配置類,下面分別看一下,首先看一下如何獲取所有備選的配置類:

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
                + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

通過(guò)SpringFactoriesLoader獲取類路徑下META-INF/spring.factories文件中key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置類,可以看一下spring-boot-autoconfigure.jar中的spring.factories內(nèi)容:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
//...以下省略...

當(dāng)然這里只是截取了其中一個(gè)類路徑j(luò)ar下的部分配置,獲取所有配置類之后進(jìn)行去重,去被排除的類,然后進(jìn)行條件過(guò)濾,下面重點(diǎn)看一下:

private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
        long startTime = System.nanoTime();
        String[] candidates = StringUtils.toStringArray(configurations);
        boolean[] skip = new boolean[candidates.length];
        boolean skipped = false;
        for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
            invokeAwareMethods(filter);
            boolean[] match = filter.match(candidates, autoConfigurationMetadata);
            for (int i = 0; i < match.length; i++) {
                if (!match[i]) {
                    skip[i] = true;
                    candidates[i] = null;
                    skipped = true;
                }
            }
        }
        if (!skipped) {
            return configurations;
        }
        List<String> result = new ArrayList<>(candidates.length);
        for (int i = 0; i < candidates.length; i++) {
            if (!skip[i]) {
                result.add(candidates[i]);
            }
        }
        if (logger.isTraceEnabled()) {
            int numberFiltered = configurations.size() - result.size();
            logger.trace("Filtered " + numberFiltered + " auto configuration class in "
                    + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
        }
        return new ArrayList<>(result);
    }

此方法大致就是首先獲取配置的AutoConfigurationImportFilter ,然后對(duì)之前獲取的所有配置類進(jìn)行過(guò)濾,最后返回過(guò)濾之后的配置類;AutoConfigurationImportFilter同樣也是通過(guò)SpringFactoriesLoader類進(jìn)行加載類路徑下META-INF/spring.factories,只不過(guò)當(dāng)前的key是:org.springframework.boot.autoconfigure.AutoConfigurationImportFilter,可以看一下SpringBoot默認(rèn)配置的filter:

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

可以看到Filter其實(shí)就是上文介紹的條件類,這里默認(rèn)了OnBeanCondition,OnClassCondition以及OnWebApplicationCondition,已這里使用的Mybatis為例看一下MybatisAutoConfiguration的注解:

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
//...以下省略...
}

可以看到其中有用到@ConditionalOnClass,表示必須提供SqlSessionFactory和SqlSessionFactoryBean類的情況下才加載此配置類,而整兩個(gè)是正式Mybatis基礎(chǔ)包中提供的;有了基礎(chǔ)包還不行,還需要DataSource,而且DataSource必須在MybatisAutoConfiguration實(shí)例化之前初始化好,SpringBoot是如何實(shí)現(xiàn),繼續(xù)看另外一個(gè)核心方法selectImports():

        @Override
        public Iterable<Entry> selectImports() {
            if (this.autoConfigurationEntries.isEmpty()) {
                return Collections.emptyList();
            }
            Set<String> allExclusions = this.autoConfigurationEntries.stream()
                    .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
            Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
                    .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
                    .collect(Collectors.toCollection(LinkedHashSet::new));
            processedConfigurations.removeAll(allExclusions);

            return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
                    .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
                    .collect(Collectors.toList());
        }

        private List<String> sortAutoConfigurations(Set<String> configurations,
                AutoConfigurationMetadata autoConfigurationMetadata) {
            return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
                    .getInPriorityOrder(configurations);
        }

首先是對(duì)被排除類的一個(gè)過(guò)濾,然后接下來(lái)重點(diǎn)看一下對(duì)配置類進(jìn)行排序的一個(gè)方法,具體操作在類AutoConfigurationSorter中進(jìn)行的,具體方法為getInPriorityOrder():

    public List<String> getInPriorityOrder(Collection<String> classNames) {
        AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
                this.autoConfigurationMetadata, classNames);
        List<String> orderedClassNames = new ArrayList<>(classNames);
        // Initially sort alphabetically
        Collections.sort(orderedClassNames);
        // Then sort by order
        orderedClassNames.sort((o1, o2) -> {
            int i1 = classes.get(o1).getOrder();
            int i2 = classes.get(o2).getOrder();
            return Integer.compare(i1, i2);
        });
        // Then respect @AutoConfigureBefore @AutoConfigureAfter
        orderedClassNames = sortByAnnotation(classes, orderedClassNames);
        return orderedClassNames;
    }

首先使用order進(jìn)行排序,然后使用@AutoConfigureBefore和@AutoConfigureAfter就行排序;order其實(shí)就是通過(guò)注解@AutoConfigureOrder進(jìn)行排序的,值是一個(gè)整數(shù),結(jié)構(gòu)類似如下:

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)

@AutoConfigureBefore和@AutoConfigureAfter字面意思也很好理解,指定在其他配置類之前和之后,所以可以看到在MybatisAutoConfiguration中有如下配置:

@AutoConfigureAfter(DataSourceAutoConfiguration.class)

表示在DataSourceAutoConfiguration配置類加載之后才會(huì)加載Mybatis配置類,這樣就解決了依賴關(guān)系;還有上文提到的Mybatis操作數(shù)據(jù)庫(kù)依賴的SqlSessionFactory和SqlSession,都在MybatisAutoConfiguration進(jìn)行了初始化操作;SpringBoot本身其實(shí)以及提供了大量常用組件的自動(dòng)配置類,我們只需要提供滿足的特定條件,SpringBoot自動(dòng)會(huì)幫我加載初始化等操作,但是肯定也有自定義配置類的需求,下面用一個(gè)簡(jiǎn)單的實(shí)例來(lái)看看如何自定義一個(gè)自動(dòng)配置類;

自定義配置類

接下來(lái)我們用很簡(jiǎn)單的實(shí)例來(lái)看一下自定義的流程,一個(gè)格式化大寫消息的實(shí)例;

1.pom文件引入依賴

<groupId>com.format</groupId>
<artifactId>format-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>format-spring-boot-starter</name>
<url>http://maven.apache.org</url>

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Spring 官方 Starter通常命名為spring-boot-starter-{name}如 spring-boot-starter-web,Spring官方建議非官方Starter命名應(yīng)遵循{name}-spring-boot-starter的格式;

2.服務(wù)類和屬性配置類

@ConfigurationProperties("format.service")
public class FormatServiceProperties {
    private String type;
    //...get/set省略...
}

public class FormatService {
    private String type;

    public FormatService(String type) {
        this.type = type;
    }

    public String wrap(String word) {
        if(type.equalsIgnoreCase("Upper")){//大寫
            return word.toUpperCase();
        }else if(type.equalsIgnoreCase("Lower")){//小寫
            return word.toLowerCase();
        }
        return word;
    }
}

屬性類提供了type參數(shù)可以在application.properties中配置,可配置值包括:upper,lower;

3.自動(dòng)配置類和創(chuàng)建spring.factories文件

@Configuration
@ConditionalOnClass(FormatService.class)
@EnableConfigurationProperties(FormatServiceProperties.class)
public class FormatAutoConfigure {

    @Autowired
    private FormatServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    FormatService formatService() {
        return new FormatService(properties.getType());
    }

}

這個(gè)就是自定義的自動(dòng)配置類,SpringBoot啟動(dòng)的時(shí)候會(huì)根據(jù)條件自動(dòng)初始化;最后在resources/META-INF/下創(chuàng)建spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.format.FormatAutoConfigure

4.測(cè)試

在其他SpringBoot中可以引入上面創(chuàng)建的項(xiàng)目,引入方式也很簡(jiǎn)單:

<dependency>
    <groupId>com.format</groupId>
    <artifactId>format-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

同時(shí)在application.properties配置格式化類型:

format.service.type=upper

啟動(dòng)應(yīng)用,瀏覽器訪問(wèn)http://localhost:8888/format?word=hello,結(jié)果為:HELLO

主要使用SpringBoot整合Mybatis開始,然后提出使用中產(chǎn)生的疑問(wèn),進(jìn)而通過(guò)分析源碼的方式來(lái)理解SpringBoot的自動(dòng)配置機(jī)制,最后自定義了一個(gè)自動(dòng)配置類來(lái)看看具體如何使用;SpringBoot通過(guò)自動(dòng)配置的方式幫助開發(fā)者減少了很大的工作量,達(dá)到開箱即用的效果;但是另一方面如果出現(xiàn)問(wèn)題需要調(diào)試可能不是那么好定位。

關(guān)于如何從SpringBoot整合Mybatis來(lái)自動(dòng)配置就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

本文題目:如何從SpringBoot整合Mybatis來(lái)自動(dòng)配置
本文地址:http://chinadenli.net/article28/jgihjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、品牌網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化、域名注冊(cè)、外貿(mào)網(wǎng)站建設(shè)定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷型網(wǎng)站建設(shè)

網(wǎng)站設(shè)計(jì)公司知識(shí)

国产精品成人一区二区在线| 日韩三极片在线免费播放| 91香蕉视频精品在线看| 国产精品乱子伦一区二区三区| 国产一区二区三区香蕉av| 亚洲国产香蕉视频在线观看| 亚洲国产欧美久久精品| 麻豆精品视频一二三区| 日韩三级黄色大片免费观看| 亚洲精品国产福利在线| 亚洲一级二级三级精品| 亚洲精品中文字幕一二三| 久久热中文字幕在线视频| 精品偷拍一区二区三区| 欧洲日本亚洲一区二区| 可以在线看的欧美黄片| 日本高清一道一二三区四五区| 亚洲精品中文字幕无限乱码| 少妇激情在线免费观看| 久久热中文字幕在线视频| 91人妻人人揉人人澡人| 精品少妇一区二区三区四区| 经典欧美熟女激情综合网| 狠色婷婷久久一区二区三区| 欧美欧美欧美欧美一区| 国产一区二区三区av在线| 亚洲精品偷拍一区二区三区| 日本国产欧美精品视频| 国产又黄又爽又粗视频在线| 人妻少妇系列中文字幕| 偷自拍亚洲欧美一区二页| 精品亚洲香蕉久久综合网| 成人免费观看视频免费| 亚洲精品中文字幕一二三| 日韩欧美一区二区黄色| 九七人妻一区二区三区| 高清一区二区三区四区五区| 精品国产av一区二区三区不卡蜜| 日韩欧美国产高清在线| 日韩精品一区二区毛片| 成人国产激情福利久久|