日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

框架复习(一):不如写个tiny-Spring?(完整版)

發(fā)布時間:2023/12/14 javascript 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 框架复习(一):不如写个tiny-Spring?(完整版) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • 框架復習(一):不如寫個tiny-Spring?
    • 項目來源
    • IOC
      • 為什么要有IOC?
      • IOC部分要實現(xiàn)什么功能?
      • 第0步:下載項目
      • 第1步:最基本的容器
      • 第2步:將bean創(chuàng)建放入工廠
      • 第3步:為Bean注入屬性
      • 第4步:讀取xml配置來初始化bean
      • 第5步:為bean注入bean
      • 第6步:ApplicationContext登場
    • AOP
      • 理解動態(tài)代理設計模式
      • 理解AOP
      • Spring AOP與Aspect
      • 第7步:使用JDK動態(tài)代理實現(xiàn)AOP織入
      • 第8步:使用AspectJ管理切面
      • 第9.1步:完善Bean的生命周期
      • 第9.2步:將AOP融入Bean的創(chuàng)建過程
      • 第9.3步:目前還存在的問題
        • 原作者代碼中的一個錯誤
        • 修正錯誤后帶來的新問題
        • 只能對接口代理
      • 第9.4步:萬惡之源
      • 第10步:使用CGLib進行類的織入
        • 如何使用CGLib實現(xiàn)動態(tài)代理
      • 第11步:通過三級緩存徹底解決循環(huán)依賴
    • 小結

框架復習(一):不如寫個tiny-Spring?

項目來源

https://github.com/code4craft/tiny-spring

IOC

https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484247&idx=1&sn=e228e29e344559e469ac3ecfa9715217&chksm=ebd74256dca0cb40059f3f627fc9450f916c1e1b39ba741842d91774f5bb7f518063e5acf5a0#rd

為什么要有IOC?

https://www.zhihu.com/question/23277575

  • 什么是依賴?

依賴,可以粗暴地理解為import,如果代碼中import了某個類,那這段代碼就依賴了這個類。面向接口編程時,邏輯都是接口邏輯(例如接口IA,有方法doX,doY,接口邏輯例如是main中實例化了IA后,順序執(zhí)行了doX和doY),但具體實例化的對象是IA接口的實現(xiàn)(例如類CA實現(xiàn)了IA,重寫了方法doX,doY)。如果不用工廠,直接new,那么main文件里面就必須import了CA,也就是main“依賴”了CA這個實現(xiàn)。而面向接口編程中,main應該跟CA解耦(就是不直接依賴CA,不會看到import CA)。工廠方法就是解決這種import CA的解決途徑之一,簡單工廠為例,原本main里面的IA a = new CA(),就變成了IA a = AFactory.getA(“CA”),并且getA的具體實現(xiàn)中,可以通過如果是字符串“CA”就new CA()返回了。這樣子的話,main里面就不用import CA了(但是要import AFactory),也即是不“依賴”CA,與CA解耦了。依賴注入,就是把上面的工廠,獲取CA對象的方式,變成反射(也還是根據(jù)字符串來生成對象,不過就不用簡單工廠if-else那么粗暴了,多一個if又要改一遍工廠的實現(xiàn),多累啊),根據(jù)配置來生成對象。不用import某個實際類,但是也把依賴(邏輯過程實際執(zhí)行還是CA來做的)給注入(放到main中)了。(上述的main指代任意一個邏輯執(zhí)行過程,不一定是main函數(shù))

  • 依賴注入,把底層類作為參數(shù)傳入上層類,實現(xiàn)上層類對下層類的控制。A類中:@Autowird B b;那不論B類怎么改變,都不需要改變A類中的代碼。比如構造函數(shù)創(chuàng)建A(B b),還有Setter創(chuàng)建。反轉A類中不應該B b=new b(),而是應該從外界注入。
    • 從哪個外界注入呢?Spring設計的是IOC容器,相當于是框架本身管理注入過程。相當于A需要B b的時候,框架就getBean(“b”)給A類。
    • 如果A需要b,B需要a,怎么注入?控制反轉,交給IOC容器去解決。tiny-spring的實現(xiàn)思路:先根據(jù)xml獲得全部bean標簽內容,然后在getBean的時候再lazy-init。這樣A需要b時,會先創(chuàng)建A,當遇到b時轉而去創(chuàng)建b,最后在創(chuàng)建出完成的A。整個類似于一個遞歸(dfs)的過程。
  • IOC,控制反轉,通過配置文件/注解自動對對象進行初始化
    • 控制反轉解決了對象層級嵌套的問題,在創(chuàng)建一個對象時可以自動創(chuàng)建依賴對象并注入,Spring的IOC容器實現(xiàn)了從xml或注解中進行自動初始化。
    • 控制反轉容器因為是自上而下創(chuàng)建實例的,因此不需要知道其依賴類的創(chuàng)建方法,屏蔽了內部的細節(jié),從外部看像一個工廠。

IOC部分要實現(xiàn)什么功能?

  • 讀取XML文件,標簽為beans和property
  • property內標簽可為value或ref,即支持依賴注入
  • 封裝成ApplicationContext創(chuàng)建所有的bean,并且解決循環(huán)依賴
  • TODO:注解版和Java配置版
  • 第0步:下載項目

    https://github.com/code4craft/tiny-spring

    • 請用git clone下載,這樣才能夠通過git checkout step-1-container-register-and-get一步一步的查看不同版本。

    第1步:最基本的容器

    • 最基本的容器是指BeanFactory和BeanDefinition。前者有一個ConcurrentHashMap<String,BeanDefinition>,因為實現(xiàn)xml中字符串id對對象實例的映射。BeanDefinition包裝了Bean。

    第2步:將bean創(chuàng)建放入工廠

    • Spring中Bean實例的生成是由容器控制的,而不是由用戶,因此Bean對象的創(chuàng)建要放在BeanFactory中。為了仿照Spring,因此抽象出FactoryBean接口,AbstractBeanFactory模板類。模板類中最重要的是protected doCreateBean()。

    • 在注冊的時候通過反射調用doCreateBean方法創(chuàng)建對象,并放入BeanDefinition包裝類中。doCreateBean相當于是個動態(tài)工廠,根據(jù)string類型的全類名反射出一個Object對象。

      public void registerBeanDefinition(String name,BeanDefinition beanDefinition){Object bean = doCreateBean(beanDefinition);beanDefinition.setBean(bean);beanDefinitionMap.put(name,beanDefinition); }
    • 到這一步就實現(xiàn)了BeanFactory的實現(xiàn)類可以通過全類名創(chuàng)建一個對象。

      public class BeanFactoryTest {@Testpublic void test(){BeanFactory beanFactory = new AutowireCapableBeanFactory();BeanDefinition beanDefinition = new BeanDefinition();//創(chuàng)建一個包裝類beanDefinition.setBeanClassName("beans.Car");//通過反射創(chuàng)建,要求必須有無參構造函數(shù)beanFactory.registerBeanDefinition("audi",beanDefinition);//注冊到hashmap中,注冊之前先調用doCreateObject方法創(chuàng)建對象,實現(xiàn)了在Facoty中創(chuàng)建對象System.out.println((Car)beanFactory.getBean("audi"));} }
    • 在看上述代碼,我們要傳給factory什么?1.全類名,即beans.Car。2.實例化后的實例名稱,即audi。這兩項顯然我們都能在配置的xml中獲取,這在第四步中完成。其次,我們目前創(chuàng)建出的對象還是一個依靠無參構造函數(shù)創(chuàng)建的,因此內部成員變量均為null,所以下一步是對成員變量進行賦值。

    第3步:為Bean注入屬性

    • 這一步有兩個類,PropertyValues和PropertyValue。PV類相當于是C++中的Pair<String fieldName,Object Value>類,保存字段和字段對應的值。PVS中保存了一個對象中所有字段和值的對應關系,即保存了一個List。每個BeanDefinition中都有一個PVS,因此每個BeanDefinition在創(chuàng)建完空Bean后可以遍歷PVS,通過反射實現(xiàn)Setter。

      protected void applyPropertyValues(Object bean,BeanDefinition mbd) throws NoSuchFieldException, IllegalAccessException {for(PropertyValue propertyValue:mbd.getPropertyValues().getPropertyValues()){Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());declaredField.setAccessible(true);declaredField.set(bean,propertyValue.getValue());} }

    第4步:讀取xml配置來初始化bean

    • 解決獲取IO流的問題?URL類定位xml文件,url.openConnect().connect()即可定位并打開文件,利用getInputStream獲得文件輸入流。
    • 通過XMLBeanDefinitionReader類和DocumentBuilder對xml進行解析。先根據(jù)bean定位到所有的bean,根據(jù)類名和實例名構建一個空實例,然后每一個bean中定位property,利用PVS類和PV類實現(xiàn)對bean屬性的賦值
    • 官方結構

    第5步:為bean注入bean

    • 核心解決三個問題1.ref怎么實現(xiàn)?2.怎么解決xml中順序問題?2.怎么避免循環(huán)依賴?
  • 怎么實現(xiàn)ref?

    • 這個問題好解決。判斷xml中是ref還是value,如果是value(本項目目前value如果是基本類型,只允許是String)則直接用PV(PropertyValue)封裝,如果是ref,就用BeanReference{name,bean}封裝一下然后再用PV封裝。

      private void processProperty(Element ele, BeanDefinition beanDefinition) {NodeList propertyNode = ele.getElementsByTagName("property");for (int i = 0; i < propertyNode.getLength(); i++) {Node node = propertyNode.item(i);if (node instanceof Element) {Element propertyEle = (Element) node;String name = propertyEle.getAttribute("name");String value = propertyEle.getAttribute("value");if (value != null && value.length() > 0) {beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));} else {String ref = propertyEle.getAttribute("ref");if (ref == null || ref.length() == 0) {throw new IllegalArgumentException("Configuration problem: <property> element for property '"+ name + "' must specify a ref or value");}BeanReference beanReference = new BeanReference(ref);beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference));}}} }
    • 在調用applyPropertyValues()方法——通過反射裝填實例的成員變量時,如果該變量是BeanReference,則該變量有可能需要創(chuàng)建一下。

      protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());declaredField.setAccessible(true);Object value = propertyValue.getValue();if (value instanceof BeanReference) {BeanReference beanReference = (BeanReference) value;value = getBean(beanReference.getName());}declaredField.set(bean, value);} }
    • 注意上述代碼中的value=getBean(beanReference.getName())。實例的創(chuàng)建過程有可能就在此刻完成。這里需要明確的是下圖:
      讀取xml后,所有的類信息都在XmlBeanDefinitionReader實例中,但是XmlBDFR中的beanDefinition們并沒有創(chuàng)建實例,即空有類信息(className,PropertyValues),但是bean為null。此時,如果遇到A實例a的b字段ref C實例c,但是此刻C實例c還未初始化,在裝配A實例a的b字段的時候,就會用getBean創(chuàng)建c。(為什么能創(chuàng)建c呢?因為在創(chuàng)建工廠后,緊接著的操作就是把xmlBDFR中的所有beanDefinition寫入工廠的ConcurrentHashMap中,即工廠也有了全部的信息,因此可以創(chuàng)建c。)

      BeanFactory beanFactory = new AutowireCapableBeanFactory(); for(Map.Entry<String,BeanDefinition> beanDefinitionEntry:xmlBeanDefinitionReader.getRegistry().entrySet()){beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(),beanDefinitionEntry.getValue()); } ((AutowireCapableBeanFactory) beanFactory).preInstantiateSingletons();
  • 通過getBean時創(chuàng)建實例的這種lazy-init方式,實現(xiàn)了不依靠xml中順序。這樣再創(chuàng)建實例的時候如果實例的依賴還沒有創(chuàng)建,就先創(chuàng)建依賴。

  • 所謂循環(huán)依賴是類似以下的情況

    <bean name="outputService" class="com.sonihr.beans.OutputService"><property name="helloWorldService" ref="helloWorldService"></property> </bean><bean name="helloWorldService" class="com.sonihr.beans.HelloWorldServiceImpl"><property name="text" value="Hello World!"></property><property name="outputService" ref="outputService"></property> </bean>

    在doCreateBean中,創(chuàng)建完空的bean(空的bean表示空構造函數(shù)構造出的bean)后,就放入beanDefinition中,這樣a ref b,b ref a時,a ref b因此b先創(chuàng)建并指向a,此時的a還不是完全體,但是引用已經連上了,然后創(chuàng)建好了b。然后b ref a的時候,a已經創(chuàng)建完畢。

  • 第6步:ApplicationContext登場

    • 這一步就是用ApplicationContext包裝之前的代碼public void refresh() throws Exception {XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());xmlBeanDefinitionReader.loadBeanDefinitions(configLocation);for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());} }![](http://img.sonihr.com/6a51bce1-149f-4ad0-8d9b-2b4f33c6399b.jpg)
    • 這樣只要如下調用即可 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc.xml"); ((ClassPathXmlApplicationContext) applicationContext).refresh(); System.out.println(applicationContext.getBean("car2"));

    AOP

    https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247483954&idx=1&sn=b34e385ed716edf6f58998ec329f9867&chksm=ebd74333dca0ca257a77c02ab458300ef982adff3cf37eb6d8d2f985f11df5cc07ef17f659d4#rd

    理解動態(tài)代理設計模式

    • 靜態(tài)代理模式

      通過構造函數(shù)注入的方式,將被代理類B的實例b注入Proxy中,然后Proxy實現(xiàn)A接口a方法時,在調用b.a()之前之后都可以寫自己的代理邏輯代碼。

    • 動態(tài)代理模式

      將接口A的字節(jié)碼文件+一個構造器,這個構造器繼承自Proxy,就構成了代理類的基本字節(jié)碼。Prxoy構造器中必然依賴InvocationHandler實例,這個InovocationHandler實例要重寫invoke方法以實現(xiàn)1.Proxy中所有A接口方法全部使用handler.invoke。2.hanler.invoke()調用被代理實例的a(),并且可以在其中寫代理邏輯。3.Proxy的a方法調用的invoke,則內部就代理a方法。

      分解操作:

      public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//指定被代理類實例Car target = new Car();//指定類加載器和接口Class carClazz = Proxy.getProxyClass(target.getClass().getClassLoader(),Drivebale.class);//創(chuàng)建構造函數(shù)Constructor constructor = carClazz.getConstructor(InvocationHandler.class);//反射創(chuàng)建代理類實例Drivebale car = (Drivebale) constructor.newInstance(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前");method.invoke(target,args);System.out.println("后");return null;}});car.running(); }

      一句話版本:

      public static void main(String[] args) {Car target = new Car();Drivebale car = (Drivebale) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("這就是JDK動態(tài)代理的正確用法");method.invoke(target,args);System.out.println("結束");return null;}});car.running(); }
    • 靜態(tài)代理和動態(tài)代理的區(qū)別

      本質區(qū)別,靜態(tài)代理是在運行期之前就編譯好的class文件,動態(tài)代理是運行期中生成的class文件。

    • 代理模式和裝飾模式的區(qū)別

      • 相同點都是返回一個功能更豐富的類。
      • 代理模式強調與被代理類無關的功能,比如被代理類是核心業(yè)務邏輯代碼,代理模式增加日志等輔助功能。包裝模式強調對被包裝類進行功能性的加強。
      • 代理模式控制對方法的訪問,可以不讓訪問者知道被代理的對象,Thread(Runnable target),MyBatis的Mapper。裝飾著模式為方法添加額外的行為,一般通過構造函數(shù)注入,IO流。
    • 代理模式的應用

      • 靜態(tài)代理:Thread implements Runnable,Thread(Runnable target),thread.run{target.run}。我們只用關心Runnable的業(yè)務邏輯,而不用關系線程創(chuàng)建,銷毀等具體的事情。

      • 動態(tài)代理:MyBatis中的Mapper。

        https://blog.csdn.net/xiaokang123456kao/article/details/76228684

        SqlSession session = sqlSessionFactory.openSession(); //獲取mapper接口的代理對象 UserMapper userMapper = session.getMapper(UserMapper.class); //調用代理對象方法 User user = userMapper.findUserById(27);

        比如UserMapper這個接口,如果要用靜態(tài)代理,就必須手動寫一個實現(xiàn)該接口的代理類,如果你有很多個接口,就要寫很多個代理類,工作量很大。但是采用動態(tài)代理后,XXXMapperProxy通過反射實現(xiàn)XxxMapper接口內方法并創(chuàng)建構造函數(shù),創(chuàng)建后在invoke中實現(xiàn)邏輯。

    理解AOP

    https://blog.csdn.net/javazejian/article/details/56267036

    • 為什么要有AOP?

      • 在面向對象編程的這些年,我們遇到了一些問題。


      參數(shù)檢查,日志,異常處理,事務開始和提交,這些都是重復代碼,怎么解決呢?面向切面編程,將這些功能抽取出來,然后定義point cut(切入點),在point cut上進功能的weaving織入,從而形成一個aspect切面。

    • 專屬名詞

      • join point:Spring中每個方法都可以是join point

      • point cut:我們想要切入的那些join point

      • advice:通知,即代理邏輯代碼

      • aspect:point cut+advice等于一個切面

      • weaving:切面應用到目標函數(shù)的過程

    Spring AOP與Aspect

    https://zhuanlan.zhihu.com/p/24565766

    • Spring aop和Aspect不是一個東西

    • Aspect是一套獨立的面向切面編程的實現(xiàn)方案,通過編譯器實現(xiàn)靜態(tài)織入.

    • Spring AOP基于動態(tài)代理設計模式的動態(tài)織入,基礎技術為jdk動態(tài)代理和CGLIB技術,前者基于反射技術且只應用于接口,后者基于繼承了用于類。

    • Spring AOP使用了Aspect的部分內容(主要是實現(xiàn)XML配置解析和類似 Aspectj 注解方式的時候,借用了 aspectjweaver.jar 中定義的一些annotation 和 class),但是并沒有使用其編譯器和織入器,可以認為是Aspect風格的,但是實現(xiàn)完全不同。

    • AOP Alliance 是AOP的接口標準,定義了 AOP 中的基礎概念(Advice、CutPoint、Advisor等),目標是為各種AOP實現(xiàn)提供統(tǒng)一的接口,本身并不是一種 AOP 的實現(xiàn)。Spring AOP, GUICE等都采用了AOP Alliance中定義的接口,因而這些lib都需要依賴 aopalliance.jar。

    第7步:使用JDK動態(tài)代理實現(xiàn)AOP織入

    • 這一步我們就是利用之前說到的動態(tài)代理模式,幾乎一模一樣的完成織入。想一下,我們實現(xiàn)動態(tài)代理要用Proxy.newInstance,我們可以封裝一個動態(tài)代理類,就叫做JdkDynamicAopProxy implements InvocationHandler。由之前的動態(tài)代理知識可知,實現(xiàn)了InvocationHandler就必須實現(xiàn)invoke方法,那我們這樣寫:

      @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// MethodInterceptor methodInterceptor = advised.getMethodInterceptor();// return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(),method,args));System.out.println("方法開始");Object result = method.invoke(advised.getTargetSource().getTarget(),args);System.out.println("方法結束");return result; }

      這樣就可以將所有代理方法前后打印兩句話了。我們通過getProxy返回構造好的代理類:return Proxy(getClass.getClassLoader,new Class[]{target.getClass},this。因為本類就是InvocationHandler的實現(xiàn)類,因此最后一個用this即可。

    • 我們知道想成功代理一個實例需要2個要素1.被代理的實例2.被代理的接口。我們用AdvisedSupport進行封裝,包括target、targetClass(其實應該是targetInterface)(前兩個被封裝進TargetSource,而TargetSource被封裝進AdvisedSupport)、methodInterceptor.等一下,methodInterceptor是個什么吊參數(shù)?

    • 聰明的小朋友已經發(fā)現(xiàn)了,按照我們這樣寫,功能只能是對被代理的方法前后加一句話而已,那有沒有一種方式能讓我們能定制對方法調用時進行的控制?有,就是MethodInterceptor,即方法攔截器類。

      http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInterceptor.html

      • MethodInterceptor,環(huán)繞切點進行織入
      • MethodBeforeAdvice,切點前側織入
      • MethodAfterAdvice,切點后側織入
      • ThrowsAdvice,切點的目標方法出現(xiàn)異常時調用
    • 與上文采用的動態(tài)代理不同,我們可以通過配置攔截器來配置不同的代理邏輯。但是注意methodInterceptor.invoke方法中還有個methodInvovation,這個類用于調用我們的target的方法,因此這個類需要target實例,method和args。

    • 所以其實啊MethodInvocation就是point cut,而MethodInterceptor就是advice,Invocation負責調用target方法即切點方法,Interceptor負責代理邏輯即advice。

    • 這一步到此為止可以做到:1.寫一個實現(xiàn)MethodInterceptor的實現(xiàn)類,實現(xiàn)增強功能。2.實現(xiàn)對接口方法的代理。

      // 1. 設置被代理對象(Joinpoint) AdvisedSupport advisedSupport = new AdvisedSupport(); TargetSource targetSource = new TargetSource(car,Driveable.class); advisedSupport.setTargetSource(targetSource);// 2. 設置攔截器(Advice) TimerInterceptor timerInterceptor = new TimerInterceptor(); advisedSupport.setMethodInterceptor(timerInterceptor);// 3. 創(chuàng)建代理(Proxy) JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport); Driveable carProxy = (Driveable)jdkDynamicAopProxy.getProxy();// 4. 基于AOP的調用 carProxy.running();
    • 給出一個AOP采用的動態(tài)代理方式的小demo

      class ReflectMethodInvocation implements MethodInvocation{private Method method;private Object target;private Object[] args;public ReflectMethodInvocation(Method method, Object target, Object[] args) {this.method = method;this.target = target;this.args = args;}@Overridepublic Method getMethod() {return method;}@Overridepublic Object[] getArguments() {return args;}@Overridepublic Object proceed() throws Throwable {return method.invoke(target,args);}@Overridepublic Object getThis() {return target;}@Overridepublic AccessibleObject getStaticPart() {return method;} }public class JdkAopNew {public static void main(String[] args) {Car car = new Car();MethodInterceptor methodInterceptor = new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {System.out.println("攔截器方式動態(tài)代理前");methodInvocation.proceed();System.out.println("后");return null;}};Drivebale drivebale = (Drivebale) Proxy.newProxyInstance(car.getClass().getClassLoader(), car.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return methodInterceptor.invoke(new ReflectMethodInvocation(method,car,args));}});drivebale.running();} }

    第8步:使用AspectJ管理切面

    • 第7步解決了怎么織入的問題,下面就是在哪里織入?Spring采用了AspectJ風格的標示性語句來表示在哪些位置進行織入,即哪些位置是point cut。類似下面的語句<aop:pointcut id="pointcut" expression="execution(public int aopxml.Calculator.*(int, int ))"/>。Spring可以對類和方法做插入,因此我們也要實現(xiàn)對類和方法表示point cut的功能。

    • 先寫出ClassFilter接口和MethodMathcer接口,望文生義的說前者是類過濾器,后者是方法匹配器。具體怎么匹配呢?就在我們的AspectJExpressionPointcut中。

    • AspectJExpressionPintcut中要做這樣幾件事1.獲得String expression即AspectJ風格表達式2.創(chuàng)建PonitcutParser,即解析AspectJ風格表達式的解析器。3.expression被解析后就變成了pointcutExpression。即expression是輸入,pointcutParser是輸出,pointcutParser是解析器,將輸入解析成輸出。這個解析器怎么創(chuàng)建呢?直接new一個行不行啊?不行。正確的創(chuàng)建方式為:pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);后面的supportedPrimitives指的是執(zhí)行的AspectJ語言風格的關鍵字,是一個set。那請問支持哪些關鍵字呢?去org.aspectj.weaver.tools包內的PointPrimitive就可以看奧。

      可以看出pointcutExpression是對expression的封裝。

    • pointcutExpression是創(chuàng)建好了,但是有什么用呢?這個類可以用于匹配方法和類。

      //匹配類 pointcutExpression.couldMatchJoinPointsInType(targetClass); //匹配方法 ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
    • 所以其實AspectJ包已經幫你做好了解析和匹配的事兒,只不過你不會用他的編譯器,你用動態(tài)代理的方式實現(xiàn)了織入。

    • AspectJExpressionPointcutAdvisor封裝了pointcut和advice,實現(xiàn)了一個完整的切面,切面=切點+advice。p.s.advice就是代理邏輯代碼。

    第9.1步:完善Bean的生命周期

    • 生命周期,最后還有一個destroy沒有顯示出來。
    • BeanPostProcessor接口(下稱BPP接口)是AOP在Bean創(chuàng)建方面的應用——根據(jù)Spring的生命周期,BeanPostProcessor是在創(chuàng)建Bean的構造函數(shù),setter方法后。并且所有BPP接口實例都不會受到BPP影響,即BPP的實例過程不會有before和after的影響。
    • BPP接口實例要率先被實例化,并且實例化過程幾乎不會存在依賴ref。
    • 一般實例的創(chuàng)建過程

    第9.2步:將AOP融入Bean的創(chuàng)建過程

    • 第7和第8步我們已經完成了AOP的point識別和識別后的織入,但是兩個功能沒有整合,同時也沒有和Spring的IOC整合起來。目的是為了,IOC給我們的容器已經不再是我們自己寫的實例,而是被織入了advice的實例——如果該類在pointcut則返回new JdkDynamicAopProxy,否則返回bean。

      public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {if (bean instanceof AspectJExpressionPointcutAdvisor) {return bean;}if (bean instanceof MethodInterceptor) {return bean;}List<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansForType(AspectJExpressionPointcutAdvisor.class);for (AspectJExpressionPointcutAdvisor advisor : advisors) {if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {AdvisedSupport advisedSupport = new AdvisedSupport();advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());TargetSource targetSource = new TargetSource(bean, bean.getClass().getInterfaces());advisedSupport.setTargetSource(targetSource);return new JdkDynamicAopProxy(advisedSupport).getProxy();}}return bean; }
    • 第一幕:和9.1非常類似的,僅有標紅出不同。因為AspectJAwareAdvisorAutoProxyCreator implements BBP,BeanFactoryWare,因此不同僅僅是,因為實現(xiàn)了BeanFactoryAware接口,因此調用setFactory方法。這一步的目的是為了是的AspectAwareAdvisorAutoProxyCreator中具有beanFactory,方便從中獲取AspectJExpressionPointcutAdvisor.class類的實例。

    • 第二幕:這一幕是目前為止最復雜也最重量級的。相當于把第9.1步和7,8兩步合起來了,歸納如下:

    • 首先因為autoProxyCreator implements BBP,BeanFactoryAware,因此其必然先于所有一般實例和AOP實例創(chuàng)建,而且所有一般實例和AOP實例都必然要經過autoProxyCreator的before和after處理
    • 當實例化一般實例和AOP實例時,after中對實例進行檢查,如果其肯定不需要代理,比如說是提供代理pointcut與advice的AspectJExpressionPointcutAdvisor或是提供advice的methodInterceptor。如果和expression給出的表達式不匹配的類也不進行代理。對那些對expression匹配的類,就返回proxy類實例代替原來的bean。
    • 小結:1.先通過BBP接口特性實現(xiàn)每個非BBP實例都必須經過BBP實例的before和after方法。2.正是因為BBP的這種特性,因此after方法中對非BBP實例進行檢查,如果和expression表示的point cut匹配則返回代理對象,否則返回原對象。
    • 第一幕創(chuàng)建BBP實例,以編譯對所有非BBP實例進行before、after操作。第二幕通過判斷該類是否為point cut從而確認返回原實例還是代理實例,到第二幕已經將實例創(chuàng)建完畢。第三幕指的是,當實例調用接口方法時,如果該方法是pointcut,則會調用如下流程:

      invocationHandler.invoke(proxy,method,args)調用methodInterceptor.invoke(methodInvocation),methodInterceptor內部進行1.代理編碼的實現(xiàn)2.函數(shù)參數(shù)methodInvocation調用proceed,從而執(zhí)行被代理實例的method方法。因為methodInvocation要可以調用被代理實例的method,因此methodInvocation當你想要實現(xiàn)這個接口時,必須要指定被代理實例target,被代理實例的方法method和參數(shù)args。

    第9.3步:目前還存在的問題

    原作者代碼中的一個錯誤

    • 來自Github原項目的Issues中:

      https://github.com/code4craft/tiny-spring/issues/10
      問題是:在進行測試的時候,發(fā)現(xiàn)調用非BPP實例的接口方法時,并沒有被代理。

    • 什么原因呢?原Issues里面也說了,要加上一句beanDefinition.setBean(bean).這句話是不是有些眼熟?邏輯是這樣的:
    • 先給出非AOP實例(即實例沒有pointcut)情況下,這部分的詳細邏輯
    • 再給出有AOP(即有pointcut,需要代理)情況下,這部分的詳細邏輯

      可以看到,第一次setBean實現(xiàn)了將beanDefinition.bean指向內存空間a。此時bean和beanDefinition.bean指向了同一塊內存區(qū)域,因此對bean的操作本質上是對內存空間a的操作,而beanDefinition.bean也指向這塊內存區(qū)域,因此對這塊區(qū)域propertyvalue的賦值不影響beanDefinition.bean的引用關系。
      **但是!**當return new之后,bean已經指向了不同的內存空間b,beanDefinition.bean仍然指向內存空間a,因此需要重新set。

    修正錯誤后帶來的新問題

    • 來自Github原項目的Issues中:

      https://github.com/code4craft/tiny-spring/issues/17
      問題是:如果a ref b,b ref a,且順序也是這樣。

    • 這個問題很奇怪。我們看看在實際Spring中的實驗效果:

      • 實驗準備:

      這些類望文知意我就不解釋了。

      而且確實是循環(huán)依賴的

      • 實驗過程:

      • 實驗一:

        可以看出,單獨的calculator和book都可以被正常代理。當然,在TinySpring中也是符合的。

      • 實驗二:

        在Spring中,接口實現(xiàn)類根本不用考慮這個問題,因為根本無法運行。邏輯在于,你獲得的A和B本質上都是代理類,代理類只實現(xiàn)了代理接口,因此無法強轉為某一個具體的實現(xiàn)類。所以A.B.b()和B.A.a()從本質上根本就不會強轉成功。

      • 實驗三:

        怎么樣才能正確進行這個實驗呢?上一個回答說到,不能進行實驗的本質是因為只能代理接口而不能代理類,所以Spring通過Cglib實現(xiàn)類代理。

        通過proxy-target-class標記為true后,強制開啟cglib,此時再看實驗結果。


        成功!

      • 小結論實驗三證明,強制開啟Chlib后,可以進行本實驗,且Spring解決了循環(huán)依賴的問題。那原作者的tiny spring是不是進行第10步之后,就解決了呢?答案是沒有,因為Cglib只是讓我們的實驗可以正常進行,不代表能解決這個問題。Spring是通過三級緩存解決的。

        上圖是第10步做完后的效果,發(fā)現(xiàn)問題還未解決。

    只能對接口代理

    • 只能對接口代理,為了對這個問題有深入的認識,我們舉出以下兩個例子:
      • 例子1:CA implements A。CA類中出了有A接口的a()以外,還有c(),當動態(tài)代理后,返回的CA類實例是proxy,因此只能轉換為A類型,所以永遠無法使用c()。這要求,CA中所有方法必須實現(xiàn)A。
      • 例子2:CA implements A,CB implements B。CA中有CB類型的成員變量,CB中有CA類型的成員變量。抱歉,不行。為什么?因為CA類型實例正在創(chuàng)建的過程中因為ca ref cb會先創(chuàng)建cb,但是cb返回的是proxy實例而不是CB實例,因此proxy實例無法賦值給cb。

    第9.4步:萬惡之源

    • 萬惡之源就是,AOP如果用動態(tài)代理實現(xiàn),從根本上就意味著只能代理接口方法。有沒有一種方式可以代理類,而不僅僅是借口呢?抱歉,還真的有。

    第10步:使用CGLib進行類的織入

    如何使用CGLib實現(xiàn)動態(tài)代理

    • CGlib的原理是通過對字節(jié)碼的操作,可以動態(tài)的生成一個目標實例類的子類,這個子類和目標實例的子類相同的基礎上,還增加了代理代碼或者叫advice。代理類 = 被代理類+增強邏輯

      • CGlib動態(tài)代理
      class Student{private String name = "zhang san";public String getName() {System.out.println(name);return name;}public void setName(String name) {this.name = name;} } public class CglibMthodTwo implements MethodInterceptor {public Object getProxy(Class clazz){Enhancer en = new Enhancer();en.setSuperclass(clazz);en.setCallback(this);Object proxy = en.create();return proxy;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("前");Object res = methodProxy.invokeSuper(o,objects);System.out.println("后");return res;}public static void main(String[] args) {CglibMthodTwo cglibMthodTwo = new CglibMthodTwo();((Student)cglibMthodTwo.getProxy(Student.class)).getName();}}
      • JDK動態(tài)代理。
      public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler {public JdkDynamicAopProxy(AdvisedSupport advised) {super(advised);}@Overridepublic Object getProxy() {return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getInterfaces(), this);}@Overridepublic Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {MethodInterceptor methodInterceptor = advised.getMethodInterceptor();Object res = null;if (advised.getMethodMatcher() != null&& advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {res = methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(),method, args));} else {res = method.invoke(advised.getTargetSource().getTarget(), args);}return res;}}
    • 與JDK動態(tài)代理的區(qū)別

      • 原理上JDK沒有修改字節(jié)碼,而是采用$proxyn extend Proxy implements InterfaceXXX的方式創(chuàng)建了一個被代理接口的實現(xiàn)類,然后在運行期寫class文件,再用classloader加載。而CGlib卻是操作字節(jié)碼,將被代理類的字節(jié)碼增強成一個子類,因此要導入ASM包。
      • 操作上,JDK動態(tài)代理創(chuàng)建為Proxy類實例,且必須要傳入InvocationHandler類,而Cglib創(chuàng)建為Enhancer類實例,且必須傳入MethodInterceptor類(注意包的問題,這個MethodInterceptor是CGlib中的)。
      • Advice即代理代碼的實現(xiàn)上,JDK動態(tài)代理可以在InvocationHandler中重寫invoke實現(xiàn),或者在InvocationHandler.invoke中調用methodInterceptor.invoke(methodInvocation),將代理的業(yè)務代碼交給methodInterceptor去做,被代理實例方法的運行通過參數(shù)methodInvocation.proceed()實現(xiàn)。而在CGlib中,通過methodInterceptor.intercept()實現(xiàn)代理增強,值得注意的是,這個方法內部有四個參數(shù),包括一個被代理實例,而JDK的InvocationHandler.invoke卻不包含被代理實例。
      • 在運行方法上,JDK代理類實例.a()的運行流程為先運行InvocationHandler.invoke,在invoke中運行methodInterceptor.invoke,在這個invoke中有代理邏輯代碼和methodInvocation.proceed(),從而實現(xiàn)代理邏輯與被代理實例方法的兩開花。而CGlib則是直接運行methodInterceptor.interceptor方法。注意,這一條很重要。
    • 為什么說運行方法上的差異很重要呢,因為這會導致步驟9的代碼不可復用。因為我們原來寫的都是JDK代理類實例的那一套代碼,如果用CGlib的話,就無法通過注入org.aopalliance.intercept.MethodInterceptor的方式實現(xiàn)增強,而是注入cglib的MethodInterceptor,通過setCallback可以設置不同methodInterceptor。有沒有一種辦法,讓我們配置一種org.aopalliance.intercept.MethodInterceptor,在CGlib的情況下也可以調用它呢?

    • 有啊,只要我們在cglib的methodInterceptor接口實現(xiàn)的intercept方法中調用org.aopalliance.intercept.MethodInterceptor不就好了。

      private static class DynamicAdvisedInterceptor implements MethodInterceptor {private AdvisedSupport advised;private org.aopalliance.intercept.MethodInterceptor delegateMethodInterceptor;private DynamicAdvisedInterceptor(AdvisedSupport advised) {this.advised = advised;this.delegateMethodInterceptor = advised.getMethodInterceptor();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {if (advised.getMethodMatcher() == null|| advised.getMethodMatcher().matches(method, advised.getTargetSource().getTargetClass())) {// return delegateMethodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(),method, args));return delegateMethodInterceptor.invoke(new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy));}// return method.invoke(advised.getTargetSource().getTarget(),args);可以這么寫,return new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy).proceed();} }

      現(xiàn)在只剩下一個疑問了,因為么要寫一個ReflectMothodInvocation的子類?因為intercept有4個入?yún)?#xff0c;所以我們交給下一步處理的時候也要有4個入?yún)?#xff0c;相當于增強了一下功能,當然你這邊不改也沒問題,就當做JDK那個版本就行。

    第11步:通過三級緩存徹底解決循環(huán)依賴

    • 廢話少說,先看結果

      @Test public void testXuhuanyilai() throws Exception {// --------- helloWorldService without AOPApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc.xml");Car car = (Car) applicationContext.getBean("car");car.getAddress().living();Address address = (Address)applicationContext.getBean("address");address.getCar().running(); } //測試結果 Invocation of Method setCar start! Invocation of Method setCar end! takes 123111 nanoseconds. Invocation of Method setAddress start! Invocation of Method setAddress end! takes 38666 nanoseconds. Invocation of Method running start! car is running Invocation of Method running end! takes 45777 nanoseconds. Invocation of Method living start! address is living Invocation of Method living end! takes 56000 nanoseconds.

      實驗結果表示,我已經解決了第9.3步中說到的AOP情況下,循環(huán)依賴導致a ref b, b ref a時,創(chuàng)建實例時,b.a指向的是空實例a,而不是代理實例a。

    • 解決方法。

      • 三層緩存。

        protected Map<String,Object> secondCache = new HashMap(); protected Map<String,Object> thirdCache = new HashMap<>(); protected Map<String,Object> firstCache = new HashMap<>();
      • thirdCache是當空構造函數(shù)創(chuàng)建一個實例時,就放入其中。

        protected Object doCreateBean(String name,BeanDefinition beanDefinition) throws Exception {Object bean = createBeanInstance(beanDefinition);thirdCache.put(name,bean);//thirdCache中放置的全是空構造方法構造出的實例beanDefinition.setBean(bean);applyPropertyValues(bean,beanDefinition);return bean; }
      • a ref b, b ref a情況下,在b創(chuàng)建時,a還只是空構造實例,因此用secondCache去保存所有field中指向空實例的那些實例,即保存b。

        for(PropertyValue propertyValue:mbd.getPropertyValues().getPropertyValues()){ Object value = propertyValue.getValue(); if(value instanceof BeanReference){//如果是ref,就創(chuàng)建這個refBeanReference beanReference = (BeanReference)value;value = getBean(beanReference.getName());String refName = beanReference.getName();if(thirdCache.containsKey(refName)&&!firstCache.containsKey(refName)){//說明當前是循環(huán)依賴狀態(tài)secondCache.put(beanReference.getName(),bean);//標注a ref b,b ref a中,b是后被循環(huán)引用的} }
      • firstCache用于保存所有最終被生成的實例.

        initializeBean(): if(thirdCache.containsKey(name)){//空構造實例如果被AOP成代理實例,則放入三級緩存,說明已經構建完畢firstCache.put(name,bean); }
      • 因此,當執(zhí)行完方法beanFactory.preInstantiateSingletons();后,thirdCache保存了所有空構造實例及名稱,secondCache保存了所有可能需要重新設置ref的實例及名稱,first保存了所有最終生成的實例和名稱。在firstcache與third中,必然存放了所有的bean,在second中只存放因循環(huán)依賴所以創(chuàng)建時ref了不完整對象的那些。在創(chuàng)建了所有實力后,通過checkoutAll方法對secondCache中的實例進行重置依賴。

        protected void onRefresh() throws Exception{beanFactory.preInstantiateSingletons();checkoutAll(); }private void checkoutAll(){Map<String,Object> secondCache = beanFactory.getSecondCache();Map<String,BeanDefinition> beanDefinitionMap = beanFactory.getBeanDefinitionMap();for(Map.Entry<String,Object> entry:secondCache.entrySet()){String invokeBeanName = entry.getKey();BeanDefinition beanDefinition = beanDefinitionMap.get(invokeBeanName);try {resetReference(invokeBeanName,beanDefinition);} catch (Exception e) {e.printStackTrace();}} } //重置依賴,這邊用到了動態(tài)類型轉換。因為原類型的setter在代理類中已經無法使用了。 private void resetReference(String invokeBeanName,BeanDefinition beanDefinition) throws Exception {Map<String,Object> thirdCache = beanFactory.getThirdCache();Map<String,Object> secondCache = beanFactory.getSecondCache();Map<String,Object> firstCache = beanFactory.getFirstCache();Map<String,BeanDefinition> beanDefinitionMap = beanFactory.getBeanDefinitionMap();for (PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValues()) {String refName = propertyValue.getName();if (firstCache.containsKey(refName)) {//如果是ref,就創(chuàng)建這個refObject exceptedValue = firstCache.get(refName);Object invokeBean = beanDefinition.getBean();Object realClassInvokeBean = thirdCache.get(invokeBeanName);Object realClassRefBean = thirdCache.get(refName);try{Method declaredMethod = realClassInvokeBean.getClass().getDeclaredMethod("set" + propertyValue.getName().substring(0, 1).toUpperCase()+ propertyValue.getName().substring(1), realClassRefBean.getClass());declaredMethod.setAccessible(true);declaredMethod.invoke((realClassInvokeBean.getClass().cast(invokeBean)), (realClassRefBean.getClass().cast(exceptedValue)));}catch (NoSuchMethodException e){Field declaredField = realClassInvokeBean.getClass().getDeclaredField(propertyValue.getName());System.out.println(declaredField);declaredField.setAccessible(true);declaredField.set((realClassInvokeBean.getClass().cast(invokeBean)), (realClassRefBean.getClass().cast(exceptedValue)));}}} }
    • 正如在9.3中說的那樣,只有在開啟全局cglib的情況下才可以完成本實驗,如果開啟jdk代理模式或者jdk代理+cglib都不會解決本bug。

    小結

    • IOC中通過讀xml用一個map,讀完才賦值給beanFactory的map的方式避免了xml因順序問題而導致的注入失敗。
    • IOC中通過getBean懶加載+先空構造器創(chuàng)建實例的方式解決了循環(huán)依賴的問題(簡單解決而已,還未能解決增加AOP功能后循環(huán)依賴的問題。)。
    • IOC本身1.因為都是注入,而不是在某一個類中new,因此系統(tǒng)耦合降低,所有的創(chuàng)建交給第三方容器,類似工廠模式2.IOC類的提供只需要xml注冊,創(chuàng)建的具體細節(jié)不需要你知道,程序更易維護和使用,因為你寫的代碼別人只要xml里注冊一下就能用你的實例。3.解決了對象層級嵌套的問題,a ref b,b ref c,c ref a,d ref b這樣復雜的嵌套關系,應該如何初始化?交給Spring!
    • AOP中通過jdk動態(tài)代理模式實現(xiàn)了被代理實例代理方法的織入。
    • AOP中通過AspectJ包完成了對AspectJ風格expression的解析,進一步完成了對類和方法ponitcut的判斷。
    • AOP中通過BeanPostProcessor接口實現(xiàn)了一個完成的bean的生命周期中after和before的工作,這個并不是通過AOP完成的,而是通過邏輯代碼的流程控制完成的:確保所有實現(xiàn)BeanPostProcessor接口的實例都率先實例化。
    • AOP中,所有ProxyCreator都實現(xiàn)BeanPostProcessor接口和BeanFactoryAware接口。前者接口保證自己率先被實例化,以保證對非AOP實例的before和after處理,后者接口保證在初始化自己的時候,會setBeanFactory,以用于后面獲取切面。
    • AOP中,所有非AOP實例都必須經過ProxyCreator的after方法,proxyCreator中已經有了beanFactory,因此可以獲得所有expression對應的類pointcut,只要實例對應的類匹配類pointcut,就返回代理類實例而不是原實例。至此,全部實例創(chuàng)建工作完畢。
    • AOP中,所有非AOP實例運行接口方法時,會按照invocationHandler.invoke(methodInterceptor.invoke(methodInvocation))邏輯進行調用,從而實現(xiàn)織入。
    • AOP中,因為JDK代理只能針對接口,因此引入Cglib技術,實現(xiàn)類的動態(tài)代理。通過在cglib包的methodInterceptor中調用org.aopalliance.intercept.MethodInterceptor,實現(xiàn)了xml中配置的methodInterceptor對接口和類都可以使用。
    • AOP中,最終通過三級緩存徹底解決了單例setter注入下的循環(huán)依賴。
    • 沒有多少人有耐心看到這里的,我知道。晚安。

    總結

    以上是生活随笔為你收集整理的框架复习(一):不如写个tiny-Spring?(完整版)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。

    黄色小说在线免费观看 | 久草免费在线观看 | 日韩免费视频播放 | 91人人澡 | 国产精品成人av久久 | 久 久久影院 | 探花国产在线 | 在线观看免费观看在线91 | 91亚洲综合 | 免费黄色网址大全 | 色综合网在线 | 亚洲女欲精品久久久久久久18 | 69精品人人人人 | 欧美性受极品xxxx喷水 | 日韩v在线| 成年人国产在线观看 | 国产精品久久久久久久久费观看 | www.国产高清| 午夜性生活片 | 国产精品 中文在线 | 久久经典国产视频 | 欧美一级黄色网 | 探花视频在线观看+在线播放 | 99精品系列 | 69视频在线播放 | 五月婷婷伊人网 | 久久国产精品电影 | 88av色| 久久久黄色 | 永久免费毛片 | 午夜精品成人一区二区三区 | 久久天堂亚洲 | 欧美a在线看 | 国产在线精品播放 | 久久久免费精品视频 | 亚洲一区精品二人人爽久久 | 日日操天天射 | 亚洲精品资源在线 | 亚洲精品网址在线观看 | 一级做a爱片性色毛片www | 伊人婷婷综合 | 91丨精品丨蝌蚪丨白丝jk | 99热这里精品 | 国产高清视频色在线www | 在线视频观看亚洲 | 国内精品中文字幕 | 国产一区二区久久精品 | 国产午夜精品视频 | www.超碰97.com| 成人av资源| 日韩三级免费 | 精品国产自在精品国产精野外直播 | avlulu久久精品| 夜夜躁日日躁 | 国产成人免费在线 | 日韩视频欧美视频 | 久久99国产精品久久99 | 在线视频91 | 国产在线精品国自产拍影院 | 亚洲电影第一页av | 欧美日韩国产精品一区二区 | 国产视频精品免费 | 国产一级三级 | www.色午夜 | 91精品一区二区三区蜜桃 | 91香蕉国产| 亚洲婷久久 | 精品视频9999 | 国产精品一区二区吃奶在线观看 | 99热这里只有精品1 av中文字幕日韩 | 国产黄在线 | 久久国产精品影片 | 日韩精品一区二区免费 | 国产99久久久国产 | 最新av网址大全 | 麻豆传媒电影在线观看 | 欧美激情视频在线观看免费 | 手机av永久免费 | 国产视频亚洲精品 | 亚洲最大av | 婷婷激情欧美 | 欧美一区免费在线观看 | 免费看毛片网站 | 欧美一区二区在线 | 97精品国产97久久久久久春色 | 欧美乱大交 | 国产一级特黄电影 | 视频在线观看国产 | 亚洲视频在线免费看 | 国产精品九九久久久久久久 | 久久亚洲欧美日韩精品专区 | 免费的黄色的网站 | 成年美女黄网站色大片免费看 | 亚洲精品av在线 | 久久亚洲综合色 | 成人在线观看影院 | www色av| 欧美一区影院 | 97综合网| 国产精品久久久久免费观看 | 国产精品免费观看久久 | www.久草.com | 成+人+色综合 | av在线看片 | a黄色一级| 国产a高清| 亚洲特级片 | 日本黄色免费观看 | 国产精品自拍在线 | 欧美成人精品欧美一级乱黄 | 欧美xxxxx在线视频 | 麻花豆传媒mv在线观看 | 超碰在线公开 | 国产美女在线精品免费观看 | 国产精品久久久久久久久久久久冷 | 五月婷婷激情综合网 | av福利网址导航 | 成人教育av | 亚洲h色精品 | 青青久草在线 | 欧美性极品xxxx做受 | 亚洲成人网av | 婷婷色网址 | 人人讲下载 | 国产99久久九九精品免费 | 在线亚州 | 亚洲精品高清视频 | 超碰人人99 | 久草精品在线播放 | 天天玩天天干 | 久久久久久中文字幕 | 欧美a级成人淫片免费看 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 天天操狠狠操网站 | bbb搡bbb爽爽爽 | 人人舔人人爱 | 国产九色视频在线观看 | 天天综合网~永久入口 | 国产日韩欧美网站 | 四虎影视成人精品 | 国产精品一区二区久久 | 亚洲少妇久久 | 久久网站最新地址 | 日韩国产精品久久久久久亚洲 | 日日干干 | av免费在线看网站 | 日韩视频1区 | 国产在线超碰 | 这里有精品在线视频 | 日韩中文字幕在线观看 | 高潮久久久久久久久 | 丝袜精品视频 | 啪一啪在线 | 国产精品夜夜夜一区二区三区尤 | 久久精品爱爱视频 | 97超碰在线资源 | 欧美日韩精品在线视频 | 精品国产一区二 | 日韩理论片 | 国产精品电影在线 | 国产色婷婷精品综合在线手机播放 | 日日躁夜夜躁aaaaxxxx | 精品久久1| 欧美久久久影院 | 夜夜躁日日躁狠狠久久av | 色婷婷亚洲婷婷 | 欧美性猛片 | 天天天天天天天操 | 在线观看日本高清mv视频 | 麻豆国产电影 | 揉bbb玩bbb少妇bbb| 国产一区二区在线播放 | 国产在线一区观看 | 美女视频网站久久 | adc在线观看 | 国产精品毛片久久蜜 | 天天综合入口 | 国产a级免费 | 亚洲另类视频 | 九九激情视频 | 国产美女被啪进深处喷白浆视频 | av资源免费在线观看 | 五月天综合在线 | 国产精品午夜在线观看 | 国产精品一区二区精品视频免费看 | 国产精品免费一区二区三区在线观看 | 日本成人免费在线观看 | 中国成人一区 | 999久久a精品合区久久久 | 国产黄a三级 | 欧美精品在线视频观看 | 天天干天天操天天 | 久久久精品国产一区二区三区 | 久久久伦理 | 精品视频国产 | 亚洲午夜精品一区二区三区电影院 | 国产午夜精品一区二区三区嫩草 | 91成熟丰满女人少妇 | 91漂亮少妇露脸在线播放 | 亚洲www天堂com | 992tv成人免费看片 | 日日夜夜综合网 | www.香蕉视频在线观看 | 91黄在线看| 久久一级片 | 99精品偷拍视频一区二区三区 | 五月天色婷婷丁香 | 麻豆超碰 | 国产精品一区二区av影院萌芽 | 操少妇视频 | 天天天操操操 | 免费精品视频在线 | 日韩欧美高清视频在线观看 | 欧美色久 | 国产视频精品视频 | 婷婷中文字幕在线观看 | 日韩精品一区二区在线视频 | 中文字幕乱码电影 | 色香com.| 欧美成人一区二区 | 五月开心六月婷婷 | 91丨九色丨91啦蝌蚪老版 | 91在线免费观看国产 | 手机看片午夜 | 亚洲精品成人av在线 | 91精品久久久久久久久 | 久久精品www人人爽人人 | av色图天堂网 | 亚洲综合激情小说 | 特级西西人体444是什么意思 | 韩国一区二区三区在线观看 | 国产精品永久 | av免费在线播放 | 久草在线视频资源 | 特黄特色特刺激视频免费播放 | 在线视频观看成人 | 欧美动漫一区二区三区 | 色婷婷av在线 | av电影在线播放 | 国产精品福利在线观看 | 丁香六月婷婷开心婷婷网 | 在线视频日韩一区 | 日韩免费三级 | 精品久久片| 日韩欧美在线视频一区二区三区 | 福利av影院| 国产999在线观看 | 欧美精品免费在线观看 | 中文字幕a∨在线乱码免费看 | 在线观看精品一区 | 超碰国产人人 | 日韩理论在线播放 | 久久免费视频网 | 超碰97在线资源 | 日韩欧美高清视频在线观看 | 国产999精品 | 中文字幕第一页在线vr | 久久国产热视频 | 日韩系列 | 久视频在线 | 国产一区久久久 | 国产精品久久久久久久久久东京 | 99色网站| 亚洲天天干 | 国产一级淫片免费看 | 99热 精品在线 | 精品国产激情 | 日韩理论在线 | 最近最新中文字幕 | 国产精品久久一区二区三区, | 高清一区二区三区av | 人人要人人澡人人爽人人dvd | 久久国色夜色精品国产 | 在线免费观看视频一区二区三区 | 日韩天天操 | 精品久久99 | 97av精品 | avove黑丝| 亚洲综合爱 | 欧美一级日韩三级 | 九九九九九精品 | 天天搞天天干天天色 | 黄色在线网站噜噜噜 | 免费在线中文字幕 | 黄色网址a | 中文字幕精品在线 | 97视频在线免费播放 | 国产馆在线播放 | 91精品夜夜 | 极品久久久久 | 久久免费视频在线观看6 | 日韩在线看片 | 中文字幕一区二区在线观看 | 久久国产精品久久国产精品 | 国产日韩在线观看一区 | 色午夜| 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 夜夜看av| 一级α片免费看 | 国产日韩欧美在线影视 | 国产 中文 日韩 欧美 | 国产婷婷视频在线 | 久久视| 国产精品 日本 | 五月婷在线视频 | 日韩一级成人av | 91久久奴性调教 | 中文字幕国内精品 | 91精品老司机久久一区啪 | 精品视频免费在线 | 精品96久久久久久中文字幕无 | 波多野结衣视频一区 | 最新av在线播放 | 久久激情视频 | 91丨九色丨国产丨porny精品 | 丁香综合五月 | 久久久久久久久艹 | 久久久福利视频 | 色综合色综合色综合 | 人人草在线观看 | 五月婷婷激情六月 | 99热精品视 | 日日操网站 | 欧美一级特黄aaaaaa大片在线观看 | 808电影免费观看三年 | 99热这里只有精品国产首页 | 欧美日韩视频免费看 | 欧美日韩国内在线 | 国产麻豆精品一区 | 久久免费精品视频 | 亚洲日本一区二区在线 | 中文字幕乱码电影 | www.久久免费视频 | 韩国av免费观看 | 日韩综合一区二区三区 | 狠狠干天天操 | 久久国产亚洲视频 | 中文字幕在线免费看 | 精品久久91| 国产精品四虎 | 黄色一级大片在线观看 | 国产一区不卡在线 | 色网站在线观看 | 日本中文在线播放 | 五月天伊人网 | 欧美一级视频在线观看 | 国产1区在线观看 | 久久99热国产 | 黄色一级大片在线免费看国产一 | 在线黄网站 | 国产精品免费在线播放 | 国产精品免费久久久久影院仙踪林 | 精品视频在线免费 | 黄色一级免费 | 九九视频免费观看视频精品 | 97精品国产 | 手机在线永久免费观看av片 | 狠色在线| 97天天干| 久久精品这里热有精品 | 亚洲黄色av| 久久国产露脸精品国产 | 欧美男男tv网站 | 97视频免费观看2区 亚洲视屏 | 香蕉影视在线观看 | 国产精品久久久777 成人手机在线视频 | 天干啦夜天干天干在线线 | 久久久96 | 91成人免费看 | 超碰97国产在线 | 色欲综合视频天天天 | 精品一区91 | 久久久久久久影院 | www.夜夜| 99久久精品无码一区二区毛片 | www.久久视频| 日本精品在线视频 | 六月色丁香 | 国产精品99精品 | 一区免费在线 | av免费网站 | 日韩在线观看视频免费 | 亚洲激情电影在线 | 色网站在线免费观看 | av在线看网站 | 日韩免费一区二区三区 | 天天摸日日摸人人看 | 亚洲日本va在线观看 | 国产高清在线免费 | 国产一级二级在线观看 | 9免费视频 | 欧美日韩高清一区二区 国产亚洲免费看 | 综合色久 | 亚洲一区二区精品视频 | 国产一级片免费观看 | 狠狠色丁香 | 999成人精品| 五月天久久狠狠 | 亚洲激情综合 | 射射射综合网 | 五月天综合婷婷 | 91视频啊啊啊 | 日韩艹 | 日日操操 | av片一区二区 | 99视频精品免费视频 | 欧美一区在线看 | 超碰在线最新网址 | 亚洲影院一区 | 一区二区三区三区在线 | 五月天婷婷在线播放 | 精品少妇一区二区三区在线 | 玖玖视频免费在线 | 激情视频一区二区 | 8x8x在线观看视频 | 男女激情网址 | 999精品在线 | 免费视频你懂得 | 国产色小视频 | 日韩激情中文字幕 | 久久这里只有精品久久 | 亚洲一区二区精品3399 | 免费看国产黄色 | 午夜影院在线观看18 | 国外成人在线视频网站 | 色偷偷88888欧美精品久久 | 亚洲一二三久久 | 狠色在线| 久久人人艹 | 久久婷婷影视 | av在线等 | 国产精品久久久久国产精品日日 | 97免费 | 久久久久亚洲精品成人网小说 | 国产精品123| 国产精品久久久久久久久久白浆 | av电影亚洲| 欧美午夜久久 | 九九免费精品视频在线观看 | 亚洲视频在线观看免费 | 手机av观看 | 欧美激情在线看 | 中国一级特黄毛片大片久久 | 天天操,夜夜操 | 欧美亚洲xxx | 91精品麻豆 | 亚洲精品白浆高清久久久久久 | 日韩av成人免费看 | 手机在线日韩视频 | 免费黄a| 国产成人av福利 | 福利视频一二区 | .国产精品成人自产拍在线观看6 | 国产精品女 | 日韩大片免费在线观看 | 欧美日韩不卡在线视频 | 热久久国产 | av成人黄色 | 日韩欧美高清在线 | www色| 热久久这里只有精品 | 91夜夜夜 | 久久激情视频 久久 | 天天综合操 | 欧美 亚洲 另类 激情 另类 | 在线不卡视频 | 亚洲热久久 | 天天鲁天天干天天射 | 少妇搡bbbb搡bbb搡忠贞 | 国产剧情av在线播放 | 欧美激情va永久在线播放 | 欧美不卡视频在线 | 特级黄录像视频 | 成人免费观看视频网站 | 久久天堂影院 | 韩国精品一区二区三区六区色诱 | 亚洲精品女人久久久 | 日本高清中文字幕有码在线 | 国产在线观看你懂得 | 草在线视频 | 在线观看中文字幕网站 | 国产精品中文字幕在线观看 | 婷婷中文在线 | 日韩精品资源 | 色欧美成人精品a∨在线观看 | 天天人人综合 | 天天摸天天舔 | 日本黄色a级大片 | 涩涩成人在线 | 亚洲精品国精品久久99热 | 日韩精品久久久免费观看夜色 | 2024国产精品视频 | 精品国产黄色片 | 久久精彩免费视频 | 91精品国产欧美一区二区 | 中文字幕免 | 日韩久久久久久久久久 | 中文字幕乱码电影 | 国产一区二区在线观看视频 | 丁香婷婷基地 | 激情综合五月天 | 免费高清在线视频一区· | 黄色的视频网站 | 日韩最新理论电影 | 久久这里只精品 | 色欲综合视频天天天 | 麻豆一精品传二传媒短视频 | av在线影视 | 国产美女精品视频 | 欧美一级免费黄色片 | 最新极品jizzhd欧美 | 日日干网址 | 精品久久久久久综合日本 | 菠萝菠萝在线精品视频 | 国产免费黄色 | 久久夜夜操 | 日韩在线网址 | 又黄又爽又无遮挡免费的网站 | 国内精品久久久久久 | 97成人精品视频在线观看 | 一区二区精品在线 | 国产毛片aaa | 欧美另类巨大 | av一本久道久久波多野结衣 | 亚洲精品欧美成人 | 在线看片日韩 | 99视频在线免费 | 国产专区第一页 | 国产一级不卡毛片 | 久久任你操 | 亚洲一区av | 中文字幕久久精品一区 | 涩涩成人在线 | 在线观看视频免费大全 | 国产一区久久 | 欧美激情综合五月色丁香 | 日本中文字幕在线 | 99视频久 | 亚洲一区日韩精品 | av免费在线播放 | 日韩在线国产 | 精品在线一区二区三区 | 成人一区二区三区在线观看 | 久久成年人网站 | 免费网站污 | 精品国产欧美 | 日本在线观看中文字幕 | 天堂在线成人 | 99色在线播放 | 欧美一进一出抽搐大尺度视频 | 国产精品久久一区二区三区不卡 | 少妇精品久久久一区二区免费 | 色婷婷综合在线 | 色婷婷亚洲精品 | 亚洲一区美女视频在线观看免费 | 色欧美视频 | 日本aaa在线观看 | 欧美日韩精品二区第二页 | 91人人视频在线观看 | 成人免费91| 在线免费视频一区 | 亚洲国产精品成人女人久久 | 蜜臀久久99精品久久久久久网站 | 国产精品久久亚洲 | 天堂麻豆| 激情 一区二区 | 日韩免费小视频 | www.狠狠干| 日韩在线第一 | 欧美一区二区三区免费看 | 亚洲日本va中文字幕 | 在线观看久久久久久 | 国产一区在线观看免费 | 亚洲精品美女免费 | 国产v欧美 | 欧美久久综合 | 国产精品黑丝在线观看 | 亚洲第一色| 精品av在线播放 | 91在线免费观看网站 | 91大神电影 | 久草视频中文在线 | 国产日韩欧美在线一区 | 西西444www大胆高清图片 | 日韩欧美视频二区 | 久久躁日日躁aaaaxxxx | 国产麻豆精品传媒av国产下载 | 国产超碰在线观看 | 日日夜夜免费精品视频 | 久久精品视频一 | 在线观看视频97 | 天天综合网久久 | 亚洲国产中文字幕在线视频综合 | 国产色女人 | 精品欧美在线视频 | 欧美人体xx | 国产二区视频在线 | 中文字幕在线观看免费 | 亚洲国产成人久久 | 久久免费视频2 | 俺要去色综合狠狠 | 日韩69av | 日日夜夜狠狠操 | 久久精品日本啪啪涩涩 | 美女久久久 | 五月开心激情 | 最新亚洲视频 | 97超视频免费观看 | 久草在线最新 | 国内精品久久久久久中文字幕 | 久久久久久亚洲精品 | 国产欧美综合在线观看 | 免费日韩一区二区三区 | 1区2区3区在线观看 三级动图 | 在线播放 日韩专区 | 天天射天天射 | 96超碰在线 | 免费的国产精品 | 天天干天天操天天爱 | 丝袜美腿在线视频 | 91在线网址| 欧美精品久久久久久久亚洲调教 | 91九色蝌蚪国产 | 狠狠干婷婷色 | 国产精品18久久久久久首页狼 | 欧美专区亚洲专区 | 国产麻豆精品一区 | 国产精品久久网 | 天天操天天操天天操天天操天天操天天操 | 深爱五月激情网 | 999久久| 天天射天天色天天干 | 日韩电影一区二区在线 | 黄色av三级在线 | 91香蕉视频在线 | 欧美成人xxx | 毛片在线播放网址 | 最新日韩在线 | 香蕉在线观看 | 久久一区二区三区国产精品 | 色婷婷国产 | 在线看v片 | 国产视频一区二区在线观看 | 国产精品久久久视频 | 天天干,天天射,天天操,天天摸 | 日韩国产精品毛片 | 欧美日韩性生活 | 国产黄a三级 | 国产999精品久久久久久 | 国产精品亚洲成人 | 亚洲 欧洲av | 国产免费xvideos视频入口 | 欧美大片在线观看一区 | 日韩一级黄色片 | 欧美在线aa | 久久五月天婷婷 | 操操操天天操 | 91网免费观看 | 欧美性做爰猛烈叫床潮 | 天天玩天天操天天射 | 国产精品观看在线亚洲人成网 | 欧美成人在线免费 | 国内精品久久久久久中文字幕 | 精品国产午夜 | 我爱av激情网 | 草久热| 精品国产一区二区三区久久久蜜臀 | 久久a国产| 免费精品在线观看 | 友田真希x88av| 综合在线亚洲 | 婷婷精品 | 亚洲国产99 | 欧美国产91 | 粉嫩一区二区三区粉嫩91 | 中国一级片免费看 | 中中文字幕av在线 | av免费网 | 天天色天天射天天综合网 | 91高清免费在线观看 | 区一区二区三在线观看 | 五月婷婷中文 | 激情丁香5月 | 国产精品美女免费视频 | 亚洲综合色视频在线观看 | 99成人精品 | 91av大全| 亚洲午夜久久久久久久久久久 | av成人资源 | 日韩丝袜视频 | 国产老太婆免费交性大片 | 成人精品99 | 国产精品毛片久久久久久久久久99999999 | 男女视频久久久 | 亚洲国产日本 | 日韩理论电影在线观看 | 久草免费福利在线观看 | 日韩一级电影网站 | 天天射天天射天天射 | 欧美午夜精品久久久久 | 99久久精品无码一区二区毛片 | 黄色免费网站 | 国产精品三级视频 | 国产一区二区高清视频 | 少妇搡bbbb搡bbb搡忠贞 | 日韩91av | 国产男女爽爽爽免费视频 | 日韩免费在线观看视频 | 欧美国产视频在线 | 69亚洲视频| 国产精品一区二区免费视频 | 日韩高清www | 成年人黄色免费看 | 操操操天天操 | 成人免费网视频 | 国产香蕉97碰碰久久人人 | 黄色一级大片在线免费看国产一 | 99久久精品免费看国产四区 | 在线视频91| 超碰97免费 | 99久久夜色精品国产亚洲96 | 久久一久久 | 日韩网站在线 | 亚洲影院国产 | 500部大龄熟乱视频 欧美日本三级 | 激情视频一区二区三区 | 国产精品ssss在线亚洲 | 特黄特黄的视频 | 91亚洲精品在线观看 | 夜夜狠狠| 波多野结衣久久精品 | 99久久99久久免费精品蜜臀 | 日韩午夜在线播放 | 中文字幕在线免费看线人 | 国产99久久久精品 | 婷婷精品国产欧美精品亚洲人人爽 | 国产字幕在线看 | 色婷婷天天干 | 欧美成人黄 | 香蕉色综合 | 亚洲欧美怡红院 | 久久视频这里有久久精品视频11 | 国产精品女同一区二区三区久久夜 | 精品久久精品久久 | 精品久久久久久亚洲综合网站 | 成人天堂网 | 久草视频免费在线观看 | 婷婷 综合 色 | 91成人免费 | 91精品一区国产高清在线gif | 国产精品国产亚洲精品看不卡15 | 国产99免费 | 97在线精品视频 | 香蕉影视在线观看 | 国产九色在线播放九色 | 免费看黄的 | 中文字幕av播放 | 永久av免费在线观看 | www.午夜| 免费三级黄色 | 国产精品 中文字幕 亚洲 欧美 | 亚洲国产网站 | 久久精品一级片 | 欧美成人91 | av线上看 | 综合网欧美 | 免费人成在线观看 | 成人香蕉视频 | 天天草天天干天天射 | 91在线影院 | 怡红院久久 | 91视视频在线直接观看在线看网页在线看 | 久久人人爽人人爽人人片av免费 | 五月激情婷婷丁香 | 日韩黄色av网站 | 在线视频 一区二区 | 久久99精品国产91久久来源 | 啪啪肉肉污av国网站 | 黄色午夜网站 | 午夜国产福利在线 | 国产亚洲精品久久久久久无几年桃 | 亚洲精品国产第一综合99久久 | 欧美日韩一区二区在线观看 | 日韩高清免费观看 | 韩国一区二区三区在线观看 | 欧美在线a视频 | 一区二区精品在线 | 天天色天天爱天天射综合 | 18网站在线观看 | 少妇性aaaaaaaaa视频 | 久久久影院官网 | 久久在线观看视频 | 91最新视频在线观看 | 午夜99| 国产98色在线 | 日韩 | 黄色网在线免费观看 | 在线播放精品一区二区三区 | 成年人视频在线免费播放 | 久久电影国产免费久久电影 | 美女视频一区二区 | 一级欧美一级日韩 | 国产第页 | 激情五月婷婷综合网 | 蜜臀aⅴ国产精品久久久国产 | 激情五月激情综合网 | 国产资源中文字幕 | 91看片淫黄大片在线播放 | 天堂素人在线 | 国内成人精品2018免费看 | 中文字幕在线日 | 97人人模人人爽人人少妇 | 激情欧美一区二区免费视频 | 免费看片网站91 | 国产精品视频免费看 | 99精品国产一区二区 | 国产精品无 | 在线电影av | 国产区精品视频 | 成人国产网站 | 国产精品免费一区二区 | 日韩av手机在线观看 | 成人国产精品 | 久久久99精品免费观看乱色 | 日本少妇视频 | 国产高清视频免费观看 | 97精品伊人 | 欧美日韩亚洲国产一区 | 亚洲精品一区二区网址 | 久久久免费少妇 | 日日夜夜免费精品 | 国产中文字幕一区 | 黄av免费在线观看 | 黄色大片入口 | 成人免费在线网 | 97视频在线观看播放 | 日韩电影在线一区 | 男女视频久久久 | 成年人黄色免费看 | 免费在线国产 | 欧美国产一区二区 | 又黄又爽又无遮挡免费的网站 | 天天干天天插伊人网 | 久久激情五月丁香伊人 | 91精品国自产在线 | 国产亚洲久久 | 久久人人爽人人爽人人片av软件 | 欧美精品三级在线观看 | 免费国产黄线在线观看视频 | 在线不卡中文字幕播放 | 国产精品色婷婷视频 | 色综合天天色 | 亚洲视频播放 | 日日草天天草 | 欧美一进一出抽搐大尺度视频 | 国产在线视频一区 | 精品在线亚洲视频 | 久久夜色精品国产欧美乱极品 | 色资源二区在线视频 | 亚洲第一中文字幕 | 在线91播放| 久久综合久久综合九色 | 国产精品久久久久久久久久久免费 | 国产精品一区二区三区免费视频 | 国产成人精品久久亚洲高清不卡 | 成人禁用看黄a在线 | 日本激情视频中文字幕 | 色婷婷丁香| 国产做aⅴ在线视频播放 | 国产大片免费久久 | 国产视频精品网 | 亚洲成熟女人毛片在线 | 日韩av免费观看网站 | 深夜激情影院 | 国内精品久久久久影院日本资源 | 久久av中文字幕片 | 日日干美女 | 激情五月av | 久草视频首页 | 日韩一区二区在线免费观看 | 国产精品一区二区免费看 | 色婷婷精品 | 一级精品视频在线观看宜春院 | 日日草夜夜操 | 特级aaa毛片 | 国产精品一区二区精品视频免费看 | 色婷婷激情电影 | 美女一区网站 | 国产在线免费观看 | 亚洲精品国产精品国 | 亚洲精品五月 | 精品亚洲视频在线观看 | 国产一区二区在线观看视频 | 亚洲精品高清视频 | 国产精品美女久久久久久久久 | 国产在线第三页 | 成人黄色在线 | 亚洲影视资源 | 中文字幕免费一区 | 一区二区视频在线看 | 免费在线观看av网站 | 亚洲国产中文在线观看 | 丝袜美腿亚洲综合 | 五月婷婷视频在线 | 激情五月av | 97超碰人人看 | 91在线日韩 | 在线国产观看 | 国内精品久久久久久久久久久久 | 国产精品视频在线看 | 久久久久久久看片 | 激情自拍av | 国产亚洲高清视频 | 日韩av中文字幕在线免费观看 | 日本最大色倩网站www | 这里只有精彩视频 | 精品国偷自产国产一区 | 欧美精品一区在线发布 | 久草视频手机在线 | 久久精品99国产精品 | 亚洲 综合 国产 精品 | 亚洲综合爱 | 伊人天天综合 | 日韩国产欧美在线视频 | 国产综合久久 | 操操操人人 | 久久免费精彩视频 | 中文字幕av一区二区三区四区 | 久久免费毛片视频 | av一区二区在线观看中文字幕 | 亚洲一区二区天堂 | 中文字幕久久精品亚洲乱码 | 中文区中文字幕免费看 | 高潮久久久久久久久 | 午夜av免费观看 | 日本视频精品 | 在线欧美最极品的av | 中文字幕国产一区 | 亚洲国产免费看 | 久久精品美女视频 | 免费看黄20分钟 | 999国内精品永久免费视频 | 麻豆视频国产精品 | 一区二区精品在线 | 91资源在线| 日韩精品欧美专区 | 手机av在线免费观看 | 丁香花在线视频观看免费 | 涩涩色亚洲一区 | 亚洲成av人片在线观看 | 天天躁日日躁狠狠躁av麻豆 | 久久丁香网 | 99热在线观看免费 | 久一久久| 国语自产偷拍精品视频偷 | 亚洲免费高清视频 | 久久精品aaa | 中文字幕免费高清av | 成人免费在线视频观看 | 国产高清精品在线观看 | 亚洲精品资源 | 国产精品手机在线播放 | 夜色资源站国产www在线视频 | 一区二区 不卡 | 亚洲国产成人久久综合 | 美国av大片| 久久99久久99精品免观看粉嫩 | 久久 亚洲视频 | 成人国产精品一区二区 | 久久另类小说 | 日韩午夜网站 | 国产福利一区在线观看 | 伊人久久精品久久亚洲一区 | 五月婷婷激情 | av在线a | 国产亚洲精品久久久久久 | 国产精品成人久久 | 中文国产字幕 | 91精品久久香蕉国产线看观看 | 黄色网在线免费观看 | 国产福利午夜 | 国产精品久久久久久久久久尿 | 中文字幕丰满人伦在线 | 亚洲精品美女久久 | 免费看的黄色小视频 | 6080yy精品一区二区三区 | 在线播放91 | 久草在线久 | 一级黄色网址 | 欧美色插| 欧美在线aa| 色综合久久久 | 青草视频在线 | 在线三级播放 | av大片网址 | 中文av网站| 人人澡人人爱 | 久久成人欧美 | 国产成人免费精品 |