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

初級必備:單例模式的7個問題

開發 前端
實話實說,關于單例模式,網上有N多個版本。你估計也看過很多版本。但看完了又能怎樣?我技術群里的一位小伙伴,上周面試,就因為一個單例模式,然后叫他回去等通知了。

[[402350]]

故事

實話實說,關于單例模式,網上有N多個版本。你估計也看過很多版本。但看完了又能怎樣?我技術群里的一位小伙伴,上周面試,就因為一個單例模式,然后叫他回去等通知了。

下面是這位同學被問到的問題:

1、說說單例模式的特點?

2、你知道單例模式的具體使用場景嗎?

3、單例模式常見寫法有幾種?

4、怎么樣保證線程安全?

5、怎么不會被反射攻擊?

6、怎樣保證不會被序列化和反序列化的攻擊?

7、枚舉為什么會不會被序列化?

.....

你也可以嘗試行的回答這幾個題,看看自己能回答上幾個。

定義

單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

特點:

  • 1、單例類只能有一個實例。
  • 2、單例類必須自己創建自己的唯一實例。
  • 3、單例類必須給所有其他對象提供這一實例
  • 4、隱藏所有的構造方法

**目的:**保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。

案例:一家企業只能有一個CEO,有多個了其實亂套了。

使用場景

需要確保任何情況下都絕對只有一個實例。

比如:ServletContext、ServletConfig、ApplicationContext、DBTool等,都使用到了單列模式。

單例模式的寫法

  • 餓漢式
  • 懶漢式(包含雙重檢查鎖、靜態內部類)
  • 注冊式(以枚舉為例)

餓漢式

從名字上就能看出,餓漢:餓了就得先吃飽,所以,一開始就搞定了。

餓漢式主要是使用了static,餓漢式也有兩種寫法,但本質可以理解為是一樣的。

  1. public class HungrySingleton{ 
  2.  
  3.     private static final HungrySingleton INSTANCE; 
  4.     static { 
  5.         INSTANCE=new HungrySingleton(); 
  6.     } 
  7. //    private static final HungrySingleton INSTANCE=new HungrySingleton(); 
  8.     private HungrySingleton(){ 
  9.  
  10.     } 
  11.  
  12.     public static HungrySingleton getInstance(){ 
  13.         return INSTANCE; 
  14.     } 

餓漢式有個致命的缺點:浪費空間,不需要也實例化。如果是成千上萬個,也這么玩,想想有多恐怖。

于是,就會想到,能不能在使用的時候在實例化,從而引出了懶漢式。

懶漢式

顧名思義,就是需要的時候再創建,因為懶,你不調用我方法,我是不會干活的。

下面是懶漢式的Java代碼實現:

  1. public class LazySingleton { 
  2.  
  3.     private static LazySingleton lazySingleton = null
  4.  
  5.     private LazySingleton() { 
  6.     } 
  7.  
  8.     public static LazySingleton getInstance() { 
  9.         if (lazySingleton == null) {//01 
  10.             lazySingleton = new LazySingleton();//02 
  11.         } 
  12.         return lazySingleton; 
  13.     }  

進入getInstance方法,先判斷lazySingleton是否為空,為空,則創建一個對象,然后返回此對象。

但是,問題來了:

兩個線程同時進入getInstance方法,然后都去執行01這行代碼,都是true,然后各自進去創建一個對象,然后返回自己創建的對象。

這豈不是不滿足只有唯一 一個對象的了嗎?所以這類存在線程安全的問題,那怎么解決呢?

第一印象肯定都是想到加鎖。于是,就有了下面的線程安全的懶加載版本:

  1. public class LazySingleton { 
  2.  
  3.     private static LazySingleton lazySingleton = null
  4.  
  5.     private LazySingleton() { 
  6.     } 
  7.  
  8.     //簡單粗暴的線程安全問題解決方案 
  9.     //依然存在性能問題 
  10.   public synchronized static LazySingleton getInstance() { 
  11.         if (lazySingleton == null) { 
  12.             lazySingleton = new LazySingleton(); 
  13.         } 
  14.         return lazySingleton; 
  15.     } 

給getInstance方法加鎖同步鎖標志synchronized,但是又涉及到鎖的問題了,同步鎖是對系統性能優影響的,盡管JDK1.6后,對其做了優化,但它畢竟還是涉及到鎖的開銷。

每個線程調用getInstance方法時候,都會涉及到鎖,所以又對此進行了優化成為了大家耳熟能詳的雙重檢查鎖。

雙重檢查鎖

代碼實現如下:

  1. public class LazyDoubleCheckSingleton {  
  2.     private static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null
  3.  
  4.     private LazyDoubleCheckSingleton() { 
  5.     } 
  6.  
  7.     public static LazyDoubleCheckSingleton getInstance() { 
  8.         if (lazyDoubleCheckSingleton == null) {//01 
  9.             synchronized (LazyDoubleCheckSingleton.class) { 
  10.                 if (lazyDoubleCheckSingleton == null) {//02 
  11.                     lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); 
  12.                 } 
  13.             } 
  14.         } 
  15.         return lazyDoubleCheckSingleton; 
  16.     } 
  17.  

這段代碼中,在01行,如果不為空,就直接返回,這是第一次檢查。如果為空,則進入同步代碼塊,02行又進行一次檢查。

雙重檢查就是現實if判斷、獲取類對象鎖、if判斷。

上面這段代碼,看似沒問題,其實還是有問題的,比如:指令重排序(需要有JVM知識墊底哈)

指令重排是什么意思呢?

比如java中簡單的一句

  1. lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); 

會被編譯器編譯成如下JVM指令:

memory =allocate(); //1:分配對象的內存空間

ctorInstance(memory); //2:初始化對象

instance =memory; //3:設置instance指向剛分配的內存地址

但是這些指令順序并非一成不變,有可能會經過JVM和CPU的優化,指令重排成下面的順序:

memory =allocate(); //1:分配對象的內存空間

instance =memory; //3:設置instance指向剛分配的內存地址

ctorInstance(memory); //2:初始化對象

為了防止指令重排序,所以,我們可以使用volatile來做文章(注意:volatile能防止指令重排序和線程可見性)。

于是,更好的版本就出來了。

  1. public class LazyDoubleCheckSingleton { 
  2.     //使用volatile修飾 
  3.     private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;  
  4.     private LazyDoubleCheckSingleton() { 
  5.     } 
  6.  
  7.     public static LazyDoubleCheckSingleton getInstance() { 
  8.         if (lazyDoubleCheckSingleton == null) { 
  9.             synchronized (LazyDoubleCheckSingleton.class) { 
  10.                 if (lazyDoubleCheckSingleton == null) { 
  11.                     lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); 
  12.                 } 
  13.             } 
  14.         } 
  15.         return lazyDoubleCheckSingleton; 
  16.     } 

盡管相比前面的版本,確實改進了很多,但依然有同步鎖,還是會影響性能問題。于是,又進行優化為靜態內部類方式:

靜態內部類

下面是靜態內部類的代碼實現:

利用了內部類的特性,在JVM底層,能完美的規避了線程安全的問題,這種方式也是目前很多項目里喜歡使用的方式。

但是,還是會存在潛在的風險,什么風險呢?

可以使用 反射 暴力的串改,同樣也會出現創建多個實例:

反射代碼實現如下:

  1. import java.lang.reflect.Constructor; 
  2.  
  3. public class LazyStaticSingletonTest { 
  4.     public static void main(String[] args) { 
  5.         try { 
  6.             Class<?> clazz = LazyStaticSingleton.class; 
  7.             Constructor constructor = clazz.getDeclaredConstructor(null); 
  8.             //強行訪問 
  9.             constructor.setAccessible(true); 
  10.             Object object = constructor.newInstance(); 
  11.  
  12.             Object object1 = LazyStaticSingleton.getInstance(); 
  13.  
  14.             System.out.println(object == object1); 
  15.         } catch (Exception ex) { 
  16.             ex.printStackTrace(); 
  17.         } 
  18.     } 

這段代碼運行結果為false。

所以,上面說的雙重檢查鎖的方式,通過反射,還是會存在潛在的風險。怎么辦呢?

在《Effect java 》這本書中,作者推薦使用枚舉來實現單例模式,因為枚舉不能被反射。

枚舉

下面是枚舉式的單例模式的代碼實現:

  1. public enum EnumSingleton { 
  2.     INSTANCE; 
  3.     private Object data; 
  4.  
  5.     public Object getData() { 
  6.         return data; 
  7.     } 
  8.  
  9.     public static EnumSingleton getInstance(){ 
  10.         return INSTANCE; 
  11.     } 

我們把上面反射的那個代碼,來測試這個枚舉式單例模式。

  1. public class EnumTest { 
  2.     public static void main(String[] args) { 
  3.         try { 
  4.             Class<?> clazz = EnumSingleton.class; 
  5.             Constructor constructor = clazz.getDeclaredConstructor(null); 
  6.             //強行訪問 
  7.             constructor.setAccessible(true); 
  8.             Object object = constructor.newInstance(); 
  9.  
  10.             Object object1 = EnumSingleton.getInstance(); 
  11.  
  12.             System.out.println(object == object1); 
  13.         } catch (Exception ex) { 
  14.             ex.printStackTrace(); 
  15.         } 
  16.     } 

運行這段代碼:

  1. java.lang.NoSuchMethodException: com.tian.my_code.test.designpattern.singleton.EnumSingleton.<init>() 
  2.  at java.lang.Class.getConstructor0(Class.java:3082) 
  3.  at java.lang.Class.getDeclaredConstructor(Class.java:2178) 
  4.  at com.tian.my_code.test.designpattern.singleton.EnumTest.main(EnumTest.java:41) 

還真的不能用反射來搞。如果此時面試官,為什么枚舉不能被反射呢?

為什么枚舉不能被反射呢?

我們在反射的代碼中

  1. Constructor constructor = clazz.getDeclaredConstructor(null); 

這行代碼是獲取他的無參構造方法。并且,從錯誤日志中,我們也可以看到,錯誤出現就是在getConstructor0方法中,并且,提示的是沒有找到無參構造方法。

很奇怪,枚舉也是類,不是說如果我們不給類顯示定義構造方法時候,會默認給我們創建一個無參構造方法嗎?

于是,我想到了一個辦法,我們可以使用jad這個工具去反編譯的我們的枚舉式單例的.class文件。

找到我們的class文件所在目錄,然后我們可以執行下面這個命令:

  1. C:\Users\Administrator>jad D:\workspace\my_code\other-local-demo\target\classes 
  2. com\tian\my_code\test\designpattern\singleton\EnumSingleton.class 
  3. Parsing D:\workspace\my_code\other-local-demo\target\classes\com\tian\my_code\t 
  4. st\designpattern\singleton\EnumSingleton.class... Generating EnumSingleton.jad 

注意:class文件目錄以及生成的jad文件所在的目錄。

然后打開EnumSingleton.jad 文件:

于是,我就想到了,那我們使用有參構造方法來創建:

  1. public class EnumTest { 
  2.     public static void main(String[] args) { 
  3.         try { 
  4.             Class<?> clazz = EnumSingleton.class;  
  5.             Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class); 
  6.             //強行訪問 
  7.             constructor.setAccessible(true); 
  8.             Object object = constructor.newInstance("田維常",996); 
  9.  
  10.             Object object1 = EnumSingleton.getInstance(); 
  11.  
  12.             System.out.println(object == object1); 
  13.         } catch (Exception ex) { 
  14.             ex.printStackTrace(); 
  15.         } 
  16.     } 

再次運行這段代碼,結果:

  1. java.lang.IllegalArgumentException: Cannot reflectively create enum objects 
  2.  at java.lang.reflect.Constructor.newInstance(Constructor.java:417) 
  3.  at com.tian.my_code.test.designpattern.singleton.EnumTest.main(EnumTest.java:45) 

提示很明顯了,就是不讓我們使用反射的方式創建枚舉對象。

  1. public T newInstance(Object ... initargs) 
  2.      throws InstantiationException, IllegalAccessException, 
  3.             IllegalArgumentException, InvocationTargetException 
  4.  { 
  5.      if (!override) { 
  6.          if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { 
  7.              Class<?> caller = Reflection.getCallerClass(); 
  8.              checkAccess(caller, clazz, null, modifiers); 
  9.          } 
  10.      } 
  11.      //Modifier.ENUM就是用來判斷是否為枚舉的 
  12.      if ((clazz.getModifiers() & Modifier.ENUM) != 0) 
  13.          throw new IllegalArgumentException("Cannot reflectively create enum objects"); 
  14.      ConstructorAccessor ca = constructorAccessor;   // read volatile 
  15.      if (ca == null) { 
  16.          ca = acquireConstructorAccessor(); 
  17.      } 
  18.      @SuppressWarnings("unchecked"
  19.      T inst = (T) ca.newInstance(initargs); 
  20.      return inst; 
  21.  } 

所以,到此,我們才算真正的理清楚了,為什么枚舉不讓反射的原因。

序列化破壞

我們以非線程安全的餓漢式來演示一下,看看序列化是如何破壞到了模式的。

  1. public class ReflectTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.         // 準備兩個對象,singleton1接收從輸入流中反序列化的實例 
  5.         HungrySingleton singleton1 = null
  6.         HungrySingleton singleton2 = HungrySingleton.getInstance(); 
  7.         try { 
  8.             // 序列化 
  9.             FileOutputStream fos = new FileOutputStream("HungrySingleton.txt"); 
  10.             ObjectOutputStream oos = new ObjectOutputStream(fos); 
  11.             oos.writeObject(singleton2); 
  12.             oos.flush(); 
  13.             oos.close(); 
  14.  
  15.             // 反序列化 
  16.             FileInputStream fis = new FileInputStream("HungrySingleton.txt"); 
  17.             ObjectInputStream ois = new ObjectInputStream(fis); 
  18.             singleton1 = (HungrySingleton) ois.readObject(); 
  19.             ois.close(); 
  20.  
  21.             System.out.println(singleton1); 
  22.             System.out.println(singleton2); 
  23.              
  24.             System.out.println(singleton1 == singleton2); 
  25.  
  26.         } catch (Exception e) { 
  27.             e.printStackTrace(); 
  28.         } 
  29.     } 

運行結果:

  1. com.tian.my_code.test.designpattern.singleton.HungrySingleton@7e6cbb7a 
  2. com.tian.my_code.test.designpattern.singleton.HungrySingleton@452b3a41 
  3. false 

看到了嗎?

使用序列化是可以破壞到了模式的,這種方式,可能很多人不是很清楚。

如何防止呢?

我們對非線程安全的餓漢式代碼進行稍微修改:

  1. public class HungrySingleton implements Serializable
  2.  
  3.     private static final HungrySingleton INSTANCE; 
  4.     static { 
  5.         INSTANCE=new HungrySingleton(); 
  6.     }  
  7.     private HungrySingleton(){ 
  8.  
  9.     } 
  10.  
  11.     public static HungrySingleton getInstance(){ 
  12.         return INSTANCE; 
  13.     } 
  14.     //添加了readResolve方法,并返回INSTANCE 
  15.     private Object readResolve方法,并返回(){ 
  16.         return INSTANCE; 
  17.     } 

再次運行上那段序列化測試的代碼,其結果如下:

  1. com.tian.my_code.test.designpattern.singleton.HungrySingleton@452b3a41 
  2. com.tian.my_code.test.designpattern.singleton.HungrySingleton@452b3a41 
  3. true 

嘿嘿,這樣我們是不是就避免了只創建了一個實例?

答案:否

在類ObjectInputStream的readObject()方法中調用了另外一個方法readObject0(false)方法。在readObject0(false)方法中調用了checkResolve(readOrdinaryObject(unshared))方法。

在readOrdinaryObject方法中有這么一段代碼:

  1. Object obj; 
  2. try {  
  3.      //是否有構造方法,有構造放就創建實例 
  4.       obj = desc.isInstantiable() ? desc.newInstance() : null
  5.  } catch (Exception ex) { 
  6.  ...  
  7.  } 
  8. //判斷單例類是否有readResolve方法 
  9. if (desc.hasReadResolveMethod()) { 
  10.     Object rep = desc.invokeReadResolve(obj);  
  11.  
  12. //invokeReadResolve方法中 
  13. if (readResolveMethod != null) {  
  14.     //調用了我們單例類中的readResolve,并返回該方法返回的對象 
  15.     //注意:是無參方法 
  16.      return readResolveMethod.invoke(obj, (Object[]) null); 

繞了半天,原來他是這么玩的,上來就先創建一個實例,然后再去檢查我們的單例類是否有readResolve無參方法,我們單例類中的readResolve方法

  1. private Object readResolve(){ 
  2.         return INSTANCE; 

結論

我們重寫了readResolve()無參方法,表面上看是只創建了一個實例,其實只創建了兩個實例。

緊接著,面試官繼續問:枚舉式單例能不能被序列化破壞呢?

枚舉式單例能不能被序列化破壞呢?

答案:不能被破壞,請看我慢慢給你道來。

don't talk ,show me the code。

我們先來驗證一下是否真的不能被破壞,請看代碼:

  1. public class EnumTest { 
  2.  
  3.     public static void main(String[] args) { 
  4.         // 準備兩個對象,singleton1接收從輸入流中反序列化的實例 
  5.         EnumSingleton singleton1 = null
  6.         EnumSingleton singleton2 = EnumSingleton.getInstance(); 
  7.         try { 
  8.             // 序列化 
  9.             FileOutputStream fos = new FileOutputStream("EnumSingleton.obj"); 
  10.             ObjectOutputStream oos = new ObjectOutputStream(fos); 
  11.             oos.writeObject(singleton2); 
  12.             oos.flush(); 
  13.             oos.close(); 
  14.  
  15.             // 反序列化 
  16.             FileInputStream fis = new FileInputStream("EnumSingleton.obj"); 
  17.             ObjectInputStream ois = new ObjectInputStream(fis); 
  18.             singleton1 = (EnumSingleton) ois.readObject(); 
  19.             ois.close(); 
  20.  
  21.             System.out.println(singleton1); 
  22.             System.out.println(singleton2); 
  23.  
  24.             System.out.println(singleton1 == singleton2); 
  25.  
  26.         } catch (Exception e) { 
  27.             e.printStackTrace(); 
  28.         } 
  29.     } 

運行結果:

  1. INSTANCE 
  2. INSTANCE 
  3. true 

確實,枚舉式單例是不會被序列化所破壞,那為什么呢?總得有個證件理由吧。

在類ObjectInputStream的readObject()方法中調用了另外一個方法readObject0(false)方法。在readObject0(false)方法中調用了checkResolve(readOrdinaryObject(unshared))方法。

  1. case TC_ENUM: 
  2.    return checkResolve(readEnum(unshared)); 

在readEnum方法中

  1. private Enum<?> readEnum(boolean unshared) throws IOException { 
  2.         if (bin.readByte() != TC_ENUM) { 
  3.             throw new InternalError(); 
  4.         } 
  5.         Class<?> cl = desc.forClass(); 
  6.         if (cl != null) { 
  7.             try { 
  8.                 @SuppressWarnings("unchecked"
  9.                 //重點 
  10.                 Enum<?> en = Enum.valueOf((Class)cl, name); 
  11.                 result = en; 
  12.                 //...其他代碼省略 
  13.             } 
  14.         } 
  15. public static <T extends Enum<T>> T valueOf(Class<T> enumType, 
  16.                                                 String name) { 
  17.        //enumType.enumConstantDirectory()返回的是一個HashMap 
  18.        //通過HashMap的get方法獲取 
  19.         T result = enumType.enumConstantDirectory().get(name); 
  20.         if (result != null
  21.             return result; 
  22.         if (name == null
  23.             throw new NullPointerException("Name is null"); 
  24.         throw new IllegalArgumentException( 
  25.             "No enum constant " + enumType.getCanonicalName() + "." + name); 
  26. //返回一個HashMap 
  27.  Map<String, T> enumConstantDirectory() { 
  28.         if (enumConstantDirectory == null) { 
  29.             T[] universe = getEnumConstantsShared(); 
  30.             if (universe == null
  31.                 throw new IllegalArgumentException( 
  32.                     getName() + " is not an enum type"); 
  33.             //使用的是HashMap 
  34.             Map<String, T> m = new HashMap<>(2 * universe.length); 
  35.             for (T constant : universe) 
  36.                 m.put(((Enum<?>)constant).name(), constant); 
  37.             enumConstantDirectory = m; 
  38.         } 
  39.         return enumConstantDirectory; 

所以,枚舉式單例模式是使用了Map

在Spring中也是有大量使用這種注冊式單例模式,IOC容器就是典型的代表。

總結

本文講述了單例模式的定義、單例模式常規寫法。單例模式線程安全問題的解決,反射破壞、反序列化破壞等。

注意:不要為了套用設計模式,而使用設計模式。而是要,在業務上遇到問題時,很自然地聯想單設計模式作為一種捷徑方法。

單例模式的優缺點

優點

在內存中只有一個實例,減少內存開銷??梢员苊鈱Y源的多重占用。設置全局訪問點,嚴格控制訪問。

缺點

沒有借口,擴展性很差。如果要擴展單例對象,只有修改代碼,沒有其他途徑。

單例模式是 不符合開閉原則的。

知識點

單例模式的重點知識總結:

  • 私有化構造器
  • 保證線程安全
  • 延遲加載
  • 防止反射攻擊
  • 防止序列化和反序列化的破壞

本文轉載自微信公眾號「Java后端技術全?!?,可以通過以下二維碼關注。轉載本文請聯系Java后端技術全棧公眾號。

 

責任編輯:武曉燕 來源: Java后端技術全棧
相關推薦

2021-09-07 10:44:35

異步單例模式

2021-02-01 10:01:58

設計模式 Java單例模式

2021-03-02 08:50:31

設計單例模式

2018-04-03 15:38:07

Java單例模式模式設計

2022-02-06 22:30:36

前端設計模式

2022-09-29 08:39:37

架構

2016-03-28 10:23:11

Android設計單例

2013-11-26 16:20:26

Android設計模式

2021-02-07 23:58:10

單例模式對象

2011-03-16 10:13:31

java單例模式

2022-06-07 08:55:04

Golang單例模式語言

2019-06-11 09:50:07

SparkBroadcast代碼

2024-11-06 16:13:00

Python單例模式

2015-09-06 11:07:52

C++設計模式單例模式

2024-02-22 10:02:03

單例模式系統代碼

2021-08-11 17:22:11

設計模式單例

2024-02-04 12:04:17

2024-03-06 13:19:19

工廠模式Python函數

2023-11-21 21:39:38

單例模式音頻管理器

2011-06-28 15:18:45

Qt 單例模式
點贊
收藏

51CTO技術棧公眾號

av亚洲精华国产精华精华| 欧美日本在线| 欧美日韩一区成人| 日本久久高清视频| 亚洲精品国产精品国| 麻豆传媒视频在线观看免费| 国产真实乱偷精品视频免| 九九热精品视频国产| 最近中文字幕无免费| 日本肉肉一区| 一区二区理论电影在线观看| 女同一区二区| jizz中国女人| 久久深夜福利| 久久久久国产一区二区三区| 在线小视频你懂的| 亚洲福利合集| 欧美三级三级三级爽爽爽| 国产夫妻自拍一区| 91社区在线| 99re亚洲国产精品| 亚洲最大av网| 瑟瑟视频在线免费观看| 精品动漫3d一区二区三区免费| 一区二区三区四区在线观看视频| 佐佐木明希电影| 99久久这里有精品| 91精品办公室少妇高潮对白| 国产xxxx振车| 国产黄色在线观看| 中文字幕第一区二区| 精品无码久久久久久久动漫| 国产农村老头老太视频| 免费一区视频| 久久免费精品视频| 九九热这里有精品视频| 成人一区而且| 亚洲性夜色噜噜噜7777| 精品人妻一区二区三区日产乱码卜| 国产精品原创视频| 91成人免费电影| 国产日产欧美视频| 美女av在线免费看| 亚洲国产精品自拍| 日韩精品一区二区免费| av超碰免费在线| 亚洲四区在线观看| 在线视频不卡一区二区三区| yw193.com尤物在线| 久久久久久久综合狠狠综合| 久久99精品久久久久久久久久| 成人1区2区3区| 国产美女在线观看一区| 91最新在线免费观看| 国产又粗又大又爽视频| 久久精品久久久精品美女| 国产精品入口夜色视频大尺度 | av剧情在线观看| 亚洲蜜桃精久久久久久久| 久久精品国产精品亚洲精品色| h视频在线免费| 欧美经典一区二区三区| 亚洲欧洲日本国产| 日本福利在线| 亚洲日本成人在线观看| 欧美少妇在线观看| 欧美人与性动交α欧美精品济南到 | 在线视频观看日韩| 性色av一区二区三区免费| 在线观看亚洲天堂| 久久久久久网| 国产精品一区二区电影| 国产精品毛片一区二区在线看舒淇| 精品午夜一区二区三区在线观看| 91久久精品美女| 粉嫩av一区二区夜夜嗨| 91亚洲国产成人精品一区二三| 久久久久久国产精品mv| 黄色av网址在线免费观看| 国产精品乱码一区二三区小蝌蚪| 手机福利在线视频| wwwwxxxx在线观看| 一本色道久久综合亚洲精品按摩| 在线观看av网页| 精品国产18久久久久久二百| 精品人伦一区二区色婷婷| 少妇饥渴放荡91麻豆| 成人羞羞网站入口| 久久久久久久亚洲精品| 久久精品视频5| 激情欧美一区二区| 精品无码久久久久国产| 免费在线午夜视频| 午夜精品福利视频网站| 亚洲最大综合网| 盗摄系列偷拍视频精品tp| 亚洲天堂视频在线观看| 国产av 一区二区三区| 国产九九精品| 成人羞羞国产免费| 天堂av中文在线资源库| **性色生活片久久毛片| 天天夜碰日日摸日日澡性色av| h1515四虎成人| 精品国精品自拍自在线| 久久久免费看片| 影音先锋久久精品| 国产精品自产拍在线观看中文| 欧美一级特黄aaaaaa大片在线观看| 欧美激情在线一区二区三区| 岛国大片在线播放| 欧美伊人亚洲伊人色综合动图| 欧美精品一区二区三区蜜桃| 精品伦精品一区二区三区视频密桃| 一本色道久久综合亚洲精品高清| 成人黄色大片在线免费观看| 亚洲av片一区二区三区| 尤物视频一区二区| 中文字幕第88页| 奇米色欧美一区二区三区| 久久久久久久久中文字幕| 国产精品乱码久久久| 中文子幕无线码一区tr| 无码人妻精品一区二区三区在线| 国产精品一区二区三区www| 亚洲日韩中文字幕| 国产成人无码精品久在线观看| 久久国产精品区| 日本一区二区三区视频免费看| 17videosex性欧美| 日韩免费性生活视频播放| 国产91在线播放九色| 日韩在线一区二区| 秋霞久久久久久一区二区| 黄视频免费在线看| 精品国产一区a| 高h视频免费观看| 精品一区二区免费| 亚洲人成网站在线播放2019| 久久爱91午夜羞羞| 亚洲精品在线不卡| 成年人免费高清视频| 成人高清在线视频| 91黄色在线看| 超碰成人在线观看| 欧美激情亚洲自拍| 黑人精品一区二区三区| 亚洲一线二线三线久久久| 久久人人爽人人片| 天天综合网网欲色| 亚洲伊人久久综合| 91蜜桃在线视频| 欧美成人综合网站| 国产 日韩 欧美 成人| 成人国产精品免费观看| 男人插女人视频在线观看| 国内精品国产成人国产三级粉色| 欧美极品少妇xxxxⅹ喷水| 国产精品区一区| 一级毛片视频在线| 制服丝袜在线91| 538精品在线观看| 国产激情91久久精品导航| 国产欧美久久久久| 红杏aⅴ成人免费视频| 国产91av在线| 国产视频福利在线| 制服丝袜激情欧洲亚洲| 青娱乐国产在线视频| 粉嫩欧美一区二区三区高清影视| 97在线国产视频| 国产欧美日韩精品一区二区免费| 国产精品久久久久久亚洲调教| 欧美极品另类| 精品免费日韩av| 国产精品一区二区三区四| 久久久国产精品午夜一区ai换脸 | 母乳一区在线观看| 午夜精品美女久久久久av福利| 亚洲人体在线| 国内精品久久久| 91社区在线观看播放| 日韩欧美国产午夜精品| wwwwww国产| 亚洲欧洲另类国产综合| jjzz黄色片| 视频一区二区国产| 欧美日韩午夜爽爽| 亚洲色图美女| 亚洲综合在线中文字幕| xxx欧美xxx| 欧美精品在线观看91| 日韩精品一二| 欧美一区二区三区白人| 在线能看的av| 亚洲男人天堂av网| av网站免费在线看| 国产盗摄女厕一区二区三区| 六月丁香婷婷在线| 午夜精品免费| 日本一区高清不卡| 2020国产精品极品色在线观看| 日韩美女福利视频| 久久99亚洲网美利坚合众国| 国产一区二区三区在线看| 精品女同一区二区三区| 欧洲激情一区二区| 日韩免费视频网站| 亚洲情趣在线观看| 国产真人做爰视频免费| 成人一级片网址| 天天影视色综合| 久久精品一区二区国产| 久久这里只有精品8| 欧美xxxxx视频| 欧美日韩免费精品| 国产精品久av福利在线观看| 国产精品国产三级国产aⅴ9色| 91资源在线观看| 欧美另类极品videosbest最新版本| 黄色av免费在线观看| 亚洲第一中文字幕在线观看| 国产精品福利电影| 欧美视频一区二区三区在线观看| 国产性xxxx高清| 亚洲一区二区三区激情| 欧美肥妇bbwbbw| 国产精品久久午夜| 美国美女黄色片| 国产视频一区不卡| 国产特黄级aaaaa片免| www.亚洲色图.com| zjzjzjzjzj亚洲女人| 国产激情视频一区二区三区欧美| 国产在线观看中文字幕| 久99久精品视频免费观看| 黄色国产小视频| 久热综合在线亚洲精品| 成人在线观看a| 香蕉国产精品偷在线观看不卡| 亚洲美免无码中文字幕在线| 国产精品第十页| 欧美中文字幕在线观看视频 | 久久69精品久久久久久久电影好| 在线观看的av| 日韩中文字幕国产| 黄色一级片在线观看| 久久天天躁日日躁| h网站久久久| 色综合老司机第九色激情| 丝袜在线观看| 午夜精品久久久久久久99黑人| 国产传媒在线| 日韩av快播网址| 高清av一区| 成人性生交xxxxx网站| 精品一区91| 国产传媒一区| 丝袜av一区| 日本一区免费观看| 久久亚洲精品中文字幕蜜潮电影| 亚洲一区三区视频在线观看| 图片区亚洲欧美小说区| 成人高清dvd| 精品不卡视频| 日本va中文字幕| 久久国内精品自在自线400部| 污视频网址在线观看| 国产乱淫av一区二区三区| 稀缺小u女呦精品呦| 久久影院午夜论| 国产激情av在线| 亚洲美女视频在线| 日本熟妇毛茸茸丰满| 欧美午夜精品久久久久久人妖| 久久久999久久久| 欧美精品 日韩| 人妻少妇精品无码专区久久| 日韩久久免费视频| 免费网站免费进入在线| 久久久免费av| 日本免费在线一区| 国产在线一区二| 成人羞羞动漫| 少妇人妻无码专区视频| 日韩中文字幕区一区有砖一区 | 日韩精品一区二区三区中文字幕| 激情久久av| 欧美激情777| 天堂…中文在线最新版在线| 美女精品自拍一二三四| 国内自拍偷拍视频| 欧美激情一区三区| 日本熟妇乱子伦xxxx| 欧美日韩精品免费| 天天摸夜夜添狠狠添婷婷 | 日本理论片午伦夜理片在线观看| 91av在线看| 日韩一区二区三区精品视频第3页| 免费看成人片| 在线播放不卡| 黄色小视频免费网站| 91麻豆文化传媒在线观看| 一起操在线播放| 在线视频一区二区三| 亚洲精品国产一区二| 伊是香蕉大人久久| 美女在线视频免费| 99re视频| 国产精品毛片久久| 99视频精品免费| 91丨九色丨蝌蚪富婆spa| 欧美成人精品欧美一级| 欧美综合亚洲图片综合区| 色一情一乱一区二区三区| 久久夜色精品国产亚洲aⅴ| 免费亚洲电影| 久久国产一区二区| 欧美午夜免费影院| 两性午夜免费视频| 国产精品久99| 成人毛片一区二区三区| 日韩精品www| 538视频在线| 成人av免费在线看| 中文字幕一区二区三区久久网站 | 亚洲第一精品在线观看| 精品日韩一区二区三区免费视频| 成人毛片av在线| 国产日韩av在线| 91亚洲成人| 日本不卡一区二区在线观看| 国产亚洲精品超碰| 天天射天天干天天| 亚洲精品在线91| 欧美色网一区| 欧美精品久久久| 羞羞视频在线观看欧美| 欧美精品黑人猛交高潮| 精品久久久香蕉免费精品视频| 蜜桃av中文字幕| 久久人91精品久久久久久不卡| 色播一区二区| 国产aaa免费视频| 成人av免费在线| 在线观看中文字幕视频| 精品亚洲永久免费精品| 黑人巨大精品| 午夜精品一区二区在线观看| 热久久免费视频| 日本少妇aaa| 欧美一区二区三级| 91av久久| 欧美亚洲精品日韩| 免费亚洲电影在线| 国产精品夜夜夜爽阿娇| 欧美一区二区三区四区高清| 中国av在线播放| 黑人另类av| 丝袜诱惑亚洲看片| 五月天免费网站| 欧美一区二区三区人| 不卡一本毛片| 欧美激情第一页在线观看| 日韩av一区二区在线影视| 欧美色视频一区二区三区在线观看| 在线成人免费观看| 丁香花在线影院| 欧美午夜精品理论片a级大开眼界 欧美午夜精品久久久久免费视 | 黄色国产小视频| 中文字幕一区三区| 亚洲精选一区二区三区| 69久久夜色精品国产7777| 欧美一区二区性| 无码国产精品久久一区免费| 五月婷婷另类国产| 岛国在线视频免费看| 91精品国产99久久久久久红楼| 亚洲精品乱码| 中国特黄一级片| 精品国产91亚洲一区二区三区婷婷| 色是在线视频| 一区二区视频在线播放| 粉嫩av亚洲一区二区图片| 欧美一区二区三区久久久| 久久影视电视剧免费网站| 另类图片第一页| 国产成人美女视频| 欧美日韩一区二区免费在线观看| 成人午夜影视| 国产精华一区二区三区| 奇米色一区二区| 国产午夜福利一区二区| 色噜噜久久综合伊人一本| 风间由美中文字幕在线看视频国产欧美 | 精品免费日产一区一区三区免费| 日本欧美久久久久免费播放网| 久久精品国产亚洲av无码娇色| 亚洲偷熟乱区亚洲香蕉av| 综合视频一区|