久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

利用Java反射機制實現對象相同字段的復制操作

瀏覽:64日期:2022-08-26 14:57:02

一、如何實現不同類型對象之間的復制問題?

1、為什么會有這個問題?

近來在進行一個項目開發的時候,為了隱藏后端數據庫表結構、同時也為了配合給前端一個更友好的API接口文檔(swagger API文檔),我采用POJO來對應數據表結構,使用VO來給傳遞前端要展示的數據,同時使用DTO來進行請求參數的封裝。以上是一個具體的場景,可以發現這樣子一個現象:POJO、VO、DTO對象是同一個數據的不同視圖,所以會有很多相同的字段,由于不同的地方使用不同的對象,無可避免的會存在對象之間的值遷移問題,遷移的一個特征就是需要遷移的值字段相同。字段相同,于是才有了不同對象之間進行值遷移復制的問題。

2、現有的解決方法

一個一個的get出來后又set進去。這個方法無可避免會增加很多的編碼復雜度,還是一些很沒有營養的代碼,看多了還會煩,所以作為一個有點小追求的程序員都沒有辦法忍受這種摧殘。

使用別人已經存在的工具。在spring包里面有一個可以復制對象屬性的工具方法,可以進行對象值的復制,下一段我們詳細去分析它的這個工具方法。

自己動手豐衣足食。自己造工具來用,之所以自己造工具不是因為喜歡造工具,而是現有的工具沒辦法解決自己的需求,不得已而為之。

二、他山之石可以攻玉,詳談spring的對象復制工具

1、看看spring的對象復制工具到底咋樣?

類名:org.springframework.beans.BeanUtils

這個類里面所有的屬性復制的方法都調用了同一個方法,我們就直接分析這個原始的方法就行了。

/** * Copy the property values of the given source bean into the given target bean. * <p>Note: The source and target classes do not have to match or even be derived * from each other, as long as the properties match. Any bean properties that the * source bean exposes but the target bean does not will silently be ignored. * @param source the source bean:也就是說要從這個對象里面復制值出去 * @param target the target bean:出去就是復制到這里面來 * @param editable the class (or interface) to restrict property setting to:這個類對象是target的父類或其實現的接口,用于控制屬性復制的范圍 * @param ignoreProperties array of property names to ignore:需要忽略的字段 * @throws BeansException if the copying failed * @see BeanWrapper */ private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties) throws BeansException { //這里在校驗要復制的對象是不可以為null的,這兩個方法可是會報錯的!! Assert.notNull(source, 'Source must not be null'); Assert.notNull(target, 'Target must not be null'); //這里和下面的代碼就有意思了 Class<?> actualEditable = target.getClass();//獲取目標對象的動態類型 //下面判斷的意圖在于控制屬性復制的范圍 if (editable != null) { //必須是target對象的父類或者其實現的接口類型,相當于instanceof運算符 if (!editable.isInstance(target)) { throw new IllegalArgumentException('Target class [' + target.getClass().getName() + '] not assignable to Editable class [' + editable.getName() + ']'); } actualEditable = editable; } //不得不說,下面這段代碼乖巧的像綿羊,待我們來分析分析它是如何如何乖巧的 PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);//獲取屬性描述,描述是什么?描述就是對屬性的方法信息的封裝,好乖。 List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null); //重頭戲開始了!開始進行復制了 for (PropertyDescriptor targetPd : targetPds) { //先判斷有沒有寫方法,沒有寫方法我也就沒有必要讀屬性出來了,這個懶偷的真好! Method writeMethod = targetPd.getWriteMethod(); //首先,沒有寫方法的字段我不寫,乖巧撒?就是說你不讓我改我就不改,讓我忽略我就忽略! if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); //如果沒辦法從原對象里面讀出屬性也沒有必要繼續了 if (sourcePd != null) { Method readMethod = sourcePd.getReadMethod(); //這里就更乖巧了!寫方法不讓我寫我也不寫!!! if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) { try { //這里就算了,來都來了,就乖乖地進行值復制吧,別搞東搞西的了 if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } catch (Throwable ex) { throw new FatalBeanException( 'Could not copy property ’' + targetPd.getName() + '’ from source to target', ex); } } } } } }

2、對復制工具的一些看法和總結

總結上一段代碼的分析,我們發現spring自帶的工具有以下特點:

它名副其實的是在復制屬性,而不是字段!!

它可以通過一個目標對象的父類或者其實現的接口來控制需要復制屬性的范圍

很貼心的可以忽略原對象的某些字段,可以通過2的方法忽略某些目標對象的字段

但是,這遠遠不夠!!!我需要如下的功能:

復制對象的字段,而不是屬性,也就是說我需要一個更暴力的復制工具。

我需要忽略原對象的某些字段,同時也能夠忽略目標對象的某些字段。

我的項目還需要忽略原對象為null的字段和目標對象不為null的字段

帶著這三個需求,開始我的工具制造。

三、自己動手豐衣足食

1、我需要解析字節碼

為了避免對字節碼的重復解析,使用緩存來保留解析過的字節碼解析結果,同時為了不讓這個工具太占用內存,使用軟引用來進行緩存,上代碼:

/* ****************************************************** * 基礎的用于支持反射解析的解析結果緩存,使用軟引用實現 ****************************************************** */ private static final Map<Class<?>,SoftReference<Map<String,Field>>> resolvedClassCache = new ConcurrentHashMap<>(); /** * 同步解析字節碼對象,將解析的結果放入到緩存 1、解析后的字段對象全部 accessAble * 1、返回的集合不支持修改,要修改請記得自己重新建一個復制的副本 * @param sourceClass:需要解析的字節碼對象 */ @SuppressWarnings('SynchronizationOnLocalVariableOrMethodParameter') public static Map<String,Field> resolveClassFieldMap(final Class<?> sourceClass){ SoftReference<Map<String,Field>> softReference = resolvedClassCache.get(sourceClass); //判斷是否已經被初始化 if(softReference == null || softReference.get() == null){ //對同一個字節碼對象的解析是同步的,但是不同字節碼對象的解析是并發的,因為字節碼對象只有一個 synchronized(sourceClass){ softReference = resolvedClassCache.get(sourceClass); if(softReference == null || softReference.get() == null){ //采用:<字段名稱,字段對象> 來記錄解析結果 Map<String,Field> fieldMap = new HashMap<>(); /* Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default access, and private fields, but excludes inherited fields */ Field[] declaredFields = sourceClass.getDeclaredFields(); if(declaredFields != null && declaredFields.length > 0){ for(Field field : declaredFields){ /* Set the accessible flag for this object to the indicated boolean value. */ field.setAccessible(true); //字段名稱和字段對象 fieldMap.put(field.getName(),field); } } //設置為不變Map,這個肯定是不能夠改的啊!所以取的時候需要重新構建一個map fieldMap = Collections.unmodifiableMap(fieldMap); softReference = new SoftReference<>(fieldMap); /* 更新緩存,將解析后的數據加入到緩存里面去 */ resolvedClassCache.put(sourceClass,softReference); return fieldMap; } } } /* 運行到這里來的時候要么早就存在,要么就是已經被其他的線程給初始化了 */ return softReference.get(); }

2、我需要能夠進行對象的復制,基本方法

/** * 進行屬性的基本復制操作 * @param source:源對象 * @param sourceFieldMap:原對象解析結果 * @param target:目標對象 * @param targetFieldMap:目標對象解析結果 */ public static void copyObjectProperties(Object source,Map<String,Field> sourceFieldMap,Object target,Map<String,Field> targetFieldMap){ //進行屬性值復制 sourceFieldMap.forEach( (fieldName,sourceField) -> { //查看目標對象是否存在這個字段 Field targetField = targetFieldMap.get(fieldName); if(targetField != null){ try{ //對目標字段進行賦值操作 targetField.set(target,sourceField.get(source)); }catch(IllegalAccessException e){ e.printStackTrace(); } } } ); }

3、夜深了,準備睡覺了

基于這兩個方法,對其進行封裝,實現了我需要的功能,并且在項目中運行目前還沒有bug,應該可以直接用在生產環境,各位看官覺得可以可以拿來試一試哦!!

4、完整的代碼(帶注釋:需要自取,無外部依賴,拿來即用)

package edu.cqupt.demonstration.common.util;import java.lang.ref.SoftReference;import java.lang.reflect.Field;import java.util.*;import java.util.concurrent.ConcurrentHashMap;/** * 反射的工具集,主要用于對對象的復制操作 */public class ReflectUtil { /* ****************************************************** * 基礎的用于支持反射解析的解析結果緩存,使用軟引用實現 ****************************************************** */ private static final Map<Class<?>,SoftReference<Map<String,Field>>> resolvedClassCache = new ConcurrentHashMap<>(); /* **************************************** * 獲取一個對象指定條件字段名稱的工具方法 **************************************** */ /** * 獲取一個對象里面字段為null的字段名稱集合 */ public static String[] getNullValueFieldNames(Object source){ //非空校驗:NullPointerException Objects.requireNonNull(source); Class<?> sourceClass = source.getClass(); //從緩存里面獲取,如果緩存里面沒有就會進行第一次反射解析 Map<String,Field> classFieldMap = getClassFieldMapWithCache(sourceClass); List<String> nullValueFieldNames = new ArrayList<>(); classFieldMap.forEach( (fieldName,field) -> { try{ //挑選出值為null的字段名稱 if(field.get(source) == null){ nullValueFieldNames.add(fieldName); } }catch(IllegalAccessException e){ e.printStackTrace(); } } ); return nullValueFieldNames.toArray(new String[]{}); } /** * 獲取一個對象里面字段不為null的字段名稱集合 */ public static String[] getNonNullValueFieldNames(Object source){ //非空校驗 Objects.requireNonNull(source); //獲取空值字段名稱 String[] nullValueFieldNames = getNullValueFieldNames(source); Map<String,Field> classFieldMap = getClassFieldMapWithCache(source.getClass()); //獲取全部的字段名稱,因為原數據沒辦法修改,所以需要重新建立一個集合來進行判斷 Set<String> allFieldNames = new HashSet<>(classFieldMap.keySet()); //移除掉值為null的字段名稱 allFieldNames.removeAll(Arrays.asList(nullValueFieldNames)); return allFieldNames.toArray(new String[]{}); } /* *************************************************************** * 復制一個對象的相關工具方法,注意事項如下: * 1、只能復制字段名稱相同且數據類型兼容的字段數據 * 2、只能復制這個對象實際類(運行時動態類型)里面聲明的各種字段 *************************************************************** */ /** * 將一個對象里面字段相同、類型兼容的數據復制到另外一個對象去 * 1、只復制類的運行時類型的聲明的全部訪問權限的字段 * @param source:從這個對象復制 * @param target:復制到這個對象來 */ public static void copyPropertiesSimple(Object source,Object target){ copyObjectProperties( source,new HashMap<>(getClassFieldMapWithCache(source.getClass())), target,new HashMap<>(getClassFieldMapWithCache(target.getClass()))); } /** * 除實現 copyPropertiesSimple 的功能外,會忽略掉原對象的指定字段的復制 * @param ignoreFieldNames:需要忽略的原對象字段名稱集合 */ public static void copyPropertiesWithIgnoreSourceFields(Object source,Object target,String ...ignoreFieldNames){ Map<String,Field> sourceFieldMap = new HashMap<>(getClassFieldMapWithCache(source.getClass())); filterByFieldName(sourceFieldMap,ignoreFieldNames); copyObjectProperties(source,sourceFieldMap,target,new HashMap<>(getClassFieldMapWithCache(target.getClass()))); } /** * 除實現 copyPropertiesSimple 的功能外,會忽略掉原對象字段值為null的字段 */ public static void copyPropertiesWithNonNullSourceFields(Object source,Object target){ Map<String,Field> sourceFieldMap = new HashMap<>(getClassFieldMapWithCache(source.getClass())); filterByFieldValue(source,sourceFieldMap,true); copyObjectProperties(source,sourceFieldMap,target,new HashMap<>(getClassFieldMapWithCache(target.getClass()))); } /** * 除實現 copyPropertiesSimple 的功能外,會忽略掉目標對象的指定字段的復制 * @param ignoreFieldNames:需要忽略的原對象字段名稱集合 */ public static void copyPropertiesWithIgnoreTargetFields(Object source,Object target,String ...ignoreFieldNames){ Map<String,Field> targetFieldMap = new HashMap<>(getClassFieldMapWithCache(target.getClass())); filterByFieldName(targetFieldMap,ignoreFieldNames); copyObjectProperties(source,new HashMap<>(getClassFieldMapWithCache(source.getClass())),target,targetFieldMap); } /** * 除實現 copyPropertiesSimple 的功能外,如果目標對象的屬性值不為null將不進行覆蓋 */ public static void copyPropertiesWithTargetFieldNonOverwrite(Object source,Object target){ Map<String,Field> targetFieldMap = new HashMap<>(getClassFieldMapWithCache(target.getClass())); filterByFieldValue(target,targetFieldMap,false); copyObjectProperties(source,new HashMap<>(getClassFieldMapWithCache(source.getClass())),target,targetFieldMap); } /** * 進行復制的完全定制復制 * @param source:源對象 * @param target:目標對象 * @param ignoreSourceFieldNames:需要忽略的原對象字段名稱集合 * @param ignoreTargetFieldNames:要忽略的目標對象字段集合 * @param isSourceFieldValueNullAble:是否在源對象的字段為null的時候仍然進行賦值 * @param isTargetFiledValueOverwrite:是否在目標對象的值不為null的時候仍然進行賦值 */ public static void copyPropertiesWithConditions(Object source,Object target ,String[] ignoreSourceFieldNames,String[] ignoreTargetFieldNames ,boolean isSourceFieldValueNullAble,boolean isTargetFiledValueOverwrite){ Map<String,Field> sourceFieldMap = new HashMap<>(getClassFieldMapWithCache(source.getClass())); Map<String,Field> targetFieldMap = new HashMap<>(getClassFieldMapWithCache(target.getClass())); if(!isSourceFieldValueNullAble){ filterByFieldValue(source,sourceFieldMap,true); } if(!isTargetFiledValueOverwrite){ filterByFieldValue(target,targetFieldMap,false); } filterByFieldName(sourceFieldMap,ignoreSourceFieldNames); filterByFieldName(targetFieldMap,ignoreTargetFieldNames); copyObjectProperties(source,sourceFieldMap,target,targetFieldMap); } /* ****************************** * 內部工具方法或者內部兼容方法 ****************************** */ /** * 同步解析字節碼對象,將解析的結果放入到緩存 1、解析后的字段對象全部 accessAble * 1、返回的集合不支持修改,要修改請記得自己重新建一個復制的副本 * @param sourceClass:需要解析的字節碼對象 */ @SuppressWarnings('SynchronizationOnLocalVariableOrMethodParameter') public static Map<String,Field> resolveClassFieldMap(final Class<?> sourceClass){ SoftReference<Map<String,Field>> softReference = resolvedClassCache.get(sourceClass); //判斷是否已經被初始化 if(softReference == null || softReference.get() == null){ //對同一個字節碼對象的解析是同步的,但是不同字節碼對象的解析是并發的 synchronized(sourceClass){ softReference = resolvedClassCache.get(sourceClass); if(softReference == null || softReference.get() == null){ Map<String,Field> fieldMap = new HashMap<>(); /* Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default access, and private fields, but excludes inherited fields */ Field[] declaredFields = sourceClass.getDeclaredFields(); if(declaredFields != null && declaredFields.length > 0){ for(Field field : declaredFields){ /* Set the accessible flag for this object to the indicated boolean value. */ field.setAccessible(true); fieldMap.put(field.getName(),field); } } //設置為不變Map fieldMap = Collections.unmodifiableMap(fieldMap); softReference = new SoftReference<>(fieldMap); /* 更新緩存,將解析后的數據加入到緩存里面去 */ resolvedClassCache.put(sourceClass,softReference); return fieldMap; } } } /* 運行到這里來的時候要么早就存在,要么就是已經被其他的線程給初始化了 */ return softReference.get(); } /** * 確保正確的從緩存里面獲取解析后的數據 * 1、返回的集合不支持修改,要修改請記得自己重新建一個復制的副本 * @param sourceClass:需要解析的字節碼對象 */ public static Map<String,Field> getClassFieldMapWithCache(Class<?> sourceClass){ //查看緩存里面有沒有已經解析完畢的現成的數據 SoftReference<Map<String,Field>> softReference = resolvedClassCache.get(sourceClass); //確保classFieldMap的正確初始化和緩存 if(softReference == null || softReference.get() == null){ //解析字節碼對象 return resolveClassFieldMap(sourceClass); }else { //從緩存里面正確的取出數據 return softReference.get(); } } /** * 將一個可變參數集合轉換為List集合,當為空的時候返回空集合 */ public static <T> List<T> resolveArrayToList(T ...args){ List<T> result = new ArrayList<>(); if(args != null && args.length > 0){ result = Arrays.asList(args); } return result; } /** * 進行屬性的基本復制操作 * @param source:源對象 * @param sourceFieldMap:原對象解析結果 * @param target:目標對象 * @param targetFieldMap:目標對象解析結果 */ public static void copyObjectProperties(Object source,Map<String,Field> sourceFieldMap,Object target,Map<String,Field> targetFieldMap){ //進行屬性值復制 sourceFieldMap.forEach( (fieldName,sourceField) -> { //查看目標對象是否存在這個字段 Field targetField = targetFieldMap.get(fieldName); if(targetField != null){ try{ //對目標字段進行賦值操作 targetField.set(target,sourceField.get(source)); }catch(IllegalAccessException e){ e.printStackTrace(); } } } ); } /** * 忽略掉對象里面的某些字段 */ public static void filterByFieldName(Map<String,Field> fieldMap,String ... ignoreFieldNames){ //需要忽略的對象字段 List<String> ignoreNames = ReflectUtil.<String>resolveArrayToList(ignoreFieldNames); //移除忽略的對象字段 fieldMap.keySet().removeAll(ignoreNames); } /** * 忽略掉非空的字段或者空的字段 */ public static void filterByFieldValue(Object object,Map<String,Field> fieldMap,boolean filterNullAble){ Iterator<String> iterator = fieldMap.keySet().iterator(); if(filterNullAble){ while(iterator.hasNext()){ try{ //移除值為null的字段 if(fieldMap.get(iterator.next()).get(object) == null){ iterator.remove(); } }catch(IllegalAccessException e){ e.printStackTrace(); } } }else { while(iterator.hasNext()){ try{ //移除字段不為null的字段 if(fieldMap.get(iterator.next()).get(object) != null){ iterator.remove(); } }catch(IllegalAccessException e){ e.printStackTrace(); } } } }}

補充知識:Java將兩個JavaBean里相同的字段自動填充

最近因為經常會操作講兩個JavaBean之間相同的字段互相填充,所以就寫了個偷懶的方法。記錄一下

/** * 將兩個JavaBean里相同的字段自動填充 * @param dto 參數對象 * @param obj 待填充的對象 */public static void autoFillEqFields(Object dto, Object obj) {try {Field[] pfields = dto.getClass().getDeclaredFields(); Field[] ofields = obj.getClass().getDeclaredFields(); for (Field of : ofields) {if (of.getName().equals('serialVersionUID')) {continue;}for (Field pf : pfields) {if (of.getName().equals(pf.getName())) {PropertyDescriptor rpd = new PropertyDescriptor(pf.getName(), dto.getClass());Method getMethod = rpd.getReadMethod();// 獲得讀方法 PropertyDescriptor wpd = new PropertyDescriptor(pf.getName(), obj.getClass());Method setMethod = wpd.getWriteMethod();// 獲得寫方法 setMethod.invoke(obj, getMethod.invoke(dto));}}}} catch (Exception e) {e.printStackTrace();}} /** * 將兩個JavaBean里相同的字段自動填充,按指定的字段填充 * @param dto * @param obj * @param String[] fields */public static void autoFillEqFields(Object dto, Object obj, String[] fields) {try {Field[] ofields = obj.getClass().getDeclaredFields(); for (Field of : ofields) {if (of.getName().equals('serialVersionUID')) {continue;}for (String field : fields) {if (of.getName().equals(field)) {PropertyDescriptor rpd = new PropertyDescriptor(field, dto.getClass());Method getMethod = rpd.getReadMethod();// 獲得讀方法 PropertyDescriptor wpd = new PropertyDescriptor(field, obj.getClass());Method setMethod = wpd.getWriteMethod();// 獲得寫方法 setMethod.invoke(obj, getMethod.invoke(dto));}}}} catch (Exception e) {e.printStackTrace();}}

但這樣寫不能把父類有的屬性自動賦值所以修改了一下

/** * 將兩個JavaBean里相同的字段自動填充 * @param obj 原JavaBean對象 * @param toObj 將要填充的對象 */ public static void autoFillEqFields(Object obj, Object toObj) { try { Map<String, Method> getMaps = new HashMap<>(); Method[] sourceMethods = obj.getClass().getMethods(); for (Method m : sourceMethods) { if (m.getName().startsWith('get')) { getMaps.put(m.getName(), m); } } Method[] targetMethods = toObj.getClass().getMethods(); for (Method m : targetMethods) { if (!m.getName().startsWith('set')) { continue; } String key = 'g' + m.getName().substring(1); Method getm = getMaps.get(key); if (null == getm) { continue; } // 寫入方法寫入 m.invoke(toObj, getm.invoke(obj)); } } catch (Exception e) { e.printStackTrace(); } }

以上這篇利用Java反射機制實現對象相同字段的復制操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
主站蜘蛛池模板: 亚洲 欧美 另类 综合 偷拍 | 国产视频中文字幕 | 日本天天操 | 午夜影院毛片 | 欧美日韩成人激情 | 黄色一级毛片 | 99re视频在线观看 | 成人一区二区三区四区 | 日批免费观看视频 | 婷婷色国产偷v国产偷v小说 | 成人a视频在线观看 | 精品视频一区二区三区 | 国产第99页 | 美日韩一区二区 | 国产中文在线 | 国产毛片aaa | 国产精品视频一二三区 | 91在线视频免费播放 | 亚洲日韩中文字幕一区 | 日韩高清成人 | 欧美黄色一区 | 成人av教育 | 日韩视频在线免费 | 国产精品一区一区三区 | 午夜tv免费观看 | 97av| 亚洲美女视频 | 欧美日韩在线免费观看 | 国产精品免费观看 | 黄a免费看 | 欧美激情精品久久久久久免费 | av黄色一级片 | 亚洲精品一区二区三区中文字幕 | 久久成人一区二区 | 国产精品国产 | 欧美精品成人一区二区在线 | 亚洲毛片在线 | 欧美日韩精品亚洲 | 国产视频网 | www.麻豆视频| 婷婷中文字幕 | 久久精品久久久久久久久久久久久 | 欧美不卡一区二区三区 | 日本在线视 | 欧美一级视频在线观看 | 国产欧美日韩在线观看 | h视频在线免费观看 | 黄网在线观看 | 国产精品久久久久一区二区三区 | 99国产视频 | 亚洲国产精品一区二区久久 | 国外成人在线视频网站 | 午夜激情免费看 | 国产精品二区三区 | 亚洲三级在线观看 | 欧美日韩国产在线观看 | 黄色一级免费看 | 亚洲国产欧美在线 | 久久精品国产一区二区三区不卡 | av综合站 | 性培育学校羞耻椅子调教h 欧美精品网站 | 欧美电影一区 | 日本高清精品 | 韩国电影久久影院 | 91香蕉视频在线观看 | 91观看 | 欧洲亚洲视频 | 亚州av在线| 午夜网址| 不卡一区二区三区四区 | 超碰97人人人人人蜜桃 | 国产精品日韩 | 国产精品自拍视频 | 日本不卡免费新一二三区 | 成人免费毛片高清视频 | 95香蕉视频| 中文字幕欧美在线 | 日韩免费福利视频 | 久久综合一区二区三区 | 国产成人一区二区 | 羞羞视频在线观看入口 | 黄色片免费在线 | 九九在线国产视频 | 日日干夜夜骑 | 日韩在线资源 | 在线免费观看色视频 | 色播99| 成人精品一区二区三区 | 中文字幕av黄色 | 国产欧美精品一区二区 | 日韩在线播放一区二区三区 | 国产精品久久久久国产精品 | 亚洲精品乱码久久久久久蜜桃不卡 | 亚洲精品国产电影 | 国产精品视频一区二区三区 | 亚洲国产一区在线 | 国产成人在线免费观看 | 亚洲一级在线 | 日韩视频中文字幕 | 日韩网站免费观看 | 久久黄色片 | 欧美国产日韩一区二区 | av一区二区三区四区 | 国产精品女教师av久久 | 国产3区 | 日韩欧美国产精品综合嫩v 久久久久久国产精品高清 国产目拍亚洲精品99久久精品 | 精品在线免费视频 | 日韩免费在线观看视频 | 国产一区中文字幕 | 久久女人 | 高清一区二区三区 | 亚洲视频在线观看免费 | 91在线看 | 日摸夜操 | 91精品一区二区三区久久久久 | 欧美日韩在线播放 | 国产高清视频一区 | 狠狠夜夜 | 日韩成人精品 | 日韩在线播放网址 | 一区二区视频网站 | 99精品99| 日韩在线不卡视频 | 精品久| 成人午夜在线视频 | 一级a毛片 | 日韩1| 国产视频大全 | 久久涩| 久久久精品免费观看 | 日韩视频一区二区三区 | av在线精品 | 日韩有码电影 | 成人精品久久 | 国产精品日日 | 国产精品伦理一区 | 欧美一区二区三区aa大片漫 | 国产亚洲精品久久久456 | 国产精品福利在线观看 | 国产精品美女一区二区三区四区 | 亚洲一区二区三区四区五区中文 | 久久久精品国产 | 色精品 | 欧美八区 | 性高湖久久久久久久久aaaaa | 国外成人在线视频网站 | 午夜激情福利视频 | 久久精品综合 | 狠狠干欧美 | 人人看人人射 | 日韩一级二级三级 | 亚洲精品成人在线 | 欧美日韩在线成人 | 亚洲免费在线观看 | 久草成人网| 另类 综合 日韩 欧美 亚洲 | 欧美大片一区二区 | 在线91 | 国产乱码精品一区二区三区av | 日韩国产欧美一区 | 欧美啊v| 一区二区网站 | 亚洲成人一区二区 | 亚洲精品久久久久久久久久久 | 国产精品一区二区三区四区 | 国产精品美女久久久久久免费 | 黄色a视频| 成人免费淫片aa视频免费 | 久在线 | 亚洲成熟少妇视频在线观看 | 国产草草视频 | 日本在线视频观看 | 日韩精品视频免费看 | 国产色区| 欧美午夜精品久久久久久人妖 | 在线观看免费av网 | 免费一区二区三区 | 香蕉视频黄色 | 成人免费视频观看视频 | 91tv亚洲精品香蕉国产一区 | 欧美一区日韩一区 | 日韩精品一区二区三区在线观看 | 日韩一区精品视频 | 亚洲视频在线免费观看 | 欧美日韩在线播放 | 亚洲欧美视频 | 性大毛片视频 | 一级片在线观看 | 亚洲欧美国产精品专区久久 | 国产欧美久久久久久 | 欧美精品亚洲精品 | 久久精品一 | 欧美一区二区三区在线看 | 欧美白人做受xxxx视频 | 亚洲国产一区视频 | 成年人在线看片 | 中文字幕一区二区三 | 国产精品成人在线观看 | 日韩精品免费在线观看 | 美日韩成人 | 精品在线91| 国产成人午夜 | 国产午夜精品一区二区三区免费 | 国产在线中文字幕 | 欧美成人黄色小说 | 欧美成年黄网站色视频 | 日韩一区二区在线观看 | 国产视频一区二区 | 羞羞视频网站 | 亚洲精品乱码久久久久久花季 | 一区自拍 | 青青草网| 精品亚洲成人 | 国产黄视频在线 | 狠狠操综合网 | 伊人超碰| 欧美日韩中文字幕 | 免费毛片视频 | 亚洲午夜视频在线观看 | 夜夜夜夜夜操 | 精品国产91| 精品一区二区三区免费 | 久草高清在线 | 黄a在线 | 一区二区三区日韩精品 | 久久九精品 | 亚洲另类视频 | 97久久精品人人做人人爽50路 | av中文字幕在线播放 | 成人欧美一区二区三区在线播放 | 欧美一级在线免费观看 | 久久影院国产 | 天天天操| 精品久久久久久久 | 久久精品一区二区三区中文字幕 | 国产一区二区三区在线 | 久久久久久久成人 | 最近的中文字幕在线看视频 | 国产精品久久久久久久福利院 | 狠狠天天| 夜夜操天天干 | 国产精品99一区二区三区 | 一色视频 | 成人免费一区二区三区视频网站 | 欧美日韩免费看 | 中文字幕一区在线观看视频 | 欧美人成在线观看 | 91社区在线观看 | 欧美大片在线看免费观看 | 狼人狠狠干 | 久久精品亚洲 | 日韩精品小视频 | 国产高清免费 | 在线视频 中文字幕 | 欧美日韩一区二区三区在线观看 | 91免费版在线观看 | 精品中文字幕在线观看 | 欧美日韩中文字幕 | 激情欧美一区二区 | 日韩在线视频观看 | 99综合| 伊人色综合久久天天五月婷 | 羞羞的视频在线观看 | 久久亚洲一区 | 国产一区日韩在线 | 日韩成人免费 | bxbx成人精品一区二区三区 | 日韩中文字幕av | 日韩成人不卡 | 欧美一级免费 | 97精品 | 91免费在线看 | 国产精品成人在线观看 | 欧美日韩国产一区二区三区不卡 | 999这里只有是极品 免费的一级黄色片 | 中文字幕免费看 | 日本久久久久久 | 青青久久久 | 久久久久国产亚洲日本 | 欧美日韩国产精品一区 | 欧美日韩国产精品一区 | 国产视频观看 | 欧美国产视频 | 亚洲精品电影 | 久久伊| 欧美日韩在线第一页 | 精品一区二区在线观看 | 日韩精品在线播放 | 久久久久国产 | 四虎影视免费在线观看 | www.伊人网 | 日韩欧美一区二区三区久久婷婷 | 91婷婷射 | 在线免费观看一区 | 国产精品精品视频一区二区三区 | 在线激情网 | 久久成人国产精品 | 美女三区| 国产一区二区三区四区三区 | 亚洲一区二区三区久久 | 日本在线一区二区 | 成人影院av| 激情久久久久 | 国产欧美精品一区二区三区 | 亚洲精品视频导航 | 国产视频一区二区在线观看 | 日韩中文久久 | 日本色道视频 | 日韩成人免费 | 精品视频在线观看一区二区 | 伊人精品在线 | 成人国产一区二区 | 国产一区二区三区四区在线观看 | 亚洲一区中文字幕在线 | 日韩成人中文字幕 | 欧美三级在线 | 激情欧美日韩一区二区 | 亚洲精品在线视频 | 亚洲欧美激情精品一区二区 | 成人精品视频在线观看 | 久久久久黄 | 日韩视频在线观看 | 日韩在线一区二区 | 欧美性猛交一区二区三区精品 | 欧美成人精品一区二区三区 | 午夜电影网 | 国产精品高潮呻吟 | 中文字幕在线三区 | www.9191| 日韩一区在线播放 | 9999久久久久 | 亚洲欧美国产精品专区久久 | 久久精品欧美一区二区三区不卡 | 久久婷婷国产麻豆91天堂 | 成人午夜视频在线观看 | 中文字幕一区二区三区精彩视频 | 免费毛片视频 | 久久久成人精品 | 国产精品一区二区在线观看 | 亚洲在线观看免费视频 | 亚洲精品一区久久久久久 | 国产目拍亚洲精品99久久精品 | 成人免费在线 | 亚洲精品一区二区三区在线观看 | 成人免费在线电影 | 天天拍天天干天天操 | 欧美不卡一区二区三区 | 中国一级大黄大黄大色毛片 | 日韩中文字幕国产 | 精品久久久久一区二区国产 | 少妇av片 | jizz在线观看 | 一区二区三区精品视频 | 亚洲精品电影在线观看 | 欧美中文字幕一区二区 | 国产精品亲子伦av一区二区三区 | 国产一级黄色 | 欧美日韩一区在线观看 | 亚洲欧美另类久久久精品2019 | 亚洲精品天堂 | 国产精品三级视频 | 精产国产伦理一二三区 | 日日干夜夜骑 | 老牛影视av一区二区在线观看 | 国产在线精品一区二区 | 亚洲国产精品自拍 | www,久久久 | 国产精品中文 | 国产视频第一页 | 在线观看国产一区 | 九一视频在线播放 | 亚洲一区中文字幕在线观看 | 久久国产精品一区二区 | 中国91视频 | 99精品国产在热久久 | 成人免费视频网站在线观看 | 免费福利视频一区二区三区 | 97精品国产97久久久久久粉红 | 欧美99| 欧美一区二区三区电影 | 亚洲精品四区 | 欧美一区二区三区在线观看视频 | 在线免费观看成年人视频 | 日韩小视频网站hq | 国产精品久久久久国产精品 | 亚洲精品在| 成人高清视频在线观看 | 亚洲精品中文字幕 | 在线视频 欧美日韩 | 欧美第一页 | 日韩爱爱网| 午夜社区 | 操操操操操操操操操操操操操操 | 欧美日韩国产一区 | 国产精选一区二区 | 国产成人无遮挡在线视频 | 亚洲久久 | www.中文字幕| 国产精品久久久久久亚洲调教 | 日韩五月 | 国产农村妇女精品久久 | 日韩视频中文字幕 | 精品国产黄a∨片高清在线 99热婷婷 | 日日骚av | 9999久久久久 | 免费的一级视频 | 一级毛片在线播放 | 久久综合电影 | 欧美国产视频 | 国产一区二区三区久久久久久 | 国产成人av一区二区三区 | 啪一啪操一操 | 国产成人av一区二区三区 | 成人精品视频99在线观看免费 | 免费黄色在线观看 | 亚洲欧美日韩天堂 | 久久99精品视频在线观看 | 日韩a级免费视频 | 成人无遮挡毛片免费看 | 99视频在线| 精品午夜久久久 | 中文一区| 欧美亚洲一区 | 中文字幕在线观看 | 视频二区在线观看 | 永久免费在线 | 国产精品一区二区无线 | 在线观看免费黄色片 | jizz在线观看 | 亚洲毛片在线 | 国产精品成人av | 五月天婷婷在线视频 | 91短视频版在线观看www免费 | 国产又粗又长又硬又猛电影 | 成人一级片| 在线免费观看一区 | 91嫩草在线| 国产美女一区 | 爱爱视频在线观看 | 国产精品一区二区三 | 日韩精品专区 | 欧美中文字幕在线观看 | 日韩欧美网址 | 久草视频在线播放 | 欧美二区三区 | 免费国产视频 | 欧美日韩中文在线 | 亚洲成av人片一区二区三区 | 天天舔日日干 | 日日撸 | 亚洲成人日韩 | 热久久这里只有精品 | 成人狠狠干 | 在线中文字幕av | 99爱视频| 久久国产午夜 | 亚洲国产欧美一区二区三区久久 | 亚洲综合在线视频 | 欧美性一区二区三区 | 毛片毛片毛片毛片毛片毛片 | 伊人一区二区三区 | 成人免费看片 | 精品视频一区二区三区 | 欧美视频二区 | 中文字幕久久精品 | 黄色成人在线 | 免费观看黄色一级大片 | 日韩精品一区二区在线观看视频 | 亚洲欧美国产精品专区久久 | 日韩在线免费 | 国产一区二区三区免费播放 | jizz18国产| 国产精品无码专区在线观看 | 欧美日韩精品一区二区三区在线观看 | 欧美日韩中文 | 日日骚| 日韩在线国产 | 久久一区二区三区四区 | 成人午夜视频在线观看 | 男女av在线 | 成人日韩 | 精品国产一区二区三区性色 | 岛国精品 | 日本三级电影免费 | 亚洲成a | 日本不卡一区二区三区在线观看 | 成人精品一区二区 | 欧美国产视频 | 亚洲成人精品在线观看 | 日韩视频精品在线 | 欧美久久久久久久久久久 | 日韩欧美一级精品久久 | 第一色视频 | 一区二区日韩精品 | 亚洲二区在线观看 | 国产黄色网址在线观看 | 亚洲精品综合 | 国产在线一区二区 | 美女午夜影院 | 视频二区 | 日本在线免费 | 国产二区视频 | 看免费的毛片 | a欧美| 日韩一区二区三区在线观看 | 欧美精品1区 | 国产视频一区二区三区四区 | 欧美国产精品一区 | 国产精品美女久久久久久久网站 | 综合婷婷 | 国产中文区二幕区2012 | 亚洲精品一区久久久久久 | 99re在线免费| 亚洲欧美另类在线观看 | 国内精品久久久久国产 | 亚洲精品国产9999久久久久 | 欧美伦理一区二区 | 亚洲女人天堂成人av在线 | 亚洲精品久久 | 欧亚视频在线观看 | 精品欧美一区二区在线观看视频 | 国产一区二区三区久久久久久久久 | 亚洲深深色噜噜狠狠网站 | 91精品久久久久久久久 | 欧美精品亚洲精品 | 91精品国产色综合久久不卡98口 | 亚洲国产一区二区三区四区 | 亚洲色图在线播放 | 国产超碰人人模人人爽人人添 | 精品久久久久久久久久久久 | 91国内外精品自在线播放 | 日韩精品在线一区 | 婷婷久久综合 | 欧美不卡视频一区发布 | 久久男人天堂 | 色天天综合久久久久综合片 | 国产成人99久久亚洲综合精品 | 国产福利片在线观看 | 日本福利视频免费观看 | 在线观看免费视频亚洲 | 男女精品视频 | 午夜家庭影院 | 亚洲日本va中文字幕 | 一级在线播放 | 日韩精品一区二区三区中文在线 | 欧美二区三区 | 国产91成人video | 久久99久久99精品免观看粉嫩 | 国产精品国产三级国产aⅴ无密码 | 欧美一级片aaa | 国产精品.xx视频.xxtv | 日韩免费在线视频 | 婷婷亚洲五月 | 国产欧美日韩综合精品一区二区 | 国产噜噜噜噜噜久久久久久久久 | 日本久久精品一区 | 国产日韩一区二区 | 婷婷欧美| 欧美日韩电影一区二区 | 日韩大片播放器 | 中文字幕精品视频在线观看 | 一区二区三区免费 | 亚洲三级在线 | 午夜精品导航 | 天天操天天碰 | 日本久久久一区二区三区 | 国产精品久久久久久久久久 | 欧美精品自拍 | www.亚洲| 欧美日韩精品在线一区 | 一级毛片观看 | 精品国产青草久久久久福利 | 国产精品久久99 | 精品成人佐山爱一区二区 | 国产欧美一区二区 | 久久久www成人免费无遮挡大片 | 国产免费av一区二区三区 | 国产1区2区3区 | 久草在线视频网 | 国产精品久久久久9999 | 99国产精品久久久久久久 | 在线看片日韩 | 视频精品一区 | 最新黄色网页 | 成人在线一区二区 | 99视频免费观看 | 国产区亚洲 | 国产一区二区免费 | 精品免费国产视频 | 亚洲人成在线播放 | 久久精品手机视频 | 久久久久久亚洲精品 | 欧美日韩成人一区 | 久久久久无码国产精品一区 | 国产伦精品一区二区三区四区视频 | 色婷婷av一区二区三区软件 | 欧美性一区二区三区 | 亚洲高清中文字幕 | 热re99久久精品国99热线看 | 在线观看免费毛片视频 | 在线观看v片 | 久久精品二区 | 精品欧美久久 | 精品国产欧美一区二区 | 久久精品国产亚洲精品 | 久久久精品国产 | 日韩视频在线观看视频 | 最新国产毛片 | 亚洲av毛片一级二级在线 | 国产99热 | 亚洲精品不卡 | 国产一极片 | 91在线观看网站 | 欧美一区2区三区3区公司 | 久久久久久中文字幕 |