日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring【AOP模块】就是这么简单

發布時間:2025/3/20 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring【AOP模块】就是这么简单 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

前言

到目前為止,已經簡單學習了Spring的Core模塊、....于是我們就開啟了Spring的AOP模塊了...在講解AOP模塊之前,首先我們來講解一下cglib代理、以及怎么手動實現AOP編程

cglib代理

在講解cglib之前,首先我們來回顧一下靜態代理和動態代理....我之前就寫過了靜態代理、動態代理的博文:blog.csdn.net/hon_3y/arti…

由于靜態代理需要實現目標對象的相同接口,那么可能會導致代理類會非常非常多....不好維護---->因此出現了動態代理

動態代理也有個約束:目標對象一定是要有接口的,沒有接口就不能實現動態代理.....----->因此出現了cglib代理

cglib代理也叫子類代理,從內存中構建出一個子類來擴展目標對象的功能!

  • CGLIB是一個強大的高性能的代碼生成包,它可以在運行期擴展Java類與實現Java接口。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop,為他們提供方法的interception(攔截)。

編寫cglib代理

接下來我們就講講怎么寫cglib代理:

  • 需要引入cglib – jar文件, 但是spring的核心包中已經包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
  • 引入功能包后,就可以在內存中動態構建子類
  • 代理的類不能為final,否則報錯【在內存中構建子類來做擴展,當然不能為final,有final就不能繼承了】
  • 目標對象的方法如果為final/static, 那么就不會被攔截,即不會執行目標對象額外的業務方法。
//需要實現MethodInterceptor接口 public class ProxyFactory implements MethodInterceptor{// 維護目標對象private Object target;public ProxyFactory(Object target){this.target = target;}// 給目標對象創建代理對象public Object getProxyInstance(){//1. 工具類Enhancer en = new Enhancer();//2. 設置父類en.setSuperclass(target.getClass());//3. 設置回調函數en.setCallback(this);//4. 創建子類(代理對象)return en.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {System.out.println("開始事務.....");// 執行目標對象的方法Object returnValue = method.invoke(target, args);System.out.println("提交事務.....");return returnValue;}}
  • 測試:
public class App {public static void main(String[] args) {UserDao userDao = new UserDao();UserDao factory = (UserDao) new ProxyFactory(userDao).getProxyInstance();factory.save();} }

?

?

?

?

使用cglib就是為了彌補動態代理的不足【動態代理的目標對象一定要實現接口】

手動實現AOP編程

AOP 面向切面的編程:

  • AOP可以實現“業務代碼”與“關注點代碼”分離

下面我們來看一段代碼:

// 保存一個用戶 public void add(User user) { Session session = null; Transaction trans = null; try { session = HibernateSessionFactoryUtils.getSession(); // 【關注點代碼】trans = session.beginTransaction(); // 【關注點代碼】session.save(user); // 核心業務代碼trans.commit(); //…【關注點代碼】} catch (Exception e) { e.printStackTrace(); if(trans != null){ trans.rollback(); //..【關注點代碼】} } finally{ HibernateSessionFactoryUtils.closeSession(session); ..【關注點代碼】} }
  • 關注點代碼,就是指重復執行的代碼。
  • 業務代碼與關注點代碼分離,好處?
    • 關注點代碼寫一次即可
    • 開發者只需要關注核心業務
    • 運行時期,執行核心業務代碼時候動態植入關注點代碼; 【代理】

案例分析:

  • IUser接口
public interface IUser {void save(); }

我們一步一步來分析,首先我們的UserDao有一個save()方法,每次都要開啟事務和關閉事務

//@Component -->任何地方都能用這個 @Repository //-->這個在Dao層中使用public class UserDao {public void save() {System.out.println("開始事務");System.out.println("DB:保存用戶");System.out.println("關閉事務");}}
  • 在剛學習java基礎的時候,我們知道:如果某些功能經常需要用到就封裝成方法:
//@Component -->任何地方都能用這個 @Repository //-->這個在Dao層中使用public class UserDao {public void save() {begin();System.out.println("DB:保存用戶");close();}public void begin() {System.out.println("開始事務");}public void close() {System.out.println("關閉事務");} }
  • 現在呢,我們可能有多個Dao,都需要有開啟事務和關閉事務的功能,現在只有UserDao中有這兩個方法,重用性還是不夠高。因此我們抽取出一個類出來
public class AOP {public void begin() {System.out.println("開始事務");}public void close() {System.out.println("關閉事務");} }
  • 在UserDao維護這個變量,要用的時候,調用方法就行了
@Repository //-->這個在Dao層中使用 public class UserDao {AOP aop;public void save() {aop.begin();System.out.println("DB:保存用戶");aop.close();}}
  • 現在的開啟事務、關閉事務還是需要我在userDao中手動調用。還是不夠優雅。。我想要的效果:當我在調用userDao的save()方法時,動態地開啟事務、關閉事務。因此,我們就用到了代理。當然了,真正執行方法的都是userDao、要干事的是AOP,因此在代理中需要維護他們的引用
public class ProxyFactory {//維護目標對象private static Object target;//維護關鍵點代碼的類private static AOP aop;public static Object getProxyInstance(Object target_, AOP aop_) {//目標對象和關鍵點代碼的類都是通過外界傳遞進來target = target_;aop = aop_;return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {aop.begin();Object returnValue = method.invoke(target, args);aop.close();return returnValue;}});} }

工廠靜態方法:

  • 把AOP加入IOC容器中
//把該對象加入到容器中 @Component public class AOP {public void begin() {System.out.println("開始事務");}public void close() {System.out.println("關閉事務");} }
  • 把UserDao放入容器中
@Component public class UserDao {public void save() {System.out.println("DB:保存用戶");}}
  • 在配置文件中開啟注解掃描,使用工廠靜態方法創建代理對象
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><bean id="proxy" class="aa.ProxyFactory" factory-method="getProxyInstance"><constructor-arg index="0" ref="userDao"/><constructor-arg index="1" ref="AOP"/></bean><context:component-scan base-package="aa"/></beans>
  • ?
  • 測試,得到UserDao對象,調用方法

public class App {public static void main(String[] args) {ApplicationContext ac =new ClassPathXmlApplicationContext("aa/applicationContext.xml");IUser iUser = (IUser) ac.getBean("proxy");iUser.save();} }

?

?

工廠非靜態方法

上面使用的是工廠靜態方法來創建代理類對象。我們也使用一下非靜態的工廠方法創建對象

package aa;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;/*** Created by ozc on 2017/5/11.*/public class ProxyFactory {public Object getProxyInstance(final Object target_, final AOP aop_) {//目標對象和關鍵點代碼的類都是通過外界傳遞進來return Proxy.newProxyInstance(target_.getClass().getClassLoader(),target_.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {aop_.begin();Object returnValue = method.invoke(target_, args);aop_.close();return returnValue;}});} }

配置文件:先創建工廠,再創建代理類對象

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--創建工廠--><bean id="factory" class="aa.ProxyFactory"/><!--通過工廠創建代理--><bean id="IUser" class="aa.IUser" factory-bean="factory" factory-method="getProxyInstance"><constructor-arg index="0" ref="userDao"/><constructor-arg index="1" ref="AOP"/></bean><context:component-scan base-package="aa"/></beans>

?

?

AOP的概述

Aop: aspect object programming 面向切面編程

  • 功能: 讓關注點代碼與業務代碼分離!
  • 面向切面編程就是指: 對很多功能都有的重復的代碼抽取,再在運行的時候往業務方法上動態植入“切面類代碼”。

關注點:

  • 重復代碼就叫做關注點。
// 保存一個用戶 public void add(User user) { Session session = null; Transaction trans = null; try { session = HibernateSessionFactoryUtils.getSession(); // 【關注點代碼】trans = session.beginTransaction(); // 【關注點代碼】session.save(user); // 核心業務代碼trans.commit(); //…【關注點代碼】} catch (Exception e) { e.printStackTrace(); if(trans != null){ trans.rollback(); //..【關注點代碼】} } finally{ HibernateSessionFactoryUtils.closeSession(session); ..【關注點代碼】} }

切面:

  • 關注點形成的類,就叫切面(類)!
public class AOP {public void begin() {System.out.println("開始事務");}public void close() {System.out.println("關閉事務");} }

切入點:

  • 執行目標對象方法,動態植入切面代碼。
  • 可以通過切入點表達式指定攔截哪些類的哪些方法; 給指定的類在運行的時候植入切面類代碼

切入點表達式:

  • 指定哪些類的哪些方法被攔截

使用Spring AOP開發步驟

1) 先引入aop相關jar文件 (aspectj aop優秀組件)

  • spring-aop-3.2.5.RELEASE.jar 【spring3.2源碼】
  • aopalliance.jar 【spring2.5源碼/lib/aopalliance】
  • aspectjweaver.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】
  • aspectjrt.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】

注意: 用到spring2.5版本的jar文件,如果用jdk1.7可能會有問題

  • 需要升級aspectj組件,即使用aspectj-1.8.2版本中提供jar文件提供。

2) bean.xml中引入aop名稱空間

  • xmlns:context="http://www.springframework.org/schema/context"
  • http://www.springframework.org/schema/context
  • http://www.springframework.org/schema/context/spring-context.xsd

引入jar包

引入4個jar包:

?

?

引入名稱空間

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"></beans>

注解方式實現AOP編程

我們之前手動的實現AOP編程是需要自己來編寫代理工廠的**,現在有了Spring,就不需要我們自己寫代理工廠了。Spring內部會幫我們創建代理工廠**。

  • 也就是說,不用我們自己寫代理對象了。

因此,我們只要關心切面類、切入點、編寫切入表達式指定攔截什么方法就可以了!

還是以上一個例子為案例,使用Spring的注解方式來實現AOP編程

在配置文件中開啟AOP注解方式

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="aa"/><!-- 開啟aop注解方式 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>

代碼:

  • 切面類
@Component @Aspect//指定為切面類 public class AOP {//里面的值為切入點表達式@Before("execution(* aa.*.*(..))")public void begin() {System.out.println("開始事務");}@After("execution(* aa.*.*(..))")public void close() {System.out.println("關閉事務");} }
  • UserDao實現了IUser接口
@Component public class UserDao implements IUser {@Overridepublic void save() {System.out.println("DB:保存用戶");}}
  • IUser接口
public interface IUser {void save(); }
  • 測試代碼:
public class App {public static void main(String[] args) {ApplicationContext ac =new ClassPathXmlApplicationContext("aa/applicationContext.xml");//這里得到的是代理對象....IUser iUser = (IUser) ac.getBean("userDao");System.out.println(iUser.getClass());iUser.save();} }

?

?

目標對象沒有接口

上面我們測試的是UserDao有IUser接口,內部使用的是動態代理...那么我們這次測試的是目標對象沒有接口

  • OrderDao沒有實現接口
@Component public class OrderDao {public void save() {System.out.println("我已經進貨了!!!");} }
  • 測試代碼:
public class App {public static void main(String[] args) {ApplicationContext ac =new ClassPathXmlApplicationContext("aa/applicationContext.xml");OrderDao orderDao = (OrderDao) ac.getBean("orderDao");System.out.println(orderDao.getClass());orderDao.save();} }

?

?

優化和AOP注解API

API:

  • @Aspect 指定一個類為切面類

  • @Pointcut("execution( cn.itcast.e_aop_anno..(..))") 指定切入點表達式*

  • @Before("pointCut_()") 前置通知: 目標方法之前執行

  • @After("pointCut_()") 后置通知:目標方法之后執行(始終執行)

  • @AfterReturning("pointCut_()") 返回后通知: 執行方法結束前執行(異常不執行)

  • @AfterThrowing("pointCut_()") 異常通知: 出現異常時候執行

  • @Around("pointCut_()") 環繞通知: 環繞目標方法執行

  • 測試:

// 前置通知 : 在執行目標方法之前執行@Before("pointCut_()")public void begin(){System.out.println("開始事務/異常");}// 后置/最終通知:在執行目標方法之后執行 【無論是否出現異常最終都會執行】@After("pointCut_()")public void after(){System.out.println("提交事務/關閉");}// 返回后通知: 在調用目標方法結束后執行 【出現異常不執行】@AfterReturning("pointCut_()")public void afterReturning() {System.out.println("afterReturning()");}// 異常通知: 當目標方法執行異常時候執行此關注點代碼@AfterThrowing("pointCut_()")public void afterThrowing(){System.out.println("afterThrowing()");}// 環繞通知:環繞目標方式執行@Around("pointCut_()")public void around(ProceedingJoinPoint pjp) throws Throwable{System.out.println("環繞前....");pjp.proceed(); // 執行目標方法System.out.println("環繞后....");}

優化

我們的代碼是這樣的:每次寫Before、After等,都要重寫一次切入點表達式,這樣就不優雅了。

@Before("execution(* aa.*.*(..))")public void begin() {System.out.println("開始事務");}@After("execution(* aa.*.*(..))")public void close() {System.out.println("關閉事務");}

于是乎,我們要使用@Pointcut這個注解,來指定切入點表達式,在用到的地方中,直接引用就行了!

  • 那么我們的代碼就可以改造成這樣了:
@Component @Aspect//指定為切面類 public class AOP {// 指定切入點表達式,攔截哪個類的哪些方法@Pointcut("execution(* aa.*.*(..))")public void pt() {}@Before("pt()")public void begin() {System.out.println("開始事務");}@After("pt()")public void close() {System.out.println("關閉事務");} }

XML方式實現AOP編程

首先,我們把所有的注解都去掉...

  • XML文件配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--對象實例--><bean id="userDao" class="aa.UserDao"/><bean id="orderDao" class="aa.OrderDao"/><!--切面類--><bean id="aop" class="aa.AOP"/><!--AOP配置--><aop:config ><!--定義切入表達式,攔截哪些方法--><aop:pointcut id="pointCut" expression="execution(* aa.*.*(..))"/><!--指定切面類是哪個--><aop:aspect ref="aop"><!--指定來攔截的時候執行切面類的哪些方法--><aop:before method="begin" pointcut-ref="pointCut"/><aop:after method="close" pointcut-ref="pointCut"/></aop:aspect></aop:config></beans>
  • 測試:
public class App {@Testpublic void test1() {ApplicationContext ac =new ClassPathXmlApplicationContext("aa/applicationContext.xml");OrderDao orderDao = (OrderDao) ac.getBean("orderDao");System.out.println(orderDao.getClass());orderDao.save();}@Testpublic void test2() {ApplicationContext ac =new ClassPathXmlApplicationContext("aa/applicationContext.xml");IUser userDao = (IUser) ac.getBean("userDao");System.out.println(userDao.getClass());userDao.save();} }

測試OrderDao

?

?

測試UserDao

?

?

切入點表達式

切入點表達式主要就是來配置攔截哪些類的哪些方法

查官方文檔

..我們去文檔中找找它的語法...

?

?

在文檔中搜索:execution(

?

?

語法解析

那么它的語法是這樣子的:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

符號講解:

  • ?號代表0或1,可以不寫
  • “*”號代表任意類型,0或多
  • 方法參數為..表示為可變參數

參數講解:

  • modifiers-pattern?【修飾的類型,可以不寫】
  • ret-type-pattern【方法返回值類型,必寫】
  • declaring-type-pattern?【方法聲明的類型,可以不寫】
  • name-pattern(param-pattern)【要匹配的名稱,括號里面是方法的參數】
  • throws-pattern?【方法拋出的異常類型,可以不寫】

官方也有給出一些例子給我們理解:

?

?

測試代碼

<!-- 【攔截所有public方法】 --><!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--><!-- 【攔截所有save開頭的方法 】 --><!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--><!-- 【攔截指定類的指定方法, 攔截時候一定要定位到方法】 --><!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--><!-- 【攔截指定類的所有方法】 --><!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--><!-- 【攔截指定包,以及其自包下所有類的所有方法】 --><!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--><!-- 【多個表達式】 --><!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--><!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--><!-- 下面2個且關系的,沒有意義 --><!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--><!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--><!-- 【取非值】 --><!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

?

轉載于:https://my.oschina.net/u/3777556/blog/1634746

總結

以上是生活随笔為你收集整理的Spring【AOP模块】就是这么简单的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产亚洲精品久久久久久久久动漫 | 亚洲一区第一页 | 国产黄a三级 | 亚洲第一视频网站 | 成人va视频| 91av国产在线 | 狠狠搞狠狠干 | 久久精品国产免费 | 中文字幕一区二区三区精彩视频 | 久久精品国产欧美亚洲人人爽 | 欧美性极品少妇xxxx | 成人91网站 | 国产又粗又长视频 | 国产女人视频 | 久久久久久久中文字幕 | 黄色一级国产 | 国产成人看片 | 中国亚洲女人69内射少妇 | 美女啪啪av | 天天操天天干天天插 | www.日本com| 久久久久亚洲av无码专区 | 精品久久一区二区三区 | 国产乱国产乱老熟300部视频 | 91精品视频在线 | 亚洲性自拍 | 国产精品98 | 欧美三级一级 | 精品无码国产一区二区三区51安 | 黄瓜视频在线播放 | 亚洲成a人片777777久久 | 国内视频自拍 | 激情五月俺也去 | 国产亚洲二区 | 久久夜色网| 啪啪福利视频 | 天天天天天操 | 国产精品日日夜夜 | 欧美午夜精品一区二区三区电影 | 天天干天天舔天天射 | 日韩簧片在线观看 | 999成人网| 中文字幕日本 | 自拍偷拍另类 | 欧美理伦少妇2做爰 | 国产激情视频一区二区 | 久热欧美 | 香蕉久久国产av一区二区 | 91亚洲精品乱码久久久久久蜜桃 | 日韩在线精品 | 亚洲蜜臀av| 91麻豆产精品久久久久久 | 少妇高清精品毛片在线视频 | 日韩视频在线观看免费视频 | 涩涩97 | 色欧美片视频在线观看 | 天堂8在线天堂资源bt | 午夜精品免费 | www.青青草| 美女网站免费观看视频 | 男生草女生的视频 | 五月综合色 | 国产一区二区三区视频免费在线观看 | 久久久精品视频在线观看 | www视频在线观看网站 | 久久成人a | 久久久夜夜夜 | xxx性日本| 亚洲精品一区二区三区中文字幕 | 亚洲啪啪| 亚洲精选一区 | 狠狠热视频| 久久国产精品影院 | 电车痴汉在线观看 | 伊人称影院 | 国产精品视频99 | 欧美久久精品 | 久久超碰精品 | 调教奶奴 | 色哟哟国产精品色哟哟 | 欧美一级不卡视频 | 青青草原亚洲视频 | 乱老熟女一区二区三区 | 日本视频免费在线 | 男生和女生一起差差差视频 | 久久国内偷拍 | 久久午夜网 | 91精品国产综合久久香蕉922 | 欧美精品 日韩 | 国产午夜福利100集发布 | 狠狠干欧美 | 亚洲一二区在线 | 久久久精品视频在线观看 | 特大黑人巨交吊性xx | 成年丰满熟妇午夜免费视频 | 美女18网站 | 国产人成精品 | a级无遮挡超级高清-在线观看 | 91在线视频免费 |