色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

聊聊在使用Spring AOP時(shí)一個(gè)非常常見的概念A(yù)spectJ

OSC開源社區(qū) ? 來源:江南一點(diǎn)雨 ? 2023-08-30 09:40 ? 次閱讀

1. 關(guān)于代理

小伙伴們知道,Java 23 種設(shè)計(jì)模式中有一種模式叫做代理模式,這種代理我們可以將之稱為靜態(tài)代理,Spring AOP 我們常說是一種動(dòng)態(tài)代理,那么這兩種代理的區(qū)別在哪里呢?

1.1 靜態(tài)代理

這種代理在我們?nèi)粘I钪衅鋵?shí)非常常見,例如房屋中介就相當(dāng)于是一個(gè)代理,當(dāng)房東需要出租房子的時(shí)候,需要發(fā)布廣告、尋找客戶、清理房間。。。由于比較麻煩,因此房東可以將租房子這件事情委托給中間代理去做。這就是一個(gè)靜態(tài)代理。

我通過一個(gè)簡(jiǎn)單的代碼來演示一下,首先我們有一個(gè)租房的接口,如下:

publicinterfaceRent{
voidrent();
}

房東實(shí)現(xiàn)了該接口,表示想要出租房屋:

publicclassLandlordimplementsRent{
@Override
publicvoidrent(){
System.out.println("房屋出租");
}
}

中介作為中間代理,也實(shí)現(xiàn)了該接口,同時(shí)代理了房東,如下:

publicclassHouseAgentimplementsRent{
privateLandlordlandlord;

publicHouseAgent(Landlordlandlord){
this.landlord=landlord;
}

publicHouseAgent(){
}

@Override
publicvoidrent(){
publishAd();
landlord.rent();
agencyFee();
}

publicvoidpublishAd(){
System.out.println("發(fā)布招租廣告");
}

publicvoidagencyFee(){
System.out.println("收取中介費(fèi)");
}
}

可以看到,中介的 rent 方法中,除了調(diào)用房東的 rent 方法之外,還調(diào)用了 publishAd 和 agencyFee 兩個(gè)方法。

接下來客戶租房,只需要和代理打交道就可以了,如下:

publicclassClient{
publicstaticvoidmain(String[]args){
Landlordlandlord=newLandlord();
HouseAgenthouseAgent=newHouseAgent(landlord);
houseAgent.rent();
}
}

這就是一個(gè)簡(jiǎn)單的代理模式。無論大家是否有接觸過 Java 23 種設(shè)計(jì)模式,上面這段代碼應(yīng)該都很好理解。

這是靜態(tài)代理。

1.2 動(dòng)態(tài)代理

動(dòng)態(tài)代理講究在不改變?cè)愒椒ǖ那闆r下,增強(qiáng)目標(biāo)方法的功能,例如,大家平時(shí)使用的 Spring 事務(wù)功能,在不改變目標(biāo)方法的情況下,就可以通過動(dòng)態(tài)代理為方法添加事務(wù)處理能力。再比如松哥在 TienChin 項(xiàng)目中所講的日志處理、接口冪等性處理、多數(shù)據(jù)源處理等,都是動(dòng)態(tài)代理能力的體現(xiàn)

從實(shí)現(xiàn)原理上,我們又可以將動(dòng)態(tài)代理劃分為兩大類:

編譯時(shí)增強(qiáng)。

運(yùn)行時(shí)增強(qiáng)。

1.2.1 編譯時(shí)增強(qiáng)

編譯時(shí)增強(qiáng),這種有點(diǎn)類似于 Lombok 的感覺,就是在編譯階段就直接生成了代理類,將來運(yùn)行的時(shí)候,就直接運(yùn)行這個(gè)編譯生成的代理類,AspectJ 就是這樣一種編譯時(shí)增強(qiáng)的工具。

AspectJ 全稱是 Eclipse AspectJ, 其官網(wǎng)地址是:http://www.eclipse.org/aspectj,截止到本文寫作時(shí),目前最新版本為:1.9.7。

從官網(wǎng)我們可以看到 AspectJ 的定位:

基于 Java 語言的面向切面編程語言。

兼容 Java。

易學(xué)易用。

使用 AspectJ 時(shí)需要使用專門的編譯器 ajc。

1.2.2 運(yùn)行時(shí)增強(qiáng)

運(yùn)行時(shí)增強(qiáng)則是指借助于 JDK 動(dòng)態(tài)代理或者 CGLIB 動(dòng)態(tài)代理等,在內(nèi)存中臨時(shí)生成 AOP 動(dòng)態(tài)代理類,我們?cè)?Spring AOP 中常說的動(dòng)態(tài)代理,一般是指這種運(yùn)行時(shí)增強(qiáng)。

我們平日開發(fā)寫的 Spring AOP,基本上都是屬于這一類。

2. AspectJ 和 Spring AOP

經(jīng)過前面的介紹,相信大家已經(jīng)明白了 AspectJ 其實(shí)也是 AOP 的一種實(shí)現(xiàn),只不過它是編譯時(shí)增強(qiáng)。

接下來,松哥再通過三個(gè)具體的案例,來和小伙伴們演示編譯時(shí)增強(qiáng)和運(yùn)行時(shí)增強(qiáng)。

2.1 AspectJ

首先,在 IDEA 中想要運(yùn)行 AspectJ,需要先安裝 AspectJ 插件,就是下面這個(gè):

55bc36ce-465d-11ee-a2ef-92fbcf53809c.png

安裝好之后,我們需要在 IDEA 中配置一下,使用 ajc 編譯器代替 javac(這個(gè)是針對(duì)當(dāng)前項(xiàng)目的設(shè)置,所以可以放心修改):

55c3e630-465d-11ee-a2ef-92fbcf53809c.png

有如下幾個(gè)需要修改的點(diǎn):

首先修改編譯器為 ajc。

將使用的 Java 版本改為 8,這個(gè)一共有兩個(gè)地方需要修改。

設(shè)置 aspectjtools.jar 的位置,這個(gè) jar 包需要自己提前準(zhǔn)備好,可以從 Maven 官網(wǎng)下載,然后在這里配置 jar 的路徑,配置完成之后,點(diǎn)擊 test 按鈕進(jìn)行測(cè)試,測(cè)試成功就會(huì)彈出來圖中的彈框。

對(duì)于第 3 步所需要的 jar,也可以在項(xiàng)目的 Maven 中添加如下依賴,自動(dòng)下載,下載到本地倉庫之后,再刪除掉 pom.xml 中的配置即可:


org.aspectj
aspectjtools
1.9.7.M3

這樣,開發(fā)環(huán)境就準(zhǔn)備好了。

接下來,假設(shè)我有一個(gè)銀行轉(zhuǎn)帳的方法:

publicclassMoneyService{

publicvoidtransferMoney(){
System.out.println("轉(zhuǎn)賬操作");
}
}

我想給這個(gè)方法添加事務(wù),那么我就新建一個(gè) Aspect,如下:

publicaspectTxAspect{
voidaround():call(voidMoneyService.transferMoney()){
System.out.println("開啟事務(wù)");
try{
proceed();
System.out.println("提交事務(wù)事務(wù)");
}catch(Exceptione){
System.out.println("回滾事務(wù)");
}
}
}

這就是 AspectJ 的語法,跟 Java 有點(diǎn)像,但是不太一樣。需要注意的是,這個(gè) TxAspect 不是一個(gè) Java 類,它的后綴是 .aj。

proceed 表示繼續(xù)執(zhí)行目標(biāo)方法,前后邏輯比較簡(jiǎn)單,我就不多說了。

最后,我們?nèi)ミ\(yùn)行轉(zhuǎn)賬服務(wù):

publicclassDemo01{
publicstaticvoidmain(String[]args){
MoneyServicemoneyService=newMoneyService();
moneyService.transferMoney();
}
}

運(yùn)行結(jié)果如下:

55e67bbe-465d-11ee-a2ef-92fbcf53809c.png

這就是一個(gè)靜態(tài)代理。

為什么這么說呢?我們通過 IDEA 來查看一下 TxAspect 編譯之后的結(jié)果:

@Aspect
publicclassTxAspect{
static{
try{
ajc$postClinit();
}catch(Throwablevar1){
ajc$initFailureCause=var1;
}

}

publicTxAspect(){
}

@Around(
value="call(voidMoneyService.transferMoney())",
argNames="ajc$aroundClosure"
)
publicvoidajc$around$org_javaboy_demo_p2_TxAspect$1$3b99afea(AroundClosureajc$aroundClosure){
System.out.println("開啟事務(wù)");

try{
ajc$around$org_javaboy_demo_p2_TxAspect$1$3b99afeaproceed(ajc$aroundClosure);
System.out.println("提交事務(wù)事務(wù)");
}catch(Exceptionvar2){
System.out.println("回滾事務(wù)");
}

}

publicstaticTxAspectaspectOf(){
if(ajc$perSingletonInstance==null){
thrownewNoAspectBoundException("org_javaboy_demo_p2_TxAspect",ajc$initFailureCause);
}else{
returnajc$perSingletonInstance;
}
}

publicstaticbooleanhasAspect(){
returnajc$perSingletonInstance!=null;
}
}

再看一下編譯之后的啟動(dòng)類:

publicclassDemo01{
publicDemo01(){
}

publicstaticvoidmain(String[]args){
MoneyServicemoneyService=newMoneyService();
transferMoney_aroundBody1$advice(moneyService,TxAspect.aspectOf(),(AroundClosure)null);
}
}

可以看到,都是修改后的內(nèi)容了。

所以說 AspectJ 的作用就有點(diǎn)類似于 Lombok,直接在編譯時(shí)期將我們的代碼改了,這就是編譯時(shí)增強(qiáng)。

2.2 Spring AOP

Spring AOP 在開發(fā)的時(shí)候,其實(shí)也使用了 AspectJ 中的注解,像我們平時(shí)使用的 @Aspect、@Around、@Pointcut 等,都是 AspectJ 里邊提供的,但是 Spring AOP 并未借鑒 AspectJ 的編譯時(shí)增強(qiáng),Spring AOP 沒有使用 AspectJ 的編譯器和織入器,Spring AOP 還是使用了運(yùn)行時(shí)增強(qiáng)。

運(yùn)行時(shí)增強(qiáng)可以利用 JDK 動(dòng)態(tài)代理或者 CGLIB 動(dòng)態(tài)代理來實(shí)現(xiàn)。我分別來演示。

2.2.1 JDK 動(dòng)態(tài)代理

JDK 動(dòng)態(tài)代理有一個(gè)要求,就是被代理的對(duì)象需要有接口,沒有接口不行,CGLIB 動(dòng)態(tài)代理則無此要求。

假設(shè)我現(xiàn)在有一個(gè)計(jì)算器接口:

publicinterfaceICalculator{
intadd(inta,intb);
}

這個(gè)接口有一個(gè)實(shí)現(xiàn)類:

publicclassCalculatorImplimplementsICalculator{
@Override
publicintadd(inta,intb){
System.out.println(a+"+"+b+"="+(a+b));
returna+b;
}
}

現(xiàn)在,我想通過動(dòng)態(tài)代理實(shí)現(xiàn)統(tǒng)計(jì)該接口的執(zhí)行時(shí)間功能,JDK 動(dòng)態(tài)代理如下:

publicclassDemo02{
publicstaticvoidmain(String[]args){

CalculatorImplcalculator=newCalculatorImpl();
ICalculatorproxyInstance=(ICalculator)Proxy.newProxyInstance(Demo02.class.getClassLoader(),newClass[]{ICalculator.class},newInvocationHandler(){
@Override
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
longstartTime=System.currentTimeMillis();
Objectinvoke=method.invoke(calculator,args);
longendTime=System.currentTimeMillis();
System.out.println(method.getName()+"方法執(zhí)行耗時(shí)"+(endTime-startTime)+"毫秒");
returninvoke;
}
});
proxyInstance.add(3,4);
}
}

不需要任何額外依賴,都是 JDK 自帶的能力:

Proxy.newProxyInstance 方法表示要生成一個(gè)動(dòng)態(tài)代理對(duì)象。

newProxyInstance 方法有三個(gè)參數(shù),第一個(gè)是一個(gè)類加載器,第二個(gè)參數(shù)是一個(gè)被代理的對(duì)象所實(shí)現(xiàn)的接口,第三個(gè)則是具體的代理邏輯。

在 InvocationHandler 中,有一個(gè) invoke 方法,該方法有三個(gè)參數(shù),分別表示當(dāng)前代理對(duì)象,被攔截下來的方法以及方法的參數(shù),我們?cè)谠摲椒ㄖ锌梢越y(tǒng)計(jì)被攔截方法的執(zhí)行時(shí)間,通過方式執(zhí)行被攔截下來的目標(biāo)方法。

最終,第一步的方法返回了一個(gè)代理對(duì)象,執(zhí)行該代理對(duì)象,就有代理的效果了。

上面這個(gè)案例就是一個(gè) JDK 動(dòng)態(tài)代理。這是一種運(yùn)行時(shí)增強(qiáng),在編譯階段并未修改我們的代碼。

2.2.2 CGLIB 動(dòng)態(tài)代理

從 SpringBoot2 開始,AOP 默認(rèn)使用的動(dòng)態(tài)代理就是 CGLIB 動(dòng)態(tài)代理了,相比于 JDK 動(dòng)態(tài)代理,CGLIB 動(dòng)態(tài)代理支持代理一個(gè)類。

使用 CGLIB 動(dòng)態(tài)代理,需要首先添加依賴,如下:


cglib
cglib
3.3.0

假設(shè)我有一個(gè)計(jì)算器,如下:

publicclassCalculator{
publicintadd(inta,intb){
System.out.println(a+"+"+b+"="+(a+b));
returna+b;
}
}

大家注意,這個(gè)計(jì)算器就是一個(gè)實(shí)現(xiàn)類,沒有接口。

現(xiàn)在,我想統(tǒng)計(jì)這個(gè)計(jì)算器方法的執(zhí)行時(shí)間,首先,我添加一個(gè)方法執(zhí)行的攔截器:

publicclassCalculatorInterceptorimplementsMethodInterceptor{
@Override
publicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{
longstartTime=System.currentTimeMillis();
Objectresult=methodProxy.invokeSuper(o,objects);
longendTime=System.currentTimeMillis();
System.out.println(method.getName()+"方法執(zhí)行耗時(shí)"+(endTime-startTime)+"毫秒");
returnresult;
}
}

當(dāng)把代理方法攔截下來之后,額外要做的事情就在 intercept 方法中完成。通過執(zhí)行 methodProxy.invokeSuper 可以調(diào)用到代理方法。

最后,配置 CGLIB,為方法配置增強(qiáng):

publicclassDemo03{
publicstaticvoidmain(String[]args){
Enhancerenhancer=newEnhancer();
enhancer.setSuperclass(Calculator.class);
enhancer.setCallback(newCalculatorInterceptor());
Calculatorcalculator=(Calculator)enhancer.create();
calculator.add(4,5);
}
}

這里其實(shí)就是創(chuàng)建了字節(jié)增強(qiáng)器,為生成的代理對(duì)象配置 superClass,然后設(shè)置攔截下來之后的回調(diào)函數(shù)就行了,最后通過 create 方法獲取到一個(gè)代理對(duì)象。

這就是 CGLIB 動(dòng)態(tài)代理。

3. 小結(jié)

經(jīng)過上面的介紹,現(xiàn)在大家應(yīng)該搞明白了靜態(tài)代理、編譯時(shí)增強(qiáng)的動(dòng)態(tài)代理和運(yùn)行時(shí)增強(qiáng)的動(dòng)態(tài)代理了吧~

那么我們?cè)陧?xiàng)目中到底該如何選擇呢?

先來說 AspectJ 的幾個(gè)優(yōu)勢(shì)吧。

Spring AOP 由于要生成動(dòng)態(tài)代理類,因此,對(duì)于一些 static 或者 final 修飾的方法,是無法代理的,因?yàn)檫@些方法是無法被重寫的,final 修飾的類也無法被繼承。但是,AspectJ 由于不需要?jiǎng)討B(tài)生成代理類,一切都是編譯時(shí)完成的,因此,這個(gè)問題在 AspectJ 中天然的就被解決了。

Spring AOP 有一個(gè)局限性,就是只能用到被 Spring 容器管理的 Bean 上,其他的類則無法使用,AspectJ 則無此限制(話說回來,Java 項(xiàng)目 Spring 基本上都是標(biāo)配了,所以這點(diǎn)其實(shí)到也不重要)。

Spring AOP 只能在運(yùn)行時(shí)增強(qiáng),而 AspectJ 則支持編譯時(shí)增強(qiáng),編譯后增強(qiáng)以及運(yùn)行時(shí)增強(qiáng)。

Spring AOP 支持方法的增強(qiáng),然而 AspectJ 支持方法、屬性、構(gòu)造器、靜態(tài)對(duì)象、final 類/方法等的增強(qiáng)。

AspectJ 由于是編譯時(shí)增強(qiáng),因此運(yùn)行效率也要高于 Spring AOP。

。。。

雖然 AspectJ 有這么多優(yōu)勢(shì),但是 Spring AOP 卻有另外一個(gè)制勝法寶,那就是簡(jiǎn)單易用

所以,我們?nèi)粘i_發(fā)中,還是 Spring AOP 使用更多。






審核編輯:劉清
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1636

    瀏覽量

    49178
  • 計(jì)算器
    +關(guān)注

    關(guān)注

    16

    文章

    437

    瀏覽量

    37396
  • JAVA語言
    +關(guān)注

    關(guān)注

    0

    文章

    138

    瀏覽量

    20116
  • AOP
    AOP
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    11111

原文標(biāo)題:似懂非懂的 AspectJ

文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    AOP知識(shí)詳解

    今天我們繼續(xù)看看AOP相關(guān)的知識(shí),前面說到了Javassit,Spring AOP,通過該篇,讓你對(duì)AOP有更完整的認(rèn)識(shí)。 AOP 再看
    的頭像 發(fā)表于 09-25 11:14 ?983次閱讀
    <b class='flag-5'>AOP</b>知識(shí)詳解

    Spring AOP如何破解java應(yīng)用

    前面我們看過javaassit是如何破解java應(yīng)用,核心都是AOP相關(guān)的知識(shí),今天我們看下Spring AOP是怎么回事! Spring-AOP
    的頭像 發(fā)表于 09-25 11:16 ?908次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>AOP</b>如何破解java應(yīng)用

    java spring教程

    Spring核心概念介紹控制反轉(zhuǎn)(IOC)依賴注入(DI)集合對(duì)象注入等Bean的管理BeanFactoryApplicationContextSpring web中的使用
    發(fā)表于 09-11 11:09

    什么是java spring

    或多個(gè)模塊聯(lián)合實(shí)現(xiàn)簡(jiǎn)單來說,Spring個(gè)輕量級(jí)的控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器框架。■ 輕量——從大小與開銷兩方面而言Sprin
    發(fā)表于 09-11 11:16

    聊聊Dubbo - Dubbo可擴(kuò)展機(jī)制源碼解析

    摘要: Dubbo可擴(kuò)展機(jī)制實(shí)戰(zhàn)中,我們了解了Dubbo擴(kuò)展機(jī)制的概念,初探了Dubbo中LoadBalance的實(shí)現(xiàn),并自己實(shí)現(xiàn)了個(gè)
    發(fā)表于 06-05 18:43

    Spring工作原理

    核心就是AOP這個(gè)就是面向切面編程,可以為某類對(duì)象 進(jìn)行監(jiān)督和控制(也就是調(diào)用這類對(duì)象的具體方法的前后去調(diào)用你指定的 模塊)從而達(dá)到對(duì)個(gè)
    發(fā)表于 07-10 07:41

    Spring筆記分享

    Spring實(shí)現(xiàn)了使用簡(jiǎn)單的組件配置組合成個(gè)復(fù)雜的應(yīng)用。 Spring 中可以使用XML和Java注解組合這些對(duì)象。6)
    發(fā)表于 11-04 07:51

    Spring AOP使用教程及代碼詳講

    和多態(tài)性等概念來建立種對(duì)象層次結(jié)構(gòu),用以模擬公共行為的個(gè)集合。當(dāng)我們需要為分散的對(duì)象引入公共行為的時(shí)候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關(guān)系,但并不適合定
    發(fā)表于 12-14 01:19 ?2734次閱讀

    Spring認(rèn)證是什么?

    ,例如:配置、組件掃描、AOP、數(shù)據(jù)訪問和事務(wù)、REST、安全、自動(dòng)配置、執(zhí)行器、 Spring boot測(cè)試等。
    的頭像 發(fā)表于 07-04 10:19 ?1341次閱讀
    <b class='flag-5'>Spring</b>認(rèn)證是什么?

    Spring框架的簡(jiǎn)單介紹及快速入門教程

    開發(fā)者J2EE開發(fā)中遇到的許多常見的問題,提供了功能強(qiáng)大IOC、AOP及Web MVC等功能。Spring可以單獨(dú)應(yīng)用于構(gòu)筑應(yīng)用程序,也可以和Struts、Webwork、Tapes
    的頭像 發(fā)表于 07-15 14:47 ?1759次閱讀

    剖析Spring中最常用的擴(kuò)展點(diǎn)(上)

    我們說到spring,可能第一個(gè)想到的是 `IOC`(控制反轉(zhuǎn)) 和 `AOP`(面向切面編程)。 沒錯(cuò),它們是spring的基石,
    的頭像 發(fā)表于 02-15 16:06 ?765次閱讀
    剖析<b class='flag-5'>Spring</b>中最常用的擴(kuò)展點(diǎn)(上)

    剖析Spring中最常用的擴(kuò)展點(diǎn)(中)

    我們說到spring,可能第一個(gè)想到的是 `IOC`(控制反轉(zhuǎn)) 和 `AOP`(面向切面編程)。 沒錯(cuò),它們是spring的基石,
    的頭像 發(fā)表于 02-15 16:06 ?519次閱讀
    剖析<b class='flag-5'>Spring</b>中最常用的擴(kuò)展點(diǎn)(中)

    剖析Spring中最常用的擴(kuò)展點(diǎn)(下)

    我們說到spring,可能第一個(gè)想到的是 `IOC`(控制反轉(zhuǎn)) 和 `AOP`(面向切面編程)。 沒錯(cuò),它們是spring的基石,
    的頭像 發(fā)表于 02-15 16:07 ?485次閱讀

    解讀Spring源碼中的IOC和AOP部分

    Spring Framework 是個(gè)非常流行的開源框架,為 Java 應(yīng)用程序提供了廣泛的支持和功能。
    的頭像 發(fā)表于 06-06 15:49 ?762次閱讀

    AOP要怎么使用

    到,創(chuàng)建個(gè)切面Advisor,并且將切點(diǎn)都綁定到個(gè)自定義注解上面。 引入AOP的Starts: org .springframework
    的頭像 發(fā)表于 10-09 16:18 ?695次閱讀
    <b class='flag-5'>AOP</b>要怎么使用
    主站蜘蛛池模板: 乳色吐息在线观看全集免费观看| 国产99r视频精品免费观看| 少妇仑乱A毛片| 且试天下芒果免费观看| 男人的天堂黄色| 美女白虎穴| 久久超碰国产精品最新| 黄色a一级视频| 韩国甜性涩爱| 黑人操日本女人| 精品国产在天天线在线麻豆 | 法国剧丝袜情版h级在线电影| 午夜电影三级还珠格格| 日韩无码在线| 日日噜噜大屁股熟妇| 日韩精品欧美在线视频在线| 肉耽高h一受n攻| 偷拍国产精品在线播放| 午夜亚洲精品不卡在线 | 午夜精品久久久久久99热蜜桃| 拉菲娱乐主管高工资q39709| 精品亚洲视频在线观看| 九九免费精品视频| 啦啦啦影院视频在线看高清...| 国产精品.XX视频.XXTV| 囯产精品久久久久免费蜜桃| 国产免费人成在线看视频| 狠狠色狠狠色综合日日2019| 久久久精品久久久久三级| 麻豆婷婷狠狠色18禁久久| 女生扒开下面| 日日噜噜夜夜躁躁狠狠| 午夜向日葵高清在线观看| 亚洲日本乱码中文论理在线电影| 午夜看片福利在线观看| 亚洲a视频在线| 一级性生活毛片| 99精品国产免费久久久久久下载| 在线毛片片免费观看| 91在线一区二区| 岛国片在线看|