在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒ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è)簡單的代碼來演示一下,首先我們有一個(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è)簡單的代理模式。無論大家是否有接觸過 Java 23 種設(shè)計(jì)模式,上面這段代碼應(yīng)該都很好理解。

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

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

動(dòng)態(tài)代理講究在不改變原類原方法的情況下,增強(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)代理類,我們在 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è)是針對當(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)行測試,測試成功就會(huì)彈出來圖中的彈框。

對于第 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)方法,前后邏輯比較簡單,我就不多說了。

最后,我們?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è)要求,就是被代理的對象需要有接口,沒有接口不行,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)代理對象。

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

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

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

上面這個(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)器,為生成的代理對象配置 superClass,然后設(shè)置攔截下來之后的回調(diào)函數(shù)就行了,最后通過 create 方法獲取到一個(gè)代理對象。

這就是 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)代理了吧~

那么我們在項(xiàng)目中到底該如何選擇呢?

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

Spring AOP 由于要生成動(dòng)態(tài)代理類,因此,對于一些 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)對象、final 類/方法等的增強(qiáng)。

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

。。。

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

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






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

    關(guān)注

    1

    文章

    1642

    瀏覽量

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

    關(guān)注

    16

    文章

    438

    瀏覽量

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

    關(guān)注

    0

    文章

    138

    瀏覽量

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

    關(guān)注

    0

    文章

    40

    瀏覽量

    11123

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

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

收藏 人收藏

    評論

    相關(guān)推薦

    AOP知識(shí)詳解

    今天我們繼續(xù)看看AOP相關(guān)的知識(shí),前面說到了Javassit,Spring AOP,通過該篇,讓你對AOP有更完整的認(rèn)識(shí)。 AOP 再看
    的頭像 發(fā)表于 09-25 11:14 ?1026次閱讀
    <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 ?935次閱讀
    <b class='flag-5'>Spring</b> <b class='flag-5'>AOP</b>如何破解java應(yīng)用

    java spring教程

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

    什么是java spring

    或多個(gè)模塊聯(lián)合實(shí)現(xiàn)簡單來說,Spring個(gè)輕量級的控制反轉(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è)就是面向切面編程,可以為某類對象 進(jìn)行監(jiān)督和控制(也就是調(diào)用這類對象的具體方法的前后去調(diào)用你指定的 模塊)從而達(dá)到對個(gè)
    發(fā)表于 07-10 07:41

    Spring筆記分享

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

    Spring AOP使用教程及代碼詳講

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

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

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

    Spring框架的簡單介紹及快速入門教程

    開發(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 ?1787次閱讀

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

    我們說到spring,可能第一個(gè)想到的是 `IOC`(控制反轉(zhuǎn)) 和 `AOP`(面向切面編程)。 沒錯(cuò),它們是spring的基石,
    的頭像 發(fā)表于 02-15 16:06 ?797次閱讀
    剖析<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 ?546次閱讀
    剖析<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 ?516次閱讀

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

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

    AOP要怎么使用

    到,創(chuàng)建個(gè)切面Advisor,并且將切點(diǎn)都綁定到個(gè)自定義注解上面。 引入AOP的Starts: org .springframework
    的頭像 發(fā)表于 10-09 16:18 ?732次閱讀
    <b class='flag-5'>AOP</b>要怎么使用
    主站蜘蛛池模板: 天堂在线网站 | 九月丁香婷婷亚洲综合色 | 成人三级影院 | 免费视频一级片 | 一级免费看片 | 男女交性视频播放视频视频 | 俄罗斯欧美色黄激情 | 中文字幕乱码人成乱码在线视频 | 婷婷爱五月天 | 新版天堂中文资源8在线 | vip影视免费观看 | 黄网站视频 | 国产亚洲小视频 | 欧美成人全部费免网站 | 男女那啥的视频免费 | 国产精品久久久精品视频 | 日本一区二区精品88 | 日日噜噜噜夜夜爽爽狠狠视频 | 午夜影剧 | 伊人精品在线观看 | 日韩欧美伦理 | 国产午夜精品一区二区理论影院 | 亚洲第一免费网站 | 琪琪午夜免费影院在线观看 | 欧美深夜| 黄色成人免费网站 | 337p欧洲亚洲大胆艺术 | 手机看片日韩永久福利盒子 | 日本免费黄色大片 | 国产gav成人免费播放视频 | 日本不卡免费高清一级视频 | 来啊mm影院亚洲mm影院 | 最刺激黄a大片免费观看下截 | 色久优优 | 亚洲午夜大片 | 日韩三级在线观看视频 | 激情久久婷婷 | 日本高清色视频在线观看免费 | 深爱五月激情五月 | 国产欧美日韩在线人成aaaa | 精品国产成人三级在线观看 |