<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SpringBoot中這10個神仙功能,驚艷到我了!

      前言

      我們每天都在用SpringBoot,但可能只用到了它20%的功能。

      今天我要分享那些讓開發(fā)效率提升數(shù)倍的隱藏神器,希望對你會有所幫助。

      一、@Conditional注解

      有些小伙伴在工作中可能遇到過這樣的場景:不同環(huán)境需要加載不同的Bean配置。

      傳統(tǒng)的做法是用@Profile,但@Conditional提供了更靈活的控制能力。

      基礎用法

      @Configuration
      public class DataSourceConfig {
          
          @Bean
          @Conditional(ProdDataSourceCondition.class)
          public DataSource prodDataSource() {
              // 生產(chǎn)環(huán)境數(shù)據(jù)源
              return DataSourceBuilder.create()
                      .url("jdbc:mysql://prod-host:3306/app")
                      .username("prod-user")
                      .password("prod-pass")
                      .build();
          }
          
          @Bean
          @Conditional(DevDataSourceCondition.class)
          public DataSource devDataSource() {
              // 開發(fā)環(huán)境數(shù)據(jù)源
              return DataSourceBuilder.create()
                      .url("jdbc:h2:mem:testdb")
                      .username("sa")
                      .password("")
                      .build();
          }
      }
      
      // 生產(chǎn)環(huán)境條件判斷
      public class ProdDataSourceCondition implements Condition {
          @Override
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              String env = context.getEnvironment().getProperty("app.env");
              return "prod".equals(env);
          }
      }
      
      // 開發(fā)環(huán)境條件判斷
      public class DevDataSourceCondition implements Condition {
          @Override
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              String env = context.getEnvironment().getProperty("app.env");
              return "dev".equals(env) || env == null;
          }
      }
      

      進階用法:組合條件

      @Target({ElementType.TYPE, ElementType.METHOD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Conditional(OnDatabaseTypeCondition.class)
      public @interface ConditionalOnDatabaseType {
          String value();
      }
      
      public class OnDatabaseTypeCondition implements Condition {
          @Override
          public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
              Map<String, Object> attributes = metadata.getAnnotationAttributes(
                  ConditionalOnDatabaseType.class.getName());
              String expectedType = (String) attributes.get("value");
              String actualType = context.getEnvironment().getProperty("app.db.type");
              return expectedType.equals(actualType);
          }
      }
      
      // 使用自定義條件注解
      @Configuration
      public class CacheConfig {
          
          @Bean
          @ConditionalOnDatabaseType("redis")
          public CacheManager redisCacheManager() {
              return new RedisCacheManager();
          }
          
          @Bean
          @ConditionalOnDatabaseType("caffeine")
          public CacheManager caffeineCacheManager() {
              return new CaffeineCacheManager();
          }
      }
      

      深度解析:@Conditional的核心價值在于實現(xiàn)了"條件化配置",這是SpringBoot自動配置的基石。

      通過實現(xiàn)Condition接口,我們可以基于任何條件(環(huán)境變量、系統(tǒng)屬性、類路徑、Bean存在性等)來決定是否加載某個Bean。

      二、@ConfigurationProperties

      有些小伙伴可能還在用@Value一個個注入配置屬性,其實@ConfigurationProperties才是更優(yōu)雅的解決方案。

      基礎綁定

      @Component
      @ConfigurationProperties(prefix = "app.datasource")
      @Validated
      public class DataSourceProperties {
          
          @NotBlank
          private String url;
          
          @NotBlank
          private String username;
          
          private String password;
          
          @Min(1)
          @Max(100)
          private int maxPoolSize = 10;
          
          private Duration connectionTimeout = Duration.ofSeconds(30);
          
          // 嵌套配置
          private Pool pool = new Pool();
          
          // getters and setters
          public static class Pool {
              private int maxSize = 20;
              private int minIdle = 5;
              
              // getters and setters
          }
      }
      
      // application.yml
      app:
        datasource:
          url: jdbc:mysql://localhost:3306/test
          username: root
          password: secret
          max-pool-size: 20
          connection-timeout: 60s
          pool:
            max-size: 50
            min-idle: 10
      

      類型安全配置

      @Configuration
      @EnableConfigurationProperties(DataSourceProperties.class)
      public class DataSourceAutoConfiguration {
          
          @Bean
          @ConditionalOnMissingBean
          public DataSource dataSource(DataSourceProperties properties) {
              HikariDataSource dataSource = new HikariDataSource();
              dataSource.setJdbcUrl(properties.getUrl());
              dataSource.setUsername(properties.getUsername());
              dataSource.setPassword(properties.getPassword());
              dataSource.setMaximumPoolSize(properties.getMaxPoolSize());
              dataSource.setConnectionTimeout(properties.getConnectionTimeout().toMillis());
              return dataSource;
          }
      }
      

      深度解析:@ConfigurationProperties不僅提供了類型安全的配置綁定,還支持嵌套屬性、集合類型、數(shù)據(jù)校驗、寬松綁定(kebab-case到camelCase自動轉換)等特性。

      這是SpringBoot"約定優(yōu)于配置"理念的完美體現(xiàn)。

      三、Spring Boot Actuator

      生產(chǎn)環(huán)境監(jiān)控是系統(tǒng)穩(wěn)定性的生命線,Actuator提供了開箱即用的監(jiān)控端點。

      核心端點配置

      @Configuration
      public class ActuatorConfig {
          
          // 自定義健康檢查
          @Component
          public class DatabaseHealthIndicator implements HealthIndicator {
              
              @Autowired
              private DataSource dataSource;
              
              @Override
              public Health health() {
                  try (Connection conn = dataSource.getConnection()) {
                      if (conn.isValid(1000)) {
                          return Health.up()
                                  .withDetail("database", "Available")
                                  .withDetail("validationQuery", "SUCCESS")
                                  .build();
                      }
                  } catch (SQLException e) {
                      return Health.down(e)
                              .withDetail("database", "Unavailable")
                              .withDetail("error", e.getMessage())
                              .build();
                  }
                  return Health.unknown().build();
              }
          }
          
          // 自定義指標
          @Component
          public class OrderMetrics {
              
              private final Counter orderCounter;
              private final DistributionSummary orderAmountSummary;
              
              public OrderMetrics(MeterRegistry registry) {
                  this.orderCounter = Counter.builder("order.count")
                          .description("Total number of orders")
                          .register(registry);
                          
                  this.orderAmountSummary = DistributionSummary.builder("order.amount")
                          .description("Order amount distribution")
                          .baseUnit("USD")
                          .register(registry);
              }
              
              public void recordOrder(Order order) {
                  orderCounter.increment();
                  orderAmountSummary.record(order.getAmount().doubleValue());
              }
          }
      }
      
      // application.yml 管理端點暴露配置
      management:
        endpoints:
          web:
            exposure:
              include: health,info,metrics,prometheus
        endpoint:
          health:
            show-details: always
            show-components: always
          metrics:
            enabled: true
      

      自定義信息端點

      @Component
      public class BuildInfoContributor implements InfoContributor {
          
          @Override
          public void contribute(Info.Builder builder) {
              Map<String, String> buildDetails = new HashMap<>();
              buildDetails.put("version", "1.0.0");
              buildDetails.put("timestamp", Instant.now().toString());
              buildDetails.put("commit", getGitCommit());
              
              builder.withDetail("build", buildDetails)
                     .withDetail("environment", getEnvironmentInfo());
          }
          
          private String getGitCommit() {
              // 獲取Git提交信息
              try {
                  return new String(Files.readAllBytes(Paths.get("git.properties")));
              } catch (IOException e) {
                  return "unknown";
              }
          }
      }
      

      深度解析:Actuator不僅僅是監(jiān)控工具,它提供了應用的全方位可觀測性。通過健康檢查、指標收集、審計事件、HTTP追蹤等功能,我們可以構建完整的應用監(jiān)控體系。

      四、Spring Boot DevTools

      有些小伙伴可能還在手動重啟應用來查看代碼變更效果,DevTools提供了極致的開發(fā)體驗。

      熱加載配置

      // application-dev.yml
      spring:
        devtools:
          restart:
            enabled: true
            exclude: static/**,public/**
            additional-paths: src/main/java
          livereload:
            enabled: true
        thymeleaf:
          cache: false
        freemarker:
          cache: false
      
      // 自定義重啟觸發(fā)器
      @Component
      public class CustomRestartTrigger implements ApplicationListener<ClassPathChangedEvent> {
          
          private final RestartScope restartScope;
          
          public CustomRestartTrigger(RestartScope restartScope) {
              this.restartScope = restartScope;
          }
          
          @Override
          public void onApplicationEvent(ClassPathChangedEvent event) {
              if (event.getChangeSet().isModified()) {
                  // 清除重啟范圍內(nèi)的Bean
                  restartScope.clear();
                  System.out.println("檢測到類路徑變化,準備重啟...");
              }
          }
      }
      

      開發(fā)時配置覆蓋

      // 開發(fā)環(huán)境特定配置
      @Profile("dev")
      @Configuration
      public class DevConfig {
          
          @Bean
          public SomeService someService() {
              // 返回mock實現(xiàn)或開發(fā)環(huán)境特定實現(xiàn)
              return new MockSomeService();
          }
      }
      

      深度解析:DevTools通過類加載器技巧實現(xiàn)了快速應用重啟,同時提供了LiveReload、全局配置、開發(fā)時屬性覆蓋等功能,將開發(fā)效率提升到了新的高度。

      五、Spring Retry

      分布式系統(tǒng)中,網(wǎng)絡抖動、服務短暫不可用是常態(tài)。

      Spring Retry提供了聲明式的重試解決方案。

      基礎重試配置

      @Service
      public class PaymentService {
          
          @Retryable(
              value = {PaymentException.class, NetworkException.class},
              maxAttempts = 3,
              backoff = @Backoff(delay = 1000, multiplier = 2)
          )
          public PaymentResult processPayment(PaymentRequest request) {
              // 調(diào)用支付網(wǎng)關
              return paymentGateway.process(request);
          }
          
          @Recover
          public PaymentResult recover(PaymentException e, PaymentRequest request) {
              // 重試全部失敗后的恢復邏輯
              log.error("支付處理失敗,進入恢復邏輯", e);
              return PaymentResult.failed("支付處理暫時不可用");
          }
      }
      
      // 配置類
      @Configuration
      @EnableRetry
      public class RetryConfig {
          
          @Bean
          public RetryTemplate retryTemplate() {
              return RetryTemplate.builder()
                      .maxAttempts(5)
                      .exponentialBackoff(1000, 2, 10000)
                      .retryOn(RemoteAccessException.class)
                      .traversingCauses()
                      .build();
          }
      }
      

      高級重試策略

      @Component
      public class CircuitBreakerRetryListener extends RetryListenerSupport {
          
          private final CircuitBreaker circuitBreaker;
          
          public CircuitBreakerRetryListener() {
              this.circuitBreaker = CircuitBreaker.ofDefaults("payment-service");
          }
          
          @Override
          public <T, E extends Throwable> void onError(
                  RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
              
              // 記錄失敗,可能觸發(fā)熔斷
              circuitBreaker.onError(throwable);
              
              if (circuitBreaker.tryAcquirePermission()) {
                  log.warn("重試失敗,但熔斷器仍允許繼續(xù)嘗試");
              } else {
                  log.error("重試失敗,熔斷器已打開,停止重試");
                  context.setExhaustedOnly(); // 標記為耗盡,停止重試
              }
          }
      }
      

      深度解析:Spring Retry的核心在于其靈活的重試策略和退避機制。

      通過@Retryable和@Recover注解,我們可以用聲明式的方式處理各種暫時性故障,提高系統(tǒng)的容錯能力。

      六、Spring Cache

      有些小伙伴可能還在手動管理緩存,Spring Cache提供了統(tǒng)一的緩存抽象。

      多緩存管理器配置

      @Configuration
      @EnableCaching
      public class CacheConfig {
          
          @Bean
          @Primary
          public CacheManager redisCacheManager(RedisConnectionFactory factory) {
              RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                      .entryTtl(Duration.ofMinutes(30))
                      .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                      .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
              
              return RedisCacheManager.builder(factory)
                      .cacheDefaults(config)
                      .withInitialCacheConfigurations(Collections.singletonMap(
                          "users", 
                          RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1))
                      ))
                      .transactionAware()
                      .build();
          }
          
          @Bean
          public CacheManager caffeineCacheManager() {
              CaffeineCacheManager cacheManager = new CaffeineCacheManager();
              cacheManager.setCaffeine(Caffeine.newBuilder()
                      .expireAfterWrite(Duration.ofMinutes(10))
                      .maximumSize(1000));
              return cacheManager;
          }
      }
      
      // 使用示例
      @Service
      public class UserService {
          
          @Cacheable(value = "users", key = "#id", unless = "#result == null")
          public User getUserById(Long id) {
              // 數(shù)據(jù)庫查詢
              return userRepository.findById(id).orElse(null);
          }
          
          @Cacheable(value = "users", key = "#username", cacheManager = "caffeineCacheManager")
          public User getUserByUsername(String username) {
              return userRepository.findByUsername(username);
          }
          
          @CacheEvict(value = "users", key = "#user.id")
          public void updateUser(User user) {
              userRepository.save(user);
          }
          
          @Caching(evict = {
              @CacheEvict(value = "users", key = "#user.id"),
              @CacheEvict(value = "users", key = "#user.username")
          })
          public void deleteUser(User user) {
              userRepository.delete(user);
          }
      }
      

      深度解析:Spring Cache的價值在于它提供了統(tǒng)一的緩存抽象層,讓我們可以在不同的緩存實現(xiàn)(Redis、Caffeine、Ehcache等)之間無縫切換,同時保持業(yè)務代碼的純凈性。

      七、Spring Boot Test

      測試是保證代碼質(zhì)量的關鍵,Spring Boot Test提供了全方位的測試支持。

      分層測試策略

      // 1. 單元測試 - 不啟動Spring容器
      @ExtendWith(MockitoExtension.class)
      class UserServiceUnitTest {
          
          @Mock
          private UserRepository userRepository;
          
          @InjectMocks
          private UserService userService;
          
          @Test
          void shouldReturnUserWhenExists() {
              // given
              User expected = new User(1L, "john");
              when(userRepository.findById(1L)).thenReturn(Optional.of(expected));
              
              // when
              User actual = userService.getUserById(1L);
              
              // then
              assertThat(actual).isEqualTo(expected);
              verify(userRepository).findById(1L);
          }
      }
      
      // 2. 切片測試 - 只啟動部分容器
      @DataJpaTest
      @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
      class UserRepositoryTest {
          
          @Autowired
          private TestEntityManager entityManager;
          
          @Autowired
          private UserRepository userRepository;
          
          @Test
          void shouldFindByUsername() {
              // given
              User user = new User(null, "john", "john@example.com");
              entityManager.persistAndFlush(user);
              
              // when
              User found = userRepository.findByUsername("john");
              
              // then
              assertThat(found.getEmail()).isEqualTo("john@example.com");
          }
      }
      
      // 3. 集成測試 - 啟動完整容器
      @SpringBootTest
      @ActiveProfiles("test")
      class UserServiceIntegrationTest {
          
          @Autowired
          private UserService userService;
          
          @Autowired
          private TestRestTemplate restTemplate;
          
          @MockBean
          private EmailService emailService;
          
          @Test
          void shouldCreateUserAndSendEmail() {
              // given
              UserCreateRequest request = new UserCreateRequest("john", "john@example.com");
              doNothing().when(emailService).sendWelcomeEmail(anyString());
              
              // when
              User user = userService.createUser(request);
              
              // then
              assertThat(user.getUsername()).isEqualTo("john");
              verify(emailService).sendWelcomeEmail("john@example.com");
          }
          
          @Test
          void shouldReturnUserViaRest() {
              // when
              ResponseEntity<User> response = restTemplate.getForEntity("/users/1", User.class);
              
              // then
              assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
              assertThat(response.getBody()).isNotNull();
          }
      }
      

      測試配置優(yōu)化

      @TestConfiguration
      public class TestConfig {
          
          @Bean
          @Primary
          public DataSource testDataSource() {
              // 使用H2內(nèi)存數(shù)據(jù)庫進行測試
              return new EmbeddedDatabaseBuilder()
                      .setType(EmbeddedDatabaseType.H2)
                      .addScript("classpath:test-schema.sql")
                      .addScript("classpath:test-data.sql")
                      .build();
          }
      }
      

      深度解析:Spring Boot Test的核心價值在于它的分層測試理念。

      通過不同的測試注解,我們可以精確控制測試的范圍和復雜度,在測試效率和覆蓋度之間找到最佳平衡。

      八、Spring Boot Starter

      有些小伙伴可能想封裝自己的通用功能,自定義Starter是最佳實踐。

      創(chuàng)建自定義Starter

      // 自動配置類
      @Configuration
      @ConditionalOnClass(MyService.class)
      @EnableConfigurationProperties(MyServiceProperties.class)
      @AutoConfigureAfter(DataSourceAutoConfiguration.class)
      public class MyServiceAutoConfiguration {
          
          @Bean
          @ConditionalOnMissingBean
          public MyService myService(MyServiceProperties properties) {
              return new MyService(properties);
          }
          
          @Bean
          @ConditionalOnProperty(name = "my.service.metrics.enabled", havingValue = "true")
          public MyServiceMetrics myServiceMetrics() {
              return new MyServiceMetrics();
          }
      }
      
      // 配置屬性類
      @ConfigurationProperties(prefix = "my.service")
      public class MyServiceProperties {
          
          private String endpoint = "http://localhost:8080";
          private Duration timeout = Duration.ofSeconds(30);
          private int maxConnections = 100;
          
          // getters and setters
      }
      
      // spring.factories文件
      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.example.myservice.MyServiceAutoConfiguration
      

      條件化Bean配置

      @Configuration
      public class ConditionalBeans {
          
          @Bean
          @ConditionalOnWebApplication
          public WebSpecificBean webSpecificBean() {
              return new WebSpecificBean();
          }
          
          @Bean
          @ConditionalOnNotWebApplication
          public NonWebBean nonWebBean() {
              return new NonWebBean();
          }
          
          @Bean
          @ConditionalOnBean(DataSource.class)
          public DataSourceAwareBean dataSourceAwareBean() {
              return new DataSourceAwareBean();
          }
      }
      

      深度解析:自定義Starter是SpringBoot生態(tài)擴展的核心機制。

      通過合理的自動配置和條件化加載,我們可以創(chuàng)建出即插即用的功能模塊,極大提升代碼復用性。

      九、Spring Boot Admin

      雖然Actuator提供了監(jiān)控端點,但Spring Boot Admin提供了更友好的管理界面。

      服務端配置

      @Configuration
      @EnableAdminServer
      public class AdminServerConfig {
          
          @Bean
          public Notifier notifier() {
              return new RemindingNotifier(
                  new FilteringNotifier(
                      new LoggingNotifier(),
                      (instanceEvent) -> instanceEvent.getType() == StatusChangeEvent.TYPE
                  ),
                  AdminServerNotifier::shouldNotify,
                  Duration.ofMinutes(10)
              );
          }
      }
      
      // 客戶端配置
      @Configuration
      public class AdminClientConfig {
          
          @Bean
          public SecurityContext securityContext() {
              return SecurityContext.builder()
                      .username("admin")
                      .password("secret")
                      .build();
          }
      }
      

      十、Spring Boot CLI

      對于快速驗證想法或創(chuàng)建原型,Spring Boot CLI提供了極致的開發(fā)體驗。

      CLI示例

      # 創(chuàng)建簡單的Web應用
      echo '@RestController class App { @RequestMapping("/") String home() { "Hello World" } }' > app.groovy
      
      # 運行應用
      spring run app.groovy
      
      # 添加依賴
      spring install com.example:my-starter:1.0.0
      
      # 打包應用
      spring jar myapp.jar *.groovy
      

      自定義CLI命令

      @Component
      @Order(0)
      public class MyCommand implements CommandLineRunner {
          
          private final ApplicationContext context;
          
          public MyCommand(ApplicationContext context) {
              this.context = context;
          }
          
          @Override
          public void run(String... args) throws Exception {
              if (args.length > 0 && "init".equals(args[0])) {
                  // 初始化邏輯
                  System.out.println("Initializing application...");
                  initializeDatabase();
                  loadSampleData();
              }
          }
          
          private void initializeDatabase() {
              // 數(shù)據(jù)庫初始化邏輯
          }
      }
      

      深度解析:Spring Boot CLI的核心價值在于它極大降低了Spring應用的入門門檻,通過Groovy腳本和自動依賴管理,讓開發(fā)者可以專注于業(yè)務邏輯而不是配置。

      總結

      我們可以總結出SpringBoot設計的核心理念:

      1. 約定優(yōu)于配置

      通過合理的默認值和自動配置,SpringBoot讓開發(fā)者從繁瑣的配置中解放出來。

      2. 模塊化設計

      每個Starter都是自包含的功能模塊,可以按需引入,保持應用的輕量。

      3. 生產(chǎn)就緒

      從監(jiān)控到管理,從健康檢查到指標收集,SpringBoot為生產(chǎn)環(huán)境提供了完整解決方案。

      4. 開發(fā)者友好

      無論是DevTools的熱加載,還是CLI的快速原型,都體現(xiàn)了對開發(fā)者體驗的重視。

      有些小伙伴可能會問:為什么要花時間學習這些"神器"?

      我的回答是:

      1. 效率提升:正確使用這些工具可以讓開發(fā)效率提升數(shù)倍。
      2. 代碼質(zhì)量:統(tǒng)一的抽象和最佳實踐提高了代碼質(zhì)量和可維護性。
      3. 系統(tǒng)穩(wěn)定性:完善的監(jiān)控和運維工具保障了系統(tǒng)穩(wěn)定性。
      4. 團隊協(xié)作:統(tǒng)一的開發(fā)模式和工具鏈促進了團隊協(xié)作。

      技術選型的真諦不在于追求最新最炫的技術,而在于選擇最適合團隊和業(yè)務的技術棧

      SpringBoot的這些"神器"之所以珍貴,正是因為它們經(jīng)過了大量生產(chǎn)實踐的檢驗,在功能和易用性之間找到了完美平衡。

      希望這篇文章能夠幫助你更好地理解和運用SpringBoot,讓你的開發(fā)之路更加順暢高效。

      最后說一句(求關注,別白嫖我)

      如果這篇文章對您有所幫助,或者有所啟發(fā)的話,幫忙關注一下我的同名公眾號:蘇三說技術,您的支持是我堅持寫作最大的動力。

      求一鍵三連:點贊、轉發(fā)、在看。

      關注公眾號:【蘇三說技術】,在公眾號中回復:進大廠,可以免費獲取我最近整理的10萬字的面試寶典,好多小伙伴靠這個寶典拿到了多家大廠的offer。

      更多經(jīng)常內(nèi)容在我的技術網(wǎng)站:http://www.susan.net.cn

      posted @ 2025-10-13 09:38  蘇三說技術  閱讀(1174)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 久久精品国产免费观看频道| 日本一区不卡高清更新二区| 国产精品一区在线蜜臀| 少妇人妻偷人免费观看| 亚洲香蕉av一区二区蜜桃| 国产成熟妇女性视频电影| 乌鲁木齐市| 国产精品揄拍一区二区久久 | 中文字幕结果国产精品| 大地资源高清免费观看| 日韩精品一区二区三区中文无码 | 日韩中文字幕有码av| 亚洲a成人片在线观看| 色8久久人人97超碰香蕉987| 国产精品国产精品国产专区| 国产成人一区二区视频免费| 一本一道av中文字幕无码| 国产精品毛片一区二区| 亚洲WWW永久成人网站| 中文字幕精品亚洲无线码二区| 国产精品伊人久久综合网| 日韩精品中文字幕有码| 国产成人欧美一区二区三区 | 亚洲男同志网站| 国产熟女一区二区三区四区| 国产精品一区二区三区蜜臀| 亚洲亚洲人成综合网络| 国产超高清麻豆精品传媒麻豆精品| 国产漂亮白嫩美女在线观看| 国产精品亚洲一区二区三区喷水 | 本道久久综合无码中文字幕| 97一区二区国产好的精华液| 久久亚洲精品成人av无| 国产午夜三级一区二区三| 国产精品熟女亚洲av麻豆| 不卡国产一区二区三区| 在线观看免费人成视频色9| 偷拍美女厕所尿尿嘘嘘小便| 精品少妇av蜜臀av| 成人午夜av在线播放| 亚洲肥熟女一区二区三区|