<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 297,  comments - 1618,  trackbacks - 0

    原文出處:http://tech.it168.com/j/2007-10-12/200710121015609.shtml
    該文請勿轉載

           Java中,其反射和動態代理機制極其強大,我們可以通過其反射機制在運行時獲取信息。而代理是一種基本的設計模式,它是一種為了提供額外的或不同的操作而插入到真實對象中的某個對象。而Java的動態代理在代理上更進一步,既能動態的創建代理對象,又能動態的調用代理方法。Java的反射和動態代理機制,使Java變得更加強大。

           Spring框架這幾年風頭正勁,雖然使用者眾多,但真正了解其內部實現原理的朋友卻并不是很多。其實,了解它的內部實現機制和設計思想是很有必要的大家都知道,Spring框架的IOCAOP部分功能強大,很值得我們學習。那么讓我們在這兩篇文章中分別詳細的學習IOCAOP的實現吧。

    在本文中,主要講述的是用Java的反射機制實現IOC。下面,讓我們開始IOC之旅吧!

    一.             Java反射機制概述與初探

    Java的反射機制是Java語言的一個重要特性,Java具有的比較突出的動態機制就是反射(reflection)。通過它,我們可以獲取如下信息:

    1) 在運行時判斷任意一個對象所屬的類;

    2) 在運行時獲取類的對象;

    3) 在運行時獲得類所具有的成員變量和方法等。

    下面讓我們通過調用一個Java Reflection API的演示實例來見識一下反射機制的強大。

    首先在IDE中建立名為reflection_proxyJava工程,并建立存放源文件的目錄src,并在src目錄下分別建立org.amigo. reflection目錄和org.amigo.proxy目錄來分別存放代理和反射的實例。我們在reflection目錄下建立ReflectionTest.java文件,在該文件中編寫代碼來演示Java Reflection API的使用。該類的代碼如下所示:

    package org.amigo.reflection;

    import java.awt.Button;
    import java.lang.reflect.Method;
    import java.util.Hashtable;

    /**
     *初探Java的反射機制.   
     *
    @author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *Creationdate:2007-10-2-上午10:13:48
     
    */

    publicclass ReflectionTest 
    {

        
    /**
         *@paramargs
         
    */

        publicstaticvoid main(String[] args) 
    throws Exception {
            ReflectionTest reflection 
    = new ReflectionTest();
            reflection.getNameTest();
            System.out.println(
    "");
            reflection.getMethodTest();
        }


        
    /**
         *Class的getName()方法測試.
         *@throwsException
         
    */

        publicvoid getNameTest() 
    throws Exception {
            System.out.println(
    "===========begin getNameTest============");
            String name 
    = "阿蜜果";
            Class cls 
    = name.getClass();
            System.out.println(
    "String類名: " + cls.getName());
            Button btn 
    = new Button();
            Class btnClass 
    = btn.getClass();
            System.out.println(
    "Button類名: " + btnClass.getName());
            Class superBtnClass 
    = btnClass.getSuperclass();
            System.out.println(
    "Button的父類名: " + superBtnClass.getName());
            Class clsTest 
    = Class.forName("java.awt.Button");
            System.out.println(
    "clsTest name: " + clsTest.getName());
            System.out.println(
    "===========end getNameTest============");
        }

        
        
    /**
         *Class的getMethod()方法測試.
         *@throwsException
         
    */

        publicvoid getMethodTest() 
    throws Exception {
            System.out.println(
    "===========begin getMethodTest==========");
            Class cls 
    = Class.forName("org.amigo.reflection.ReflectionTest");
            Class ptypes[] 
    = new Class[2];
            ptypes[
    0= Class.forName("java.lang.String");
            ptypes[
    1= Class.forName("java.util.Hashtable");
            Method method 
    = cls.getMethod("testMethod", ptypes);
            Object args[] 
    = new Object[2];
            args[
    0= "hello, my dear!";
            Hashtable
    <String, String> ht = new Hashtable<String, String>();
            ht.put(
    "name""阿蜜果");
            args[
    1= ht;

            String returnStr 
    = (String) method.invoke(new ReflectionTest(), args);
            System.out.println(
    "returnStr= " + returnStr);
            System.out.println(
    "===========end getMethodTest==========");
        }


        
    public String testMethod(String str, Hashtable ht) throws Exception {
            String returnStr 
    = "返回值";
            System.out.println(
    "測試testMethod()方法調用");
            System.out.println(
    "str= " + str);
            System.out.println(
    "名字= " + (String) ht.get("name"));
            System.out.println(
    "結束testMethod()方法調用");
            
    return returnStr;
    }

    }

         運行該例,可在控制臺看到如下內容:

    ===========begin getNameTest============

    String類名: java.lang.String

    Button類名: java.awt.Button

    Button的父類名: java.awt.Component

    clsTest name: java.awt.Button

    ===========end getNameTest============

    ===========begin getMethodTest==========

    測試testMethod()方法調用

    str= hello, my dear!

    名字= 阿蜜果

    結束testMethod()方法調用

    returnStr= 返回值

    ===========end getMethodTest==========

        分析運行結果,我們可以發現,Java的反射機制使得我們在運行時能夠判斷一個對象所屬的類,獲取對象的方法并得其進行調用,并獲取方法的返回結果等功能。

    二.             IOC使用的背景

    在我們日常的設計中,類與類之間存在著千絲萬縷的關系,如果兩個類存在著強耦合關系,那么在維護時,一個類的修改很可能會牽動另一個類的關聯修改,從而使得我們的維護工作步履維艱。下面讓我們來看這樣的一個強耦合反面例子。

    首先我們建立一個Chinese.java類,該類的sayHelloWorld(String name)方法,用中文對名為name的人問好,其內容如下:

    package org.amigo.reflection;

    /**
     *中國人類.   
     *
    @author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *Creationdate:2007-10-2-上午10:37:17
     
    */

    publicclass Chinese 
    {

        
    /**
         *用中文對某人問好.
         *@paramname姓名
         
    */

        publicvoid sayHelloWorld(String name) 
    {
           String helloWorld 
    = "你好," + name;
           System.out.println(helloWorld);
        }

    }

     

    下面我們接著建立一個American.java類,該類的sayHelloWorld(String name)方法,用英文對名為name的人問好,其內容如下:

    package org.amigo.reflection;

    /**
     *美國人類.   
     *
    @author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *@version1.0
     *Creationdate:2007-10-2-上午10:41:27

     
    */

    publicclass American 
    {

        
    /**
         *用英文對某人問好.
         *@paramname姓名
         
    */

        publicvoid sayHelloWorld(String name) 
    {
           String helloWorld 
    = "Hello," + name;
           System.out.println(helloWorld);
        }

    }

     

        最后我們編寫一個測試類對這兩個類的sayHelloWorld(String name)方法進行測試,下面是該類的內容:

    package org.amigo.reflection;

    /**
     *HelloWorld測試.
     *
    @author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     *Creationdate:2007-10-2-上午10:45:13
     
    */

    publicclass HelloWorldTest 
    {

        
    /**
         *測試Chinese和American的sayHelloWorld()方法.
         *@paramargs
         *
    @author<a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
         *Creationdate:2007-10-2-上午10:43:51
         
    */

        publicstaticvoid main(String[] args) 
    {
           Chinese chinese 
    = new Chinese();
           chinese.sayHelloWorld(
    "阿蜜果");
           
           American american 
    = new American();
           american.sayHelloWorld(
    "Amigo");
        }

    }


        觀察HelloWorldTest我們可以很清楚的看到,該類與Chinese.java類和American.java類都存在強耦合關系。

    上面的例子讓我們想到的是在N年以前,當我們需要某個東西時,我們一般是自己制造。但是當發展到了一定的階段后,工廠出現了,我們可以工廠中購買我們需要的東西,這極大的方便了我們。在上例中,我們都是通過new來創建新的對象,在開發中,這種強耦合關系是我們所不提倡的,那么我們應該如何來實現這個例子的解耦呢?我們接著想到了使用工廠模式,我們需要新建一個工廠類來完成對象的創建,并采用依賴接口的方式,此時需要對代碼進行如下修改:

    首先建立接口類Human.java,其內容如下:

    package org.amigo.reflection;

    /**
     * 人類接口類.    
     * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-10-2 - 上午11:04:56
     
    */

    public interface Human {

        
    /**
         * 對某人問好.
         * 
    @param name 姓名
         
    */

        
    public void sayHelloWorld(String name);
    }


    并將American.java類和Chinese.java類改為實現該接口,即類頭分別改成:public class American implements Humanpublic class Chinese implements Human。

    接著編寫HumanFactory.java工廠類,其內容為

    package org.amigo.reflection;

    /**
     * 工廠類.    
     * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-10-2 - 上午11:09:30
     
    */

    public class HumanFactory {

           
    /**
            * 通過類型字段獲取人的相應實例
            * 
    @param type 類型
            * 
    @return 返回相應實例
            
    */

           
    public Human getHuman(String type) {
                  
    if ("chinese".equals(type)) {
                         
    return new Chinese();
                  }
     else {
                         
    return new American();
                  }

           }

    }


    最后我們還需要修改測試類HelloWorld.java類,修改后的內容如下:

    package org.amigo.reflection;

    /**
     * HelloWorld測試.
     * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-10-2 - 上午10:45:13
     
    */

    public class HelloWorldTest {

           
    /**
            * 測試sayHelloWorld()方法.
            * 
    @param args
            * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
            * Creation date: 2007-10-2 - 上午10:43:51
            
    */

           
    public static void main(String[] args) {
                  HumanFactory factory 
    = new HumanFactory();
                  Human human1 
    = factory.getHuman("chinese");
                  human1.sayHelloWorld(
    "阿蜜果");

                  Human human2 
    = factory.getHuman("american");
                  human2.sayHelloWorld(
    "Amigo");
                  }

    }

    觀察此例我們可以看到,該類不再與具體的實現類ChineseAmerican存在耦合關系,而只是與它們的接口類Human存在耦合關系,具體對象的獲取只是通過傳入字符串來獲取,很大程度上降低了類與類之間的耦合性。

    但是我們還是不太滿足,因為還需要通過chineseamerican在類中獲取實例,那么當我們需要修改時實現時,我們還需要在類中修改這些字符串,那么還有沒有更好的辦法呢?讓我們在下節中進行繼續探討。

    三.             IOC粉墨登場

    IOCInverse of Control)可翻譯為“控制反轉”,但大多數人都習慣將它稱為“依賴注入”。在Spring中,通過IOC可以將實現類、參數信息等配置在其對應的配置文件中,那么當需要更改實現類或參數信息時,只需要修改配置文件即可,這種方法在上例的基礎上更進一步的降低了類與類之間的耦合。我們還可以對某對象所需要的其它對象進行注入,這種注入都是在配置文件中做的,SpringIOC的實現原理利用的就是Java的反射機制, Spring還充當了工廠的角色,我們不需要自己建立工廠類。Spring的工廠類會幫我們完成配置文件的讀取、利用反射機制注入對象等工作,我們可以通過bean的名稱獲取對應的對象。

    下面讓我們看看如下的模擬Springbean工廠類:

    package org.amigo.reflection;

    import java.io.InputStream;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;

    /**
     * bean工廠類.    
     * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-10-6 - 上午10:04:41
     
    */

    public class BeanFactory {
           
    private Map<String, Object> beanMap = new HashMap<String, Object>();

           
    /**
            * bean工廠的初始化.
            * 
    @param xml xml配置文件
            
    */

           
    public void init(String xml) {
                  
    try {
                         
    //讀取指定的配置文件
                         SAXReader reader = new SAXReader();
                         ClassLoader classLoader 
    = Thread.currentThread().getContextClassLoader();
                         
    //從class目錄下獲取指定的xml文件
                         InputStream ins = classLoader.getResourceAsStream(xml);
                         Document doc 
    = reader.read(ins);
                         Element root 
    = doc.getRootElement();   
                         Element foo;
                         
    //遍歷bean
                         for (Iterator i = root.elementIterator("bean"); i.hasNext();) {   
                                foo 
    = (Element) i.next();
                                
    //獲取bean的屬性id和class
                                Attribute id = foo.attribute("id");   
                                Attribute cls 
    = foo.attribute("class");
                                
    //利用Java反射機制,通過class的名稱獲取Class對象
                                Class bean = Class.forName(cls.getText());
                                
    //獲取對應class的信息
                                java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                                
    //獲取其屬性描述
    java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                                
    //設置值的方法
                                Method mSet = null;
                                
    //創建一個對象
                                Object obj = bean.newInstance();
                                
    //遍歷該bean的property屬性
                                for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {   
                                       Element foo2 
    = (Element) ite.next();
                                       
    //獲取該property的name屬性
                                       Attribute name = foo2.attribute("name");
                                      String value 
    = null;
                                       
    //獲取該property的子元素value的值
                                       for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                                              Element node 
    = (Element) ite1.next();                                          value = node.getText();
    break;
                                       }

                                       
    for (int k = 0; k < pd.length; k++{
                                              
    if (pd[k].getName().equalsIgnoreCase(name.getText())) {                                             mSet = pd[k].getWriteMethod();
    //利用Java的反射極致調用對象的某個set方法,并將值設置進去                                              mSet.invoke(obj, value);
    }

    }

    }


    //將對象放入beanMap中,其中key為id值,value為對象
    beanMap.put(id.getText(), obj);
    }

    }
     catch (Exception e) {
        System.out.println(e.toString());
    }

    }


           
    /**
            * 通過bean的id獲取bean的對象.
            * 
    @param beanName bean的id
            * 
    @return 返回對應對象
            
    */

           
    public Object getBean(String beanName) {
                  Object obj 
    = beanMap.get(beanName);
                  
    return obj;
           }


           
    /**
            * 測試方法.
            * 
    @param args
            * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
            * Creation date: 2007-10-6 - 上午11:21:14
            
    */

           
    public static void main(String[] args) {
                 BeanFactory factory 
    = new BeanFactory();
                  factory.init(
    "config.xml");
                  JavaBean javaBean 
    = (JavaBean) factory.getBean("javaBean");
                  System.out.println(
    "userName=" + javaBean.getUserName());
                  System.out.println(
    "password=" + javaBean.getPassword());
           }

    }

    該類的init(xml)方法,通過指定的xml來給對象注入屬性,為了對該類進行測試,我還需要新建一個JavaBean和在src目錄下新建一個名為config.xml的配置文件。JavaBean的內容如下:

    package org.amigo.reflection;

    /**
     * 
     * 簡單的bean,用于測試   
     * 
    @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
     * Creation date: 2007-10-6 - 上午11:24:30
     
    */

    public class JavaBean {
           
    private String userName;
           
    private String password;

        
    public String getPassword() {
                  
    return password;
           }


           
    public String getUserName() {
                  
    return userName;
           }


           
    public void setUserName(String userName) {
                  
    this.userName = userName;
           }


           
    public void setPassword(String password) {
                  
    this.password = password;
           }

    }

     

    這個簡單bean對象中有兩個屬性,分別為userNamepassword,下面我們在配置文件config.xml中對其屬性注入對應的屬性值。配置文件內容如下:

    <?xml version="1.0" encoding="UTF-8"?>

    <beans>
        
    <bean id="javaBean" class="org.amigo.reflection.JavaBean">
           
    <property name="userName">
               
    <value>阿蜜果</value>
           
    </property>
           
    <property name="password">
               
    <value>12345678</value>
           
    </property>
        
    </bean>
    </beans>

    類與配置文件都完成后,可以運行BeanFactory.java文件,控制臺顯示內容為:

    userName=阿蜜果

    password=12345678

    可以看到,雖然在main()方法中沒有對屬性賦值,但屬性值已經被注入,在BeanFactory類中的Class bean = Class.forName(cls.getText());通過類名來獲取對應的類,mSet.invoke(obj, value);通過invoke方法來調用特定對象的特定方法,實現的原理都是基于Java的反射機制,在此我們有一次見證了Java反射機制的強大。

    當然,這只是對IOC的一個簡單演示,在Spring中,情況要復雜得多,例如,可以一個bean引用另一個bean,還可以有多個配置文件、通過多種方式載入配置文件等等。不過原理還是采用Java的反射機制來實現IOC的。

    四.             總結

    在本文中,筆者通過講述Java反射機制概述與初探、IOC使用的背景、IOC粉墨登場等內容,演示了Java反射機制API的強大功能,并通過編寫自己的簡單的IOC框架,讓讀者更好的理解了IOC的實現原理。

    本文通過IOC的一個簡要實現實例,模擬了SpringIOC的實現,雖然只是完成了Spring中依賴注入的一小部分工作,但是很好的展現了Java反射機制在Spring中的應用,能使我們能更好的從原理上了解IOC的實現,也能為我們實現自己的準Spring框架提供方案,有興趣的朋友可以通過Spring的源碼進行IOC的進一步的學習。

    posted on 2007-10-12 17:41 阿蜜果 閱讀(5903) 評論(11)  編輯  收藏 所屬分類: Java 、Spring


    FeedBack:
    # re: 利用Java的反射與代理機制實現IOC和AOP(一)
    2007-10-12 18:27 | 大媽
    不錯不錯!!學習了??!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC和AOP(一)
    2007-10-12 18:59 | 北極雪
    學習!謝謝了!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC和AOP(一)[未登錄]
    2007-10-12 19:00 | BeanSoft
    多謝! 收藏了!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC和AOP(一)
    2007-10-12 19:34 | apple0668
    閱讀啦,學習!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC和AOP(一)
    2007-10-13 16:13 | 翔南
    又學習了!!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2007-10-24 13:02 | Bruce Luo
    MM,你真是厲害呀!不錯不錯!  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2008-01-01 15:02 | sgwood
    聰明的MM  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2008-08-13 23:32 | 拿著磚頭拍腦袋
    果然強大,我剛開始學spring我能拜你為師嗎??
    可以的話加我QQ:657861643  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2008-08-18 17:02 | MM
    錢為人用無需多,人為錢忙凈白忙
      回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2008-08-18 23:25 | 拿著磚頭拍腦袋
    這里例子中的文件目錄是什么樣子呀??
    我運行的程序老是報這樣的異常:
    org.dom4j.DocumentException: null Nested exception: null
    at org.dom4j.io.SAXReader.read(SAXReader.java:484)
    at org.dom4j.io.SAXReader.read(SAXReader.java:343)
    at IOCPackage.BeanFactory.init(BeanFactory.java:20)
    at IOCPackage.BeanFactory.main(BeanFactory.java:65)
    Nested exception:
    java.net.MalformedURLException
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.dom4j.io.SAXReader.read(SAXReader.java:465)
    at org.dom4j.io.SAXReader.read(SAXReader.java:343)
    at IOCPackage.BeanFactory.init(BeanFactory.java:20)
    at IOCPackage.BeanFactory.main(BeanFactory.java:65)
    Nested exception: java.net.MalformedURLException
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.dom4j.io.SAXReader.read(SAXReader.java:465)
    at org.dom4j.io.SAXReader.read(SAXReader.java:343)
    at IOCPackage.BeanFactory.init(BeanFactory.java:20)
    at IOCPackage.BeanFactory.main(BeanFactory.java:65)
    Exception in thread "main" java.lang.NullPointerException
    at IOCPackage.BeanFactory.main(BeanFactory.java:67)


    期待你的回應。。。。  回復  更多評論
      
    # re: 利用Java的反射與代理機制實現IOC
    2013-06-18 00:49 | 拍磚
    該文請勿欣賞 哈哈, 感謝樓主  回復  更多評論
      
    <2007年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

          生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
          我的作品:
          玩轉Axure RP  (2015年12月出版)
          

          Power Designer系統分析與建模實戰  (2015年7月出版)
          
         Struts2+Hibernate3+Spring2   (2010年5月出版)
         

    留言簿(263)

    隨筆分類

    隨筆檔案

    文章分類

    相冊

    關注blog

    積分與排名

    • 積分 - 2294492
    • 排名 - 3

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 青青操免费在线观看| 国产人成网在线播放VA免费| 亚洲av无码成人精品国产| 午夜亚洲WWW湿好爽| 欧洲乱码伦视频免费国产| 在线观看片免费人成视频播放 | 亚洲国产成人久久综合一区| 亚洲精品无码人妻无码| 免费福利资源站在线视频| 羞羞视频免费网站在线看| 69视频在线观看免费| 波多野结衣中文字幕免费视频| 精品久久久久久久免费人妻 | 国产精品久免费的黄网站| 亚洲免费无码在线| 亚洲国产香蕉碰碰人人| 亚洲色偷偷综合亚洲AV伊人蜜桃 | 亚洲精品第一国产综合野| 成人精品国产亚洲欧洲| A级毛片高清免费视频在线播放| 999国内精品永久免费观看| 免费看国产一级片| 久久亚洲综合色一区二区三区| 91亚洲自偷在线观看国产馆| 青青视频免费在线| 99国产精品视频免费观看| 免费观看的a级毛片的网站| 亚洲人成网站在线观看播放| 亚洲AV无码成人专区| 一级毛片aa高清免费观看| ww在线观视频免费观看| 亚洲国产精品一区二区九九| 久久精品国产亚洲av麻豆色欲 | 免费精品久久天干天干| 久久精品a一国产成人免费网站| JLZZJLZZ亚洲乱熟无码| 亚洲中字慕日产2020| 成人电影在线免费观看| 麻豆国产精品入口免费观看| 亚洲精品福利视频| 男女交性无遮挡免费视频|