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

自定義注解!絕對是程序員裝逼的利器!!

開發 后端
本文,就來介紹幾個,作者在開發中實際用到的幾個例子,向你介紹下如何使用注解來提升你代碼的逼格。

[[351399]]

 相信很多人對Java中的注解都很熟悉,比如我們經常會用到的一些如@Override、@Autowired、@Service等,這些都是JDK或者諸如Spring這類框架給我們提供的。

在以往的面試過程中,我發現,關于注解的知識很多程序員都僅僅停留在使用的層面上,很少有人知道注解是如何實現的,更別提使用自定義注解來解決實際問題了。

但是其實,我覺得一個好的程序員的標準就是懂得如何優化自己的代碼,那在代碼優化上面,如何精簡代碼,去掉重復代碼就是一個至關重要的話題,在這個話題領域,自定義注解絕對可以算得上是一個大大的功臣。

所以,在我看來,會使用自定義注解 ≈ 好的程序員。

那么,本文,就來介紹幾個,作者在開發中實際用到的幾個例子,向你介紹下如何使用注解來提升你代碼的逼格。

基本知識

在Java中,注解分為兩種,元注解和自定義注解。

很多人誤以為自定義注解就是開發者自己定義的,而其它框架提供的不算,但是其實上面我們提到的那幾個注解其實都是自定義注解。

關于"元"這個描述,在編程世界里面有都很多,比如"元注解"、"元數據"、"元類"、"元表"等等,這里的"元"其實都是從meta翻譯過來的。

一般我們把元注解理解為描述注解的注解,元數據理解為描述數據的數據,元類理解為描述類的類…

所以,在Java中,除了有限的幾個固定的"描述注解的注解"以外,所有的注解都是自定義注解。

在JDK中提供了4個標準的用來對注解類型進行注解的注解類(元注解),他們分別是: 

  1. @Target  
  2. @Retention  
  3. @Documented  
  4. @Inherited 

除了以上這四個,所有的其他注解全部都是自定義注解。

這里不準備深入介紹以上四個元注解的作用,大家可以自行學習。

本文即將提到的幾個例子,都是作者在日常工作中真實使用到的場景,這例子有一個共同點,那就是都用到了Spring的AOP技術。

什么是AOP以及他的用法相信很多人都知道,這里也就不展開介紹了。

使用自定義注解做日志記錄

不知道大家有沒有遇到過類似的訴求,就是希望在一個方法的入口處或者出口處做統一的日志處理,比如記錄一下入參、出參、記錄下方法執行的時間等。

如果在每一個方法中自己寫這樣的代碼的話,一方面會有很多代碼重復,另外也容易被遺漏。

這種場景,就可以使用自定義注解+切面實現這個功能。

假設我們想要在一些web請求的方法上,記錄下本次操作具體做了什么事情,比如新增了一條記錄或者刪除了一條記錄等。

首先我們自定義一個注解: 

  1. /**  
  2.  * Operate Log 的自定義注解  
  3.  */  
  4. @Target(ElementType.METHOD)  
  5. @Retention(RetentionPolicy.RUNTIME)  
  6. public @interface OpLog {  
  7.     /** 
  8.      * 業務類型,如新增、刪除、修改  
  9.      * @return  
  10.      */  
  11.     public OpType opType();  
  12.     /**  
  13.      * 業務對象名稱,如訂單、庫存、價格  
  14.      * @return 
  15.      */  
  16.     public String opItem();  
  17.     /**  
  18.      * 業務對象編號表達式,描述了如何獲取訂單號的表達式  
  19.      * @return  
  20.      */  
  21.     public String opItemIdExpression();  

因為我們不僅要在日志中記錄本次操作了什么,還需要知道被操作的對象的具體的唯一性標識,如訂單號信息。

但是每一個接口方法的參數類型肯定是不一樣的,很難有一個統一的標準,那么我們就可以借助Spel表達式,即在表達式中指明如何獲取對應的對象的唯一性標識。

有了上面的注解,接下來就可以寫切面了。主要代碼如下: 

  1. /**  
  2.  * OpLog的切面處理類,用于通過注解獲取日志信息,進行日志記錄  
  3.  * @author Hollis  
  4.  */ 
  5. @Aspect  
  6. @Component  
  7. public class OpLogAspect {  
  8.     private static final Logger LOGGER = LoggerFactory.getLogger(OpLogAspect.class);  
  9.     @Autowired  
  10.     HttpServletRequest request;  
  11.     @Around("@annotation(com.hollis.annotation.OpLog)")  
  12.     public Object log(ProceedingJoinPoint pjp) throws Exception {  
  13.         Method method = ((MethodSignature)pjp.getSignature()).getMethod();  
  14.         OpLog opLog = method.getAnnotation(OpLog.class);  
  15.         Object response = null 
  16.         try {  
  17.             // 目標方法執行  
  18.             response = pjp.proceed();  
  19.         } catch (Throwable throwable) {  
  20.             throw new Exception(throwable);  
  21.         }   
  22.         if (StringUtils.isNotEmpty(opLog.opItemIdExpression())) {  
  23.             SpelExpressionParser parser = new SpelExpressionParser();  
  24.             Expression expression = parser.parseExpression(opLog.opItemIdExpression());  
  25.             EvaluationContext context = new StandardEvaluationContext();  
  26.             // 獲取參數值  
  27.             Object[] args = pjp.getArgs();  
  28.             // 獲取運行時參數的名稱  
  29.             LocalVariableTableParameterNameDiscoverer discoverer  
  30.                 = new LocalVariableTableParameterNameDiscoverer();  
  31.             String[] parameterNames = discoverer.getParameterNames(method);  
  32.             // 將參數綁定到context中  
  33.             if (parameterNames != null) {  
  34.                 for (int i = 0; i < parameterNames.length; i++) {  
  35.                     context.setVariable(parameterNames[i], args[i]); 
  36.                  }  
  37.             }  
  38.             // 將方法的resp當做變量放到context中,變量名稱為該類名轉化為小寫字母開頭的駝峰形式  
  39.             if (response != null) {  
  40.                 context.setVariable(  
  41.                     CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, response.getClass().getSimpleName()),  
  42.                     response);  
  43.             }  
  44.             // 解析表達式,獲取結果  
  45.             String itemId = String.valueOf(expression.getValue(context));  
  46.             // 執行日志記錄 
  47.             handle(opLog.opType(), opLog.opItem(), itemId);  
  48.         }  
  49.         return response; 
  50.     }  
  51.     private void handle(OpType opType,  String opItem, String opItemId) {  
  52.       // 通過日志打印輸出  
  53.       LOGGER.info("opType = " + opType.name() +",opItem = " +opItem + ",opItemId = " +opItemId);  
  54.     }  

以上切面中,有幾個點需要大家注意的:

    1、使用@Around注解來指定對標注了OpLog的方法設置切面。

    2、使用Spel的相關方法,通過指定的表示,從對應的參數中獲取到目標對象的唯一性標識。

    3、再方法執行成功后,輸出日志。

有了以上的切面及注解后,我們只需要在對應的方法上增加注解標注即可,如: 

  1. @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})  
  2. @OpLog(opType = OpType.QUERY, opItem = "order"opItemIdExpression = "#id" 
  3. public @ResponseBody  
  4. HashMap view(@RequestParam(name = "id") String id)  
  5.     throws Exception {  

上面這種是入參的參數列表中已經有了被操作的對象的唯一性標識,直接使用#id指定即可。

如果被操作的對象的唯一性標識不在入參列表中,那么可能是入參的對象中的某一個屬性,用法如下: 

  1. @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})  
  2. @OpLog(opType = OpType.QUERY, opItem = "order"opItemIdExpression = "#orderVo.id" 
  3. public @ResponseBody  
  4. HashMap update(OrderVO orderVo)  
  5.     throws Exception {  

以上,即可從入參的OrderVO對象的id屬性的值獲取。

如果我們要記錄的唯一性標識,在入參中沒有的話,應該怎么辦呢?最典型的就是插入方法,插入成功之前,根本不知道主鍵ID是什么,這種怎么辦呢?

我們上面的切面中,做了一件事情,就是我們把方法的返回值也會使用表達式進行一次解析,如果可以解析得到具體的值,也是可以。如以下寫法: 

  1. @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})  
  2. @OpLog(opType = OpType.QUERY, opItem = "order"opItemIdExpression = "#insertResult.id" 
  3. public @ResponseBody  
  4. InsertResult insert(OrderVO orderVo)  
  5.     throws Exception {  
  6.     return orderDao.insert(orderVo);  

以上,就是一個簡單的使用自定義注解+切面進行日志記錄的場景。下面我們再來看一個如何使用注解做方法參數的校驗。

使用自定義注解做前置檢查

當我們對外部提供接口的時候,會對其中的部分參數有一定的要求,比如某些參數值不能為空等。大多數情況下我們都需要自己主動進行校驗,判斷對方傳入的值是否合理。

這里推薦一個使用HibernateValidator + 自定義注解 + AOP實現參數校驗的方式。

首先我們會有一個具體的入參類,定義如下: 

  1. public class User {  
  2.     private String idempotentNo;  
  3.     @NotNull(  
  4.         message = "userName can't be null"  
  5.     )  
  6.     private String userName;  

以上,對userName參數注明不能為null。

然后再使用Hibernate Validator定義一個工具類,用于做參數校驗。 

  1. /**  
  2.  * 參數校驗工具  
  3.  * @author Hollis  
  4.  */  
  5. public class BeanValidator {  
  6.     private static Validator validator = Validation.byProvider(HibernateValidator.class).configure().failFast(true)  
  7.         .buildValidatorFactory().getValidator();  
  8.     /**  
  9.      * @param object object  
  10.      * @param groups groups  
  11.      */  
  12.     public static void validateObject(Object object, Class<?>... groups) throws ValidationException {  
  13.         Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups); 
  14.         if (constraintViolations.stream().findFirst().isPresent()) {  
  15.             throw new ValidationException(constraintViolations.stream().findFirst().get().getMessage());  
  16.         }  
  17.     }  

以上代碼,會對一個bean進行校驗,一旦失敗,就會拋出ValidationException。

接下來定義一個注解: 

  1. /**  
  2.  * facade接口注解, 用于統一對facade進行參數校驗及異常捕獲  
  3.  * <pre> 
  4.  *      注意,使用該注解需要注意,該方法的返回值必須是BaseResponse的子類  
  5.  * </pre>  
  6.  */  
  7. @Target(ElementType.METHOD)  
  8. @Retention(RetentionPolicy.RUNTIME)  
  9. public @interface Facade {  

這個注解里面沒有任何參數,只用于標注那些方法要進行參數校驗。

接下來定義切面: 

  1. /**  
  2.  * Facade的切面處理類,統一統計進行參數校驗及異常捕獲  
  3.  * @author Hollis  
  4.  */ 
  5.  @Aspect  
  6. @Component  
  7. public class FacadeAspect {  
  8.     private static final Logger LOGGER = LoggerFactory.getLogger(FacadeAspect.class);  
  9.     @Autowired  
  10.     HttpServletRequest request;  
  11.     @Around("@annotation(com.hollis.annotation.Facade)")  
  12.     public Object facade(ProceedingJoinPoint pjp) throws Exception {  
  13.         Method method = ((MethodSignature)pjp.getSignature()).getMethod();  
  14.         Object[] args = pjp.getArgs();  
  15.         Class returnType = ((MethodSignature)pjp.getSignature()).getMethod().getReturnType();  
  16.         //循環遍歷所有參數,進行參數校驗  
  17.         for (Object parameter : args) {  
  18.             try {  
  19.                 BeanValidator.validateObject(parameter);  
  20.             } catch (ValidationException e) {  
  21.                 return getFailedResponse(returnType, e);  
  22.             }  
  23.         }  
  24.         try {  
  25.             // 目標方法執行  
  26.             Object response = pjp.proceed();  
  27.             return response;  
  28.         } catch (Throwable throwable) {  
  29.             return getFailedResponse(returnType, throwable);  
  30.         }  
  31.     }  
  32.     /**  
  33.      * 定義并返回一個通用的失敗響應  
  34.      */  
  35.     private Object getFailedResponse(Class returnType, Throwable throwable)  
  36.         throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {  
  37.         //如果返回值的類型為BaseResponse 的子類,則創建一個通用的失敗響應  
  38.         if (returnType.getDeclaredConstructor().newInstance() instanceof BaseResponse) {  
  39.             BaseResponse response = (BaseResponse)returnType.getDeclaredConstructor().newInstance();  
  40.             response.setSuccess(false);  
  41.             response.setResponseMessage(throwable.toString());  
  42.             response.setResponseCode(GlobalConstant.BIZ_ERROR);  
  43.             return response;  
  44.         }  
  45.         LOGGER.error(  
  46.             "failed to getFailedResponse , returnType (" + returnType + ") is not instanceof BaseResponse");  
  47.         return null;  
  48.     }  

以上代碼,和前面的切面有點類似,主要是定義了一個切面,會對所有標注@Facade的方法進行統一處理,即在開始方法調用前進行參數校驗,一旦校驗失敗,則返回一個固定的失敗的Response。

特別需要注意的是,這里之所以可以返回一個固定的BaseResponse,是因為我們會要求我們的所有對外提供的接口的response必須繼承BaseResponse類,這個類里面會定義一些默認的參數,如錯誤碼等。

之后,只需要對需要參數校驗的方法增加對應注解即可: 

  1. @Facade  
  2. public TestResponse query(User user) {  

這樣,有了以上注解和切面,我們就可以對所有的對外方法做統一的控制了。

其實,以上這個facadeAspect我省略了很多東西,我們真正使用的那個切面,不僅僅做了參數檢查,還可以做很多其他事情。比如異常的統一處理、錯誤碼的統一轉換、記錄方法執行時長、記錄方法的入參出參等等。

總之,使用切面+自定義注解,我們可以統一做很多事情。除了以上的這幾個場景,我們還有很多相似的用法,比如:

統一的緩存處理。如某些操作需要在操作前查緩存、操作后更新緩存。這種就可以通過自定義注解+切面的方式統一處理。

代碼其實都差不多,思路也比較簡單,就是通過自定義注解來標注需要被切面處理的累或者方法,然后在切面中對方法的執行過程進行干預,比如在執行前或者執行后做一些特殊的操作。

使用這種方式可以大大減少重復代碼,大大提升代碼的優雅性,方便我們使用。

但是同時也不能過度使用,因為注解看似簡單,但是其實內部有很多邏輯是容易被忽略的。就像我之前寫過一篇《Spring官方都推薦使用的@Transactional事務,為啥我不建議使用!》中提到的觀點一樣,無腦的使用切面和注解,可能會引入一些不必要的問題。

不管怎么說,自定義注解卻是是一個很好的發明,可以減少很多重復代碼。快快在你的項目中用起來吧。 

 

責任編輯:龐桂玉 來源: Hollis
相關推薦

2015-07-28 17:58:22

程序員指南

2022-11-10 10:29:07

KPI軟件開發

2020-07-24 07:44:10

程序員思維逆向

2017-03-07 15:25:51

2024-10-14 17:18:27

2020-07-16 10:19:43

程序員技能開發者

2015-04-10 19:37:34

程序員

2024-08-16 08:38:48

2015-04-03 11:15:32

程序員如何寫簡歷寫簡歷技巧

2021-12-30 12:30:01

Java注解編譯器

2023-10-11 07:57:23

springboot微服務

2023-10-24 13:48:50

自定義注解舉值驗證

2015-06-25 10:07:12

程序員

2018-04-02 11:19:20

MacAppleScript代碼

2019-04-10 16:17:02

程序員結構源代碼

2024-12-27 15:37:23

2022-02-17 07:10:39

Nest自定義注解

2021-02-20 13:55:35

程序員計算機技術

2013-08-20 09:33:59

程序員

2009-06-02 13:43:04

程序員定義職場
點贊
收藏

51CTO技術棧公眾號

av一区二区三区免费观看| 国产成人精品日本亚洲专区61| 黄色a级三级三级三级| 免费污视频在线| 91在线观看地址| 国产精品久久久久一区二区| 国产日韩欧美在线观看视频| 久久亚洲道色| 欧美美女一区二区| 久久久久久人妻一区二区三区| 天天操天天干天天| 九色综合狠狠综合久久| 国模私拍视频一区| 美女福利视频网| 三级小说欧洲区亚洲区| 欧美肥妇毛茸茸| 97av视频在线观看| 污片视频在线免费观看| 欧美国产综合一区二区| 国产精品毛片一区视频| 国产视频在线免费观看| 久久久精品网| 91高清视频在线免费观看| 人人干在线观看| 激情综合网五月| 亚洲成人av在线| 亚洲天堂一区二区在线观看| 日本免费久久| 亚洲欧美欧美一区二区三区| 相泽南亚洲一区二区在线播放 | 欧美性受ⅹ╳╳╳黑人a性爽| 国产色综合久久| 国产日本一区二区三区| japanese国产| 紧缚奴在线一区二区三区| 日韩av片免费在线观看| 美日韩一二三区| 尹人成人综合网| 欧美日韩电影在线观看| 国产午夜精品理论片| 热久久天天拍国产| 国产亚洲精品久久久| 超碰97在线资源站| 风间由美性色一区二区三区四区 | 黄色在线网站| 久久影音资源网| 久久久com| 亚洲欧美色视频| 99re成人在线| 久久精品五月婷婷| 天堂av网在线| 久久久亚洲精品石原莉奈| 蜜桃久久影院| 美国成人毛片| 国产欧美一区二区精品婷婷 | 在线观看亚洲精品视频| 凹凸日日摸日日碰夜夜爽1| 欧洲一区精品| 日本久久一区二区| 国产精品视频中文字幕| 黄色欧美视频| 欧美一区二区三区日韩| 伊人av在线播放| 成人h动漫精品一区二区器材| 精品对白一区国产伦| 国产精品扒开腿做爽爽爽a片唱戏| 卡通动漫国产精品| 亚洲欧洲在线免费| 国产精品18在线| 亚洲一区二区三区| 久久琪琪电影院| 亚洲综合久久网| 捆绑紧缚一区二区三区视频| 成人午夜小视频| 亚洲国产精品久久久久爰性色| 99久久精品免费看国产| 欧美亚洲另类久久综合| aiai在线| 亚洲线精品一区二区三区八戒| 奇米影视亚洲色图| 欧美精品高清| 欧美成人伊人久久综合网| 中文文字幕文字幕高清| 国产中文精品久高清在线不| 日韩一区二区在线视频| 日韩乱码一区二区| 日韩激情视频网站| 亚洲最大成人网色| 青青青免费视频在线2| 国产精品丝袜黑色高跟| 免费网站永久免费观看| 欧美黑人一区| 欧美一区二区播放| 国产精品成人一区二区三区电影毛片 | 美女诱惑一区二区| 国产精品久久亚洲| 在线观看av黄网站永久| 亚洲一区二区偷拍精品| 色婷婷综合久久久久中文字幕| 久久久久久久久久久久电影| 日韩毛片在线观看| 性欧美videos| 日韩中文字幕区一区有砖一区| 91免费看蜜桃| 春暖花开成人亚洲区| 亚洲国产精品久久久久秋霞影院| 青青在线免费观看视频| 最新精品在线| 久久久成人的性感天堂| 欧美一区二区三区四| 国产乱码精品一区二区三区忘忧草| 蜜桃麻豆91| 草草影院在线| 91精品国产91久久久久久一区二区 | 国产一区99| 欧美精品日韩三级| 亚洲一级黄色大片| 久久精品视频在线看| 分分操这里只有精品| www一区二区三区| 宅男66日本亚洲欧美视频| 久久久精品视频免费| 国产一二三精品| 亚洲aⅴ天堂av在线电影软件| 亚洲欧美一区二区三区| 精品国产不卡一区二区三区| 国产成人av免费在线观看| 蜜臀av一区二区在线观看| 欧美精品欧美精品| 精品三级久久| 精品久久久久一区二区国产| 久久国产波多野结衣| 美女www一区二区| 日韩中文字幕av在线| 天堂av中文在线观看| 亚洲精品国产免费| 国产成人啪精品午夜在线观看| 国产成人在线视频播放| 99精品一级欧美片免费播放| 先锋影音一区二区| 中文字幕一精品亚洲无线一区| 午夜视频网站在线观看| 国产日韩成人精品| 日本美女高潮视频| 国产尤物久久久| 国产精品一区av| 在线日本视频| 7777精品伊人久久久大香线蕉完整版| 国产一级淫片久久久片a级| 蜜桃传媒麻豆第一区在线观看| 水蜜桃亚洲一二三四在线| 成人国产一区| 久久视频在线免费观看| av高清一区二区| 亚洲最大成人网4388xx| 国产一线在线观看| 夜久久久久久| 日韩成人在线资源| 欧美伊人亚洲伊人色综合动图| 少妇高潮 亚洲精品| 99这里有精品视频| 午夜视频一区在线观看| 欧美图片一区二区| 蜜桃91丨九色丨蝌蚪91桃色| 在线观看日韩片| 日韩欧美另类中文字幕| 性色av一区二区咪爱| 丝袜视频国产在线播放| 欧美视频一区二区三区四区| av最新在线观看| 懂色av中文字幕一区二区三区| 成 年 人 黄 色 大 片大 全| 国产精品亚洲片在线播放| 国产日韩欧美中文在线播放| 好操啊在线观看免费视频| 日韩欧美视频在线| 日本午夜视频在线观看| 欧美激情中文字幕一区二区| 欧美体内she精高潮| 99精品视频网| 天堂资源在线亚洲资源| 亚洲伊人影院| 日韩av免费在线观看| 99自拍视频在线观看| 日韩av影院在线观看| 中国女人一级一次看片| 一区av在线播放| 性欧美精品中出| 国产乱码精品一区二区三区五月婷| 欧美v在线观看| 66视频精品| 欧美日韩亚洲一区二区三区在线观看| crdy在线观看欧美| 日本久久久久久| 欧美人与牲禽动交com| 在线视频精品一| 狠狠躁夜夜躁av无码中文幕| 欧美视频自拍偷拍| 国产成人无码一区二区三区在线| 国产精品欧美综合在线| 看全色黄大色黄女片18| 国模大尺度一区二区三区| 国模无码视频一区二区三区| 最新精品国产| 日韩精品无码一区二区三区| 红杏aⅴ成人免费视频| 国产欧美一区二区三区在线看| 松下纱荣子在线观看| 欧美乱大交做爰xxxⅹ性3| 91av资源在线| 亚洲美女av电影| 黄色av一区二区三区| 在线成人免费视频| 福利网址在线观看| 欧美日韩国产中文精品字幕自在自线| 国精产品一区一区二区三区mba| 久久久国产一区二区三区四区小说| 一区二区三区人妻| 久久国内精品视频| 91网址在线播放| 久久高清国产| 无码精品国产一区二区三区免费| 欧美三级网页| 精品无码av无码免费专区| 日韩理论片av| 四虎永久在线精品免费一区二区| 天堂99x99es久久精品免费| 国产91免费视频| 久久国产精品免费一区二区三区| 国产在线精品一区免费香蕉| 亚洲精品555| 国产精品高潮呻吟久久av野狼| 欧美裸体视频| 欧美综合激情网| 亚洲精品中文字幕| 欧美一区二区.| 欧美aa视频| 日韩美女激情视频| 黄色综合网址| 国产成人精品午夜| 亚洲天堂一区二区| 日韩免费在线免费观看| 日本免费一区二区三区四区| 日本在线精品视频| 美女一区网站| 国产精品劲爆视频| 精品欧美日韩精品| 成人福利在线观看| 国产亚洲精aa在线看| 亚洲xxxx视频| 国产精品中文字幕制服诱惑| 国外成人免费视频| 亚洲va久久| 亚洲欧美日韩国产成人综合一二三区| 日韩大片在线| 国产在线无码精品| 亚洲精选久久| 99视频精品免费| 毛片av一区二区| 色综合久久久无码中文字幕波多| 国产成人免费av在线| a级一a一级在线观看| 久久综合色婷婷| 蜜桃av免费观看| 亚洲精品中文在线影院| 欧美一级高潮片| 日韩欧美综合在线视频| 亚洲综合精品国产一区二区三区| 欧美一区二区三区小说| 无码精品一区二区三区在线| 亚洲图片在线综合| 97影院秋霞午夜在线观看| 久久人人爽人人| 欧美成人影院| 91亚洲精品久久久| 牛牛影视一区二区三区免费看| 日本午夜精品一区二区| 99视频精品全国免费| 国产成a人亚洲精v品在线观看| 免费永久网站黄欧美| 91欧美视频在线| 成人激情av网| 黄色国产在线播放| 亚洲午夜在线电影| 成人毛片一区二区三区| 欧美一区二区三区电影| 婷婷丁香一区二区三区| 色偷偷av亚洲男人的天堂| 福利网站在线观看| 国产精品久久av| 国产 日韩 欧美 综合 一区| 亚洲精品在线观看免费| 激情欧美丁香| 久久国产精品国产精品| 波多野结衣91| a在线视频播放观看免费观看| 欧美日韩免费在线观看| 99久久久久成人国产免费| 精品网站999www| 日韩免费影院| 国产精品美女久久久久av超清| 久久九九热re6这里有精品| 亚洲最新在线| 麻豆九一精品爱看视频在线观看免费| 中文字幕55页| 国产精品理论片| 你懂的国产视频| 日韩写真欧美这视频| av网站无病毒在线| 热99在线视频| 精品国产乱子伦一区二区| 天天爱天天做天天操| 日韩激情视频在线观看| 亚洲久久久久久| 亚洲一区av在线| 国产尤物视频在线观看| 国产一区二区欧美日韩| 在线观看爽视频| 国产精品一区二| 综合久久十次| 日韩视频在线观看一区二区三区| 久久九九久久九九| av中文在线播放| 日韩av在线免费观看一区| 色老头在线观看| 91系列在线播放| 国产精品99在线观看| 麻豆一区二区三区视频| 国产校园另类小说区| 日韩欧美成人一区二区三区| 亚洲精品动漫久久久久| 爱看av在线| 国产成人亚洲欧美| 狠色狠色综合久久| zjzjzjzjzj亚洲女人| 亚洲黄色片在线观看| 国产www视频| 美女福利精品视频| 天堂精品在线视频| 国产高清不卡无码视频| 国产黑丝在线一区二区三区| 麻豆网址在线观看| 欧美一区二区观看视频| 午夜成年人在线免费视频| 91国产在线播放| 亚洲国产专区校园欧美| 第四色在线视频| 狠狠综合久久av一区二区小说| 亚洲色图 校园春色| 奇米四色中文综合久久| 欧美欧美黄在线二区| 久久九九国产视频| 国产精品乱码一区二三区小蝌蚪| 国产乡下妇女三片| 日韩中文理论片| 欧洲精品99毛片免费高清观看 | 国产精品女主播一区二区三区| 久久精品女同亚洲女同13| 精品久久久久久国产| 国产免费av高清在线| 国产日韩欧美电影在线观看| 亚洲美女视频| 91传媒理伦片在线观看| 欧美性xxxx在线播放| 9色在线视频网站| 97操在线视频| 国产亚洲精品v| 国产白丝一区二区三区 | 亚洲va天堂va国产va久| 深夜福利视频在线观看| 国产精品扒开腿爽爽爽视频| 国产精品久久观看| 男人网站在线观看| 色噜噜久久综合| www在线观看播放免费视频日本| 成人区精品一区二区| 国产精品久久久免费| 美女100%露胸无遮挡| 日韩三级av在线播放| 中文字幕高清在线播放| 欧美亚洲视频一区| av电影在线观看不卡| 在线观看免费视频一区| 欧美激情二区三区| 精品国产精品| 性农村xxxxx小树林| 欧美日韩一本到| 国产精品vvv| 自拍亚洲欧美老师丝袜| 99视频一区二区三区| 一级片aaaa| 国产91成人在在线播放| 天天做天天爱天天综合网| 中文字幕一区二区久久人妻网站| 欧美日韩黄色一区二区| av成人福利| 四虎影院一区二区| 久久亚洲一级片| 亚洲高清视频在线播放| 国产欧美 在线欧美|