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

Springboot整合Ehcache和Redis實現多級緩存實戰案例

開發 架構 Redis
本文通過springboot整合ehcache和redis實現多級緩存案例實戰,從源碼角度分析下多級緩存實現原理。

一、概述

在實際的工作中,我們通常會使用多級緩存機制,將本地緩存和分布式緩存結合起來,從而提高系統性能和響應速度。本文通過springboot整合ehcache和redis實現多級緩存案例實戰,從源碼角度分析下多級緩存實現原理。

二、實戰案例

pom依賴(注意引入cache和ehcache組件依賴)。

<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>cache-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.23</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
    </dependencies>
</project>

application.properties(啟動類加上:@EnableCaching注解)。

server.port = 7001
spring.application.name = cache-demo

#log config
logging.config = classpath:log/logback.xml
debug = false

#mp config
mybatis-plus.mapper-locations = classpath*:mapper/*.xml
mybatis-plus.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/數據庫?characterEncoding=utf-8
spring.datasource.username = 數據庫賬號
spring.datasource.password = 數據庫密碼

#redis config
spring.redis.host = redis主機
spring.redis.port = 6379
spring.redis.password=redis密碼,沒有就刪掉該配置

# ehcache config
spring.cache.type = ehcache
spring.cache.ehcache.config = classpath:ehcache.xml

ehcache.xml。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <diskStore path="D:\ehcache"/>

    <!--默認緩存策略 -->
    <!-- external:是否永久存在,設置為true則不會被清除,此時與timeout沖突,通常設置為false-->
    <!-- diskPersistent:是否啟用磁盤持久化-->
    <!-- maxElementsInMemory:最大緩存數量-->
    <!-- overflowToDisk:超過最大緩存數量是否持久化到磁盤-->
    <!-- timeToIdleSeconds:最大不活動間隔,設置過長緩存容易溢出,設置過短無效果,單位:秒-->
    <!-- timeToLiveSeconds:最大存活時間,單位:秒-->
    <!-- memoryStoreEvictionPolicy:緩存清除策略-->
    <defaultCache
            eternal="false"
            diskPersistent="false"
            maxElementsInMemory="1000"
            overflowToDisk="false"
            timeToIdleSeconds="60"
            timeToLiveSeconds="60"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="studentCache"
            eternal="false"
            diskPersistent="false"
            maxElementsInMemory="1000"
            overflowToDisk="false"
            timeToIdleSeconds="100"
            timeToLiveSeconds="100"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>

MybatisPlusConfig類(注意:@MapperScan注解,也可加在啟動類上)。

@Configuration
@MapperScan("com.cache.demo.mapper")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //分頁插件
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

測試demo。

這里可以將一級緩存、二級緩存時效設置短一些,方便進行測試。

@Slf4j
@RestController
@RequestMapping("/cache")
public class CacheController {

    @Resource
    private StudentMapper studentMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

  	// 添加緩存注解(一級緩存:ehcache)
    @Cacheable(value = "studentCache", key = "#id+'getStudentById'")
    @GetMapping("/getStudentById")
    public String getStudentById(Integer id) {
        String key = "student:" + id;
      	// 一級緩存中不存在,則從二級緩存:redis中查找
        String studentRedis = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(studentRedis)) {
            return JSON.toJSONString(JSON.parseObject(studentRedis, Student.class));
        }
        // 二級緩存中不存在則查詢數據庫,并更新二級緩存、一級緩存
        Student student = studentMapper.selectStudentById(id);
        if (null != student) {
            stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(student));
        }
        return JSON.toJSONString(student);
    }
}

啟動類上的:@EnableCaching注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
  
	boolean proxyTargetClass() default false;
  
	AdviceMode mode() default AdviceMode.PROXY;
  
  int order() default Ordered.LOWEST_PRECEDENCE;
}

導入的:CachingConfigurationSelector類:

public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {

	@Override
	public String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
        // 此處走的是:PROXY
				return getProxyImports();
			case ASPECTJ:
				return getAspectJImports();
			default:
				return null;
		}
	}

	private String[] getProxyImports() {
		List<String> result = new ArrayList<>(3);
    // 導入了AutoProxyRegistrar類和ProxyCachingConfiguration類
		result.add(AutoProxyRegistrar.class.getName());
		result.add(ProxyCachingConfiguration.class.getName());
		if (jsr107Present && jcacheImplPresent) {
			result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
		}
		return StringUtils.toStringArray(result);
	}
}

AutoProxyRegistrar類(代碼有所簡化):

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
				// 最終注冊了:InfrastructureAdvisorAutoProxyCreator(BeanPostProcessor接口實現類)
    		// 通過重寫postProcessAfterInitialization接口創建代理對象
      	AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
	}
}

@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

導入的第一個類看完了,接著看導入的第二個類:ProxyCachingConfiguration。

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {

	@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(CacheOperationSource cacheOperationSource, CacheInterceptor cacheInterceptor) {
		//  構建BeanFactoryCacheOperationSourceAdvisor
    BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();
		// 設置緩存注解解析器
    advisor.setCacheOperationSource(cacheOperationSource);
		// 設置緩存攔截器:cacheInterceptor
    advisor.setAdvice(cacheInterceptor);
		if (this.enableCaching != null) {
			advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
		}
		return advisor;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public CacheOperationSource cacheOperationSource() {
    // 緩存注解解析器
		return new AnnotationCacheOperationSource();
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {
		// 緩存攔截器
    CacheInterceptor interceptor = new CacheInterceptor();
		interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
		interceptor.setCacheOperationSource(cacheOperationSource);
		return interceptor;
	}
}

繼續看下CacheInterceptor類(重要):

public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {

	@Override
	@Nullable
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();
		CacheOperationInvoker aopAllianceInvoker = () -> {
			try {
				return invocation.proceed();
			}
			catch (Throwable ex) {
				throw new CacheOperationInvoker.ThrowableWrapper(ex);
			}
		};

		Object target = invocation.getThis();
		Assert.state(target != null, "Target must not be null");
		try {
      // 緩存執行邏輯
			return execute(aopAllianceInvoker, target, method, invocation.getArguments());
		}
		catch (CacheOperationInvoker.ThrowableWrapper th) {
			throw th.getOriginal();
		}
	}
}

@Nullable
	protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
		if (this.initialized) {
			Class<?> targetClass = getTargetClass(target);
			CacheOperationSource cacheOperationSource = getCacheOperationSource();
			if (cacheOperationSource != null) {
        // 解析緩存相關注解,返回CacheOperation
        // 每個緩存注解對應一種不同的解析處理操作
        // CacheEvictOperation、CachePutOperation、CacheableOperation等
				Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
				if (!CollectionUtils.isEmpty(operations)) {
          // 執行緩存邏輯
					return execute(invoker, method,
							new CacheOperationContexts(operations, method, args, target, targetClass));
				}
			}
		}
		return invoker.invoke();
	}

private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
		// 解析處理@CacheEvict注解
    processCacheEvicts(contexts.get(CacheEvictOperation.class), true,	CacheOperationExpressionEvaluator.NO_RESULT);

		// 解析處理@Cacheable注解
		Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));

		List<CachePutRequest> cachePutRequests = new ArrayList<>();
		if (cacheHit == null) {
			collectPutRequests(contexts.get(CacheableOperation.class),	CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
		}

		Object cacheValue;
		Object returnValue;

		if (cacheHit != null && !hasCachePut(contexts)) {
			// 命中緩存,則從緩存中獲取數據
			cacheValue = cacheHit.get();
			returnValue = wrapCacheValue(method, cacheValue);
		} else {
			// 未命中緩存,則通過反射執行目標方法
			returnValue = invokeOperation(invoker);
			cacheValue = unwrapReturnValue(returnValue);
		}

		// 解析處理@CachePut注解
		collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);

		// 未命中緩存時,會封裝一個cachePutRequests
  	// 然后通過反射執行目標方法后,執行該方法,最終調用EhCacheCache.put方法將數據寫入緩存中
		for (CachePutRequest cachePutRequest : cachePutRequests) {
			cachePutRequest.apply(cacheValue);
		}
		// 解析處理@CacheEvict注解,和上面的方法相同,只不過第二個參數不同
		processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
		return returnValue;
	}

接著看下findCachedItem方法。

private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) {
		Object result = CacheOperationExpressionEvaluator.NO_RESULT;
		for (CacheOperationContext context : contexts) {
			if (isConditionPassing(context, result)) {
        // 生成key策略:解析@Cacheable注解中的key屬性
        // 若未配置則默認使用SimpleKeyGenerator#generateKey方法生成key
				Object key = generateKey(context, result);
				Cache.ValueWrapper cached = findInCaches(context, key);
				if (cached != null) {
					return cached;
				}	else {
					if (logger.isTraceEnabled()) {
						logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());
					}
				}
			}
		}
		return null;
	}

// SimpleKeyGenerator#generateKey
public static Object generateKey(Object... params) {
  	// 方法沒有參數,則返回空的SimpleKey
		if (params.length == 0) {
			return SimpleKey.EMPTY;
		}
  	// 方法參數只有一個,則返回該參數
		if (params.length == 1) {
			Object param = params[0];
			if (param != null && !param.getClass().isArray()) {
				return param;
			}
		}
  	// 否則將方法參數進行封裝,返回SimpleKey
		return new SimpleKey(params);
	}

private Cache.ValueWrapper findInCaches(CacheOperationContext context, Object key) {
		for (Cache cache : context.getCaches()) {
      // 從一級緩存中獲取數據
			Cache.ValueWrapper wrapper = doGet(cache, key);
			if (wrapper != null) {
				if (logger.isTraceEnabled()) {
					logger.trace("Cache entry for key '" + key + "' found in cache '" + cache.getName() + "'");
				}
				return wrapper;
			}
		}
		return null;
	}

protected Cache.ValueWrapper doGet(Cache cache, Object key) {
		try {
      // 這里我們使用的是:EhCacheCache,所以最終會調用EhCacheCache.get方法獲取緩存中的數據
			return cache.get(key);
		}
		catch (RuntimeException ex) {
			getErrorHandler().handleCacheGetError(ex, cache, key);
			return null;
		}
	}

三、總結

@EnableCaching和@Transactional等實現邏輯大體相同,看的多了,則一通百通。

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-02-14 07:47:20

SpringBootEhcache

2020-06-29 07:43:12

緩存RedisSpringBoot

2020-01-10 15:42:13

SpringBootRedis數據庫

2022-03-15 08:22:31

Ehcachespring緩存

2023-01-13 07:39:07

2017-04-17 10:35:40

Spring BooRedis 操作

2019-04-23 08:42:42

EhcacheMemcacheRedis

2024-11-01 16:18:52

2024-11-04 08:02:23

SpringRabbitMQ中間件

2024-12-24 08:44:55

ActiveMQRabbitMQ交換機

2021-09-26 05:02:00

緩存Ehcache用法

2024-02-20 14:10:55

系統緩存冗余

2023-05-05 18:38:33

多級緩存Caffeine開發

2023-05-05 06:13:51

分布式多級緩存系統

2021-03-26 08:16:32

SpringbootWebsocket前端

2017-05-09 10:07:34

SpringbootDubboZooKeeper

2022-06-13 10:23:34

Helios緩存服務端

2025-04-21 03:00:00

2023-01-11 15:11:36

SpringEhcache

2015-12-28 10:48:44

RedisSpring緩存實例
點贊
收藏

51CTO技術棧公眾號

国产一区二区三区精品欧美日韩一区二区三区| 亚洲制服欧美另类| 伊人色综合久久天天| 国产精品久久久久久久久久久久冷| 中文字幕亚洲精品在线| 国产精品亚洲二区| 欧美精品乱人伦久久久久久| 成人在线播放网址| 国产一级免费在线观看| 狠狠色丁香婷婷综合久久片| 午夜精品在线视频| 免费一级suv好看的国产网站| 中文字幕区一区二区三| 欧美性大战xxxxx久久久| 欧美另类videosbestsex日本| 深夜福利视频在线观看| 国产在线播放一区三区四| 人人做人人澡人人爽欧美| 来吧亚洲综合网| 亚瑟一区二区三区四区| 欧美一卡在线观看| 麻豆一区二区三区视频| 蜜桃av在线播放| 亚洲欧美日韩一区| 婷婷五月色综合| 熟妇高潮一区二区高潮| 国产在线日韩欧美| 国产精品高潮呻吟久久av野狼 | 色老头在线视频| 欧美/亚洲一区| 中文字幕日韩av| 老司机福利av| 久久久免费毛片| 欧美videossexotv100| 国产一区二区在线观看免费视频| 超级碰碰久久| 天天色综合天天| 超碰人人爱人人| 免费av网站在线观看| 国产亚洲欧美日韩在线一区| 久久99精品国产99久久| 亚洲a视频在线| 国产麻豆日韩欧美久久| 成人网址在线观看| 又污又黄的网站| 青青国产91久久久久久 | 中文字幕一区二区人妻电影| 日韩午夜在线电影| 国产69精品久久久久9| 91成人福利视频| 亚州av乱码久久精品蜜桃 | 成人免费网站黄| 日韩成人午夜| 精品无人区乱码1区2区3区在线| 精品国产乱码久久久久夜深人妻| 亚洲一区二区三区日本久久九 | 日本人妻丰满熟妇久久久久久| 国产福利一区二区三区| 97超碰在线播放| 成人福利小视频| 成人中文字幕电影| 国产精品一区二区三区观看| 色欲av伊人久久大香线蕉影院| 国产v日产∨综合v精品视频| 99久热re在线精品视频| 成人免费视频国产| 99视频在线精品| 久久99精品久久久久久水蜜桃 | 91嫩草国产线观看亚洲一区二区| 欧美人伦禁忌dvd放荡欲情| 女人高潮一级片| 视频一区国产| 337p日本欧洲亚洲大胆色噜噜| 黄色免费看视频| 久久不见久久见免费视频7| 国产亚洲一区二区在线| 亚洲精品一区二区三区在线播放| 欧美伊人影院| 欧美亚洲成人xxx| 波多野结衣视频免费观看| 久久国产欧美日韩精品| 91精品啪aⅴ在线观看国产| 亚洲第一天堂影院| 久久久一区二区三区| 四虎永久国产精品| 日本孕妇大胆孕交无码| 欧美性猛交xxxx免费看久久久| 五月天激情视频在线观看| 欧美大片91| 亚洲欧美另类人妖| 91传媒免费观看| 亚洲精品看片| 国产精品专区一| 特黄aaaaaaaaa真人毛片| 国产日韩一级二级三级| 欧美乱做爰xxxⅹ久久久| 9i看片成人免费高清| 3d成人h动漫网站入口| 蜜臀av粉嫩av懂色av| 欧美日韩一区二区三区视频播放| 九九综合九九综合| 国模私拍一区二区| 成人免费视频免费观看| 亚洲一区二区三区涩| 69av成人| 91精品欧美综合在线观看最新| 国产精品300页| 天天做天天爱综合| 日韩av色综合| 国内爆初菊对白视频| 国产欧美日韩在线| 天天夜碰日日摸日日澡性色av| 97精品资源在线观看| 一本一本久久a久久精品综合小说| 久久久久久久久久综合 | 亚洲AV无码久久精品国产一区| 希岛爱理av免费一区二区| 美女扒开尿口让男人操亚洲视频网站 | 亚洲伊人春色| 久久青草精品视频免费观看| 一区二区 亚洲| 久久精品视频免费观看| 欧美乱大交xxxxx潮喷l头像| 91久久青草| 最近中文字幕mv在线一区二区三区四区 | 欧美综合国产精品久久丁香| 亚洲成人黄色片| 亚洲色图在线视频| 天天干天天干天天干天天干天天干| 豆花视频一区二区| 欧美另类69精品久久久久9999| 在线观看国产小视频| 久久久久久日产精品| 免费一级特黄毛片| xxxx日韩| 欧美激情免费看| 国产wwwxxx| 亚洲人123区| 波多野结衣国产精品| 国产精品一在线观看| 日韩免费在线看| 青青色在线视频| 韩曰欧美视频免费观看| 一区二区视频观看| 免费久久99精品国产自在现线| 精品午夜一区二区三区| 麻豆理论在线观看| 精品亚洲永久免费精品| 欧美a∨亚洲欧美亚洲| 99这里只有精品| 日本三级免费网站| 蜜桃一区二区三区| 国产成人精品免费久久久久| 精品久久av| 欧美视频精品在线观看| 亚洲最大成人综合网| 日韩国产成人精品| 欧美高清视频一区| 成人日韩在线观看| 日韩在线免费av| 国产欧美久久久| 一区二区三区在线播| 亚洲最大视频网| 韩日在线一区| 久久日韩精品| 成人av色网站| 欧美成人第一页| 欧美自拍偷拍第一页| 疯狂欧美牲乱大交777| 三上悠亚ssⅰn939无码播放| 日韩av中文在线观看| 亚洲欧美日韩精品综合在线观看| 亚洲色图综合| 久久久久久中文| 精品资源在线看| 91精品国产免费久久综合| 国产真实夫妇交换视频| 久久久精品人体av艺术| 九九九九九九九九| 影音先锋中文字幕一区二区| 欧美日韩在线一区二区三区| 色成人综合网| 国语对白做受69| 国产福利在线看| 日韩一区二区电影网| 日韩男人的天堂| 国产精品久久久久精k8| 无码人妻一区二区三区在线| 日韩高清一区二区| 400部精品国偷自产在线观看| 国产日韩三级| 成人福利网站在线观看11| sqte在线播放| 中文字幕亚洲一区在线观看| 欧美一级视频免费| 欧美色中文字幕| 91蜜桃视频在线观看| 国产精品视频免费| 在线观看免费视频黄| 美女网站色91| 日日摸日日碰夜夜爽av| 午夜久久免费观看| 欧美日韩国产综合视频在线| 国产精品一区三区在线观看| 国产91九色视频| 黄污视频在线观看| 中文字幕在线看视频国产欧美在线看完整 | 美国毛片一区二区| 国产3p露脸普通话对白| 久久久久久久久久久久久久久久久久 | 少妇高潮久久久| 777久久久精品| 无码人妻一区二区三区线| 亚洲制服丝袜av| www.黄色com| 久久亚洲二区三区| 亚洲视频天天射| 精品亚洲国内自在自线福利| 成年人观看网站| 日韩亚洲精品在线| 日韩免费在线观看av| 欧美电影一二区| 色女孩综合网| 久久久久观看| 国产精品一级久久久| 美女精品视频在线| 成人国产亚洲精品a区天堂华泰| 一级毛片久久久| 国内成人精品视频| 美女尤物在线视频| 欧美精品中文字幕一区| 国产最新在线| 精品国产一区二区三区久久久| 国产午夜视频在线观看| 亚洲精品久久久久| 色呦呦中文字幕| 亚洲二区中文字幕| 手机看片1024国产| 亚洲成人久久一区| 人妻精品一区一区三区蜜桃91| 日韩三级在线观看| www男人的天堂| 日韩欧美高清dvd碟片| 国产v片在线观看| 日韩精品一区二区三区在线播放| 国内毛片毛片毛片毛片| 日韩久久精品一区| 欧美一区二区黄片| 国产婷婷97碰碰久久人人蜜臀| 婷婷国产在线| 精品视频在线导航| 二区三区在线| 日韩在线观看你懂的| 成人三级网址| 欧美国产日韩一区二区在线观看| 波多野结依一区| 69久久夜色精品国产7777| 亚洲精品动漫| 国产精品99导航| 欧美日韩免费电影| 91网在线免费观看| 国产成人夜色高潮福利影视| 国内精品视频在线播放| 欧洲亚洲视频| 视频一区在线免费观看| 91亚洲国产| 51xx午夜影福利| 亚洲看片免费| 免费涩涩18网站入口| 国产精品香蕉一区二区三区| 国产香蕉精品视频| 久久久精品欧美丰满| 青青操在线播放| 亚洲国产精品欧美一二99| 国产精品久久久久久人| 欧美日韩中文字幕一区| 国产黄色片免费观看| 亚洲精品视频二区| 午夜在线小视频| 久久久久久久久久久91| 搜成人激情视频| 99久久精品免费看国产四区| 伊人久久大香线蕉| 国产日产欧美一区二区| 国产精品一二| 北条麻妃亚洲一区| 久久亚洲一区二区三区明星换脸 | 九色视频在线播放| 欧美大胆a视频| 欧美xxx视频| 97超级碰碰| 成人一区而且| 免费 成 人 黄 色| 激情丁香综合五月| 玖玖爱在线观看| 一区二区三区四区视频精品免费 | 日韩理论片在线观看| 欧美黄在线观看| 日本爱爱免费视频| 成人精品免费看| 日韩av片在线免费观看| 精品国产91久久久久久| 国产露脸国语对白在线| 亚洲女成人图区| 丝袜美腿av在线| 91精品久久久久久久久久另类| 琪琪久久久久日韩精品| 韩国黄色一级大片| 首页国产欧美久久| 在线免费播放av| 亚洲精品久久久蜜桃| 中文字幕二区三区| 亚洲精品在线91| 黄色美女视频在线观看| 91在线直播亚洲| 日韩美女一区二区三区在线观看| 777精品久无码人妻蜜桃| 国产乱子轮精品视频| 黑人と日本人の交わりビデオ| 欧美日韩亚洲激情| 人妻91麻豆一区二区三区| 欧美精品亚州精品| 久久综合偷偷噜噜噜色| 亚洲黄色成人久久久| 久久久综合网| 欧美熟妇一区二区| 欧美日韩中文在线| 日本波多野结衣在线| 久久久久成人网| 99精品在免费线中文字幕网站一区| 在线观看欧美亚洲| 卡一卡二国产精品| 黄色激情小视频| 欧美色图一区二区三区| 91精彩在线视频| 国产精品视频久久久| 不卡在线一区二区| 天美星空大象mv在线观看视频| 久久久精品黄色| 国产精品久久久久久久久久久久久久久久久 | 青青草国产免费一区二区下载| 日本va中文字幕| 国产欧美日韩视频一区二区| 色老头在线视频| 中文字幕亚洲精品| 国内精品伊人| 欧美h视频在线观看| 国产伦理精品不卡| 免费无码毛片一区二区app| 欧美大片日本大片免费观看| 免费av不卡在线观看| 国产精品久久7| 99精品国产福利在线观看免费| 丝袜熟女一区二区三区| 精品电影在线观看| 女人偷人在线视频| 日本精品久久久久影院| 成人av国产| 69久久精品无码一区二区| 亚洲图片一区二区| 男女视频在线观看免费| 国产精品观看在线亚洲人成网| 久久国产亚洲精品| 天堂网成人在线| 亚洲va韩国va欧美va| 欧美新色视频| 成人国产精品一区二区| 一区免费在线| 美女被到爽高潮视频| 欧美精品在线一区二区| 免费影视亚洲| 免费在线成人av电影| 久久国产精品区| 国产一级性生活| 亚洲欧洲午夜一线一品| 亚洲tv在线| 成人免费网站入口| 国产日韩av一区二区| 国产情侣av在线| 欧美在线亚洲一区| 国产韩国精品一区二区三区| 亚洲av成人片无码| 欧美性xxxxxx少妇| 男女视频在线| 午夜一区二区三区| 国产91在线观看丝袜| 中文字幕69页| 欧美高跟鞋交xxxxhd| 久久av免费看| 亚洲最大视频网| 欧美日韩一区二区三区四区| 国精一区二区三区| 天天爽天天狠久久久| 成人av综合在线| 亚洲综合一区中| 欧美在线欧美在线| 欧美国产免费| 91视频免费在观看| 亚洲国产精品高清久久久| 亚洲男男av|