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

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

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

    Chan Chen Coding...

    Spring AOP

    Spring AOP 簡單理解

    AOP技術(shù)即(面向切面編程)技術(shù)是在面向?qū)ο缶幊袒A(chǔ)上的發(fā)展,AOP技術(shù)是對(duì)所有對(duì)象或一類對(duì)象編程。核心是在不增加代碼的基礎(chǔ)上,還增加了新的功能。AOP編程在開發(fā)框架本身用的比較多,而實(shí)際項(xiàng)目中,用的比較少。它是將分散在各個(gè)業(yè)務(wù)邏輯代碼中的相同代碼抽取出來形成一個(gè)獨(dú)立的模塊。

    1、定義AOP術(shù)語

    (1)切面(aspect):要實(shí)現(xiàn)的交叉功能,是系統(tǒng)模塊化的一個(gè)切面或領(lǐng)域。

    (2)通知(advice):切面的具體實(shí)現(xiàn),包含五類通知。

    (3)連接點(diǎn)(jointpoint):應(yīng)用程序執(zhí)行過程中插入切面的地點(diǎn)。

    (4)切點(diǎn)(cutpoint):定義通知應(yīng)該應(yīng)用哪些連接點(diǎn)。

    (5)引入(introduction):為類添加新方法和屬性。

    (6)目標(biāo)對(duì)象(target):通知邏輯的織入目標(biāo)類。

    (7)代理(proxy):將通知應(yīng)用到目標(biāo)對(duì)象后創(chuàng)建的對(duì)象,應(yīng)用系統(tǒng)的其他部分不用為了支持代理對(duì)象而改變

    (8)織入(weaving):將切面應(yīng)用到目標(biāo)對(duì)象從而創(chuàng)建一個(gè)新代理對(duì)象的過程。

     

    2、AOP原理和實(shí)例

    (1)基礎(chǔ)接口和類的實(shí)現(xiàn):

    package com.jasson.aop;

    public interface TestServiceInter1 {

        public void sayHello();
    }


    package com.jasson.aop;

    public interface TestServiceInter2 {

        public void sayBye();
        
        public void sayHi();
    }

    (2)實(shí)現(xiàn)類如下:
    package com.jasson.aop;

    public class TestService implements TestServiceInter1,TestServiceInter2 {

        public void sayHello() {
            System.out.println("sayHello() method ");
        }

        public void sayBye() {
            System.out.println("sayBye() method");
        }
        
        public void sayHi() {
            System.out.println("sayHi() method");
        }
    }

    (1)前置通知:要求在每個(gè)方法調(diào)用前進(jìn)行日志記錄,則用的前置通知,定義如下:

    package com.jasson.aop;

    import java.lang.reflect.Method;

    import org.springframework.aop.MethodBeforeAdvice;

    public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

        /**
         * method: 方法名
         * args: 輸入?yún)?shù)
         * target: 目標(biāo)對(duì)象
         
    */
        public void before(Method method, Object[] args, Object target)
                throws Throwable {
            System.out.println("前置通知調(diào)用 記錄日志"+method.getName());
        }
    }

    配置文件如下:

     

    <?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:context="http://www.springframework.org/schema/context"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    >
    <!-- 配置被代理的對(duì)象,即目標(biāo)對(duì)象 -->
    <bean id="testService" class="com.jasson.aop.TestService" />
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.jasson.aop.MyMethodBeforeAdvice" />
    <!-- 配置代理對(duì)象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jasson.aop.TestServiceInter1</value>
                <value>com.jasson.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知織入到代理對(duì)象  -->
        <property name="interceptorNames">
            <!-- 相當(dāng)于包MyMethodBeforeAdvice前置通知和代理對(duì)象關(guān)聯(lián),我們也
            可以把通知看出攔截器,struts2核心攔截器 -->
            <list>
                <value>myMethodBeforeAdvice</value>
            </list>
        </property>
        <!-- 配置被代理對(duì)象,即目標(biāo)對(duì)象 -->
        <property name="target" ref="testService"/>
    </bean>
    </beans>
     

    package com.jasson.aop;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class App1 {

        /**
         * 
    @param args
         
    */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ApplicationContext ac=new ClassPathXmlApplicationContext("com/jasson/aop/beans.xml");
            TestServiceInter1 ts=(TestServiceInter1) ac.getBean("proxyFactoryBean");
            ts.sayHello();
            System.out.println("*******************************************");
            ((TestServiceInter2)ts).sayBye();
            System.out.println("*******************************************");
            ((TestServiceInter2)ts).sayHi();
        }
    } 

     執(zhí)行結(jié)果如下:

    31-May-2012 18:19:53 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c8f6f8: defining beans [testService,myMethodBeforeAdvice,
    myAfterReturningAdvice,myMethodInterceptor,myThrowsAdvice,proxyFactoryBean]; root of factory hierarchy
    前置通知調(diào)用 記錄日志sayHello
    sayHello() method 
    *******************************************
    前置通知調(diào)用 記錄日志sayBye
    sayBye() method
    *******************************************
    前置通知調(diào)用 記錄日志sayHi
    sayHi() method

    (2)后置通知:要求在調(diào)用每個(gè)方法后執(zhí)行的功能,例如在調(diào)用每個(gè)方法后關(guān)閉資源

     

    package com.jasson.aop;

    import java.lang.reflect.Method;

    import org.springframework.aop.AfterReturningAdvice;

    public class MyAfterReturningAdvice implements AfterReturningAdvice {

        @Override
        public void afterReturning(Object returnValue, Method method, Object[] arg,
                Object target) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("后置通知調(diào)用,關(guān)閉資源"+method.getName());
        }
    }
     bean 配置如下:
    <?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:context="http://www.springframework.org/schema/context"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    >
    <!-- 配置被代理的對(duì)象,即目標(biāo)對(duì)象 -->
    <bean id="testService" class="com.jasson.aop.TestService" />
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.jasson.aop.MyMethodBeforeAdvice" />
    <!-- 配置后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.jasson.aop.MyAfterReturningAdvice" />
    <!-- 配置代理對(duì)象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jasson.aop.TestServiceInter1</value>
                <value>com.jasson.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知織入到代理對(duì)象  -->
        <property name="interceptorNames">
            <!-- 相當(dāng)于包MyMethodBeforeAdvice前置通知和代理對(duì)象關(guān)聯(lián),我們也
            可以把通知看出攔截器,struts2核心攔截器 -->
            <list>
                <value>myMethodBeforeAdvice</value>
                <value>myAfterReturningAdvice</value>
            </list>
        </property>
        <!-- 配置被代理對(duì)象,即目標(biāo)對(duì)象 -->
        <property name="target" ref="testService"/>
    </bean>
    </beans>

    執(zhí)行結(jié)果如下:

     

    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@122cdb6: defining beans [testService,myMethodBeforeAdvice,myAfterReturningAdvice,myMethodInterceptor,myThrowsAdvice,proxyFactoryBean]; root of factory hierarchy
    前置通知調(diào)用 記錄日志sayHello
    sayHello() method 
    后置通知調(diào)用,關(guān)閉資源sayHello
    *******************************************
    前置通知調(diào)用 記錄日志sayBye
    sayBye() method
    后置通知調(diào)用,關(guān)閉資源sayBye
    *******************************************
    前置通知調(diào)用 記錄日志sayHi
    sayHi() method

    后置通知調(diào)用,關(guān)閉資源sayHi 

    (3)環(huán)繞通知:指在某個(gè)具體的方法中,添加相應(yīng)的操作

    package com.jasson.aop;

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;

    public class MyMethodInterceptor implements MethodInterceptor {

        @Override
        public Object invoke(MethodInvocation arg) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("環(huán)繞通知調(diào)用方法前");
            Object obj = arg.proceed();
            System.out.println("環(huán)繞通知調(diào)用方法后");
            return obj;
        }
    }

    配置文件如下:

    <?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:context="http://www.springframework.org/schema/context"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    >
    <!-- 配置被代理的對(duì)象,即目標(biāo)對(duì)象 -->
    <bean id="testService" class="com.jasson.aop.TestService" />
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.jasson.aop.MyMethodBeforeAdvice" />
    <!-- 配置后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.jasson.aop.MyAfterReturningAdvice" />
    <!-- 配置環(huán)繞通知 -->
    <bean id="myMethodInterceptor" class="com.jasson.aop.MyMethodInterceptor" />
    <!-- 配置代理對(duì)象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jasson.aop.TestServiceInter1</value>
                <value>com.jasson.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知織入到代理對(duì)象  -->
        <property name="interceptorNames">
            <!-- 相當(dāng)于包MyMethodBeforeAdvice前置通知和代理對(duì)象關(guān)聯(lián),我們也
            可以把通知看出攔截器,struts2核心攔截器 -->
            <list>
                <value>myMethodBeforeAdvice</value>
                <value>myAfterReturningAdvice</value>
                <value>myMethodInterceptor</value>
            </list>
        </property>
        <!-- 配置被代理對(duì)象,即目標(biāo)對(duì)象 -->
        <property name="target" ref="testService"/>
    </bean>
    </beans>
     執(zhí)行結(jié)果如下:
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1ce2dd4: defining beans [testService,myMethodBeforeAdvice,myAfterReturningAdvice,myMethodInterceptor,proxyFactoryBean]; root of factory hierarchy
    前置通知調(diào)用 記錄日志sayHello
    環(huán)繞通知調(diào)用方法前
    sayHello() method 
    環(huán)繞通知調(diào)用方法后
    后置通知調(diào)用,關(guān)閉資源sayHello
    *******************************************
    前置通知調(diào)用 記錄日志sayBye
    環(huán)繞通知調(diào)用方法前
    sayBye() method
    環(huán)繞通知調(diào)用方法后
    后置通知調(diào)用,關(guān)閉資源sayBye
    *******************************************
    前置通知調(diào)用 記錄日志sayHi
    環(huán)繞通知調(diào)用方法前
    sayHi() method
    環(huán)繞通知調(diào)用方法后
    后置通知調(diào)用,關(guān)閉資源sayHi
     (4)異常通知:當(dāng)發(fā)生異常時(shí),要執(zhí)行的通知
    package com.jasson.aop;

    import java.lang.reflect.Method;

    import org.springframework.aop.ThrowsAdvice;

    public class MyThrowsAdvice implements ThrowsAdvice {

        public void afterThrowing(Method method, Object[] os, Object target,
                Exception exception) {

            System.out.println("異常通知產(chǎn)生異常,進(jìn)行處理" + exception.getMessage());
        }
    }
     

     

    <?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:context="http://www.springframework.org/schema/context"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    >
    <!-- 配置被代理的對(duì)象,即目標(biāo)對(duì)象 -->
    <bean id="testService" class="com.jasson.aop.TestService" />
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.jasson.aop.MyMethodBeforeAdvice" />
    <!-- 配置后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.jasson.aop.MyAfterReturningAdvice" />
    <!-- 配置環(huán)繞通知 -->
    <bean id="myMethodInterceptor" class="com.jasson.aop.MyMethodInterceptor" />
    <!-- 配置異常通知 -->
    <bean id="myThrowsAdvice" class="com.jasson.aop.MyThrowsAdvice" />
    <!-- 配置代理對(duì)象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jasson.aop.TestServiceInter1</value>
                <value>com.jasson.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知織入到代理對(duì)象  -->
        <property name="interceptorNames">
            <!-- 相當(dāng)于包MyMethodBeforeAdvice前置通知和代理對(duì)象關(guān)聯(lián),我們也
            可以把通知看出攔截器,struts2核心攔截器 -->
            <list>
                <value>myMethodBeforeAdvice</value>
                <value>myAfterReturningAdvice</value>
                <value>myMethodInterceptor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
        <!-- 配置被代理對(duì)象,即目標(biāo)對(duì)象 -->
        <property name="target" ref="testService"/>
    </bean>
     

    package com.jasson.aop;

    public class TestService implements TestServiceInter1,TestServiceInter2 {

        public void sayHello() {
            System.out.println("sayHello() method ");
        }

        public void sayBye() {
            System.out.println("sayBye() method");
        }
        
        public void sayHi() {
            int a =10/0;
            System.out.println("sayHi() method");
        }
    }
     
    執(zhí)行結(jié)果如下:
    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1ce2dd4: defining beans [testService,myMethodBeforeAdvice,myAfterReturningAdvice,myMethodInterceptor,myThrowsAdvice,proxyFactoryBean]; root of factory hierarchy
    前置通知調(diào)用 記錄日志sayHello
    環(huán)繞通知調(diào)用方法前
    sayHello() method 
    環(huán)繞通知調(diào)用方法后
    后置通知調(diào)用,關(guān)閉資源sayHello
    *******************************************
    前置通知調(diào)用 記錄日志sayBye
    環(huán)繞通知調(diào)用方法前
    sayBye() method
    環(huán)繞通知調(diào)用方法后
    后置通知調(diào)用,關(guān)閉資源sayBye
    *******************************************
    前置通知調(diào)用 記錄日志sayHi
    環(huán)繞通知調(diào)用方法前
    異常通知產(chǎn)生異常,進(jìn)行處理/ by zero
    Exception in thread "main" java.lang.ArithmeticException: / by zero 

    (5)上面的通知都是針對(duì)每個(gè)方法的,如果只是對(duì)單個(gè)或者一類的方法進(jìn)行相應(yīng)處理的時(shí),可采用名字或者正則表達(dá)式的方式進(jìn)行處理

    配置如下:

    <?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:context="http://www.springframework.org/schema/context"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    >
    <!-- 配置被代理的對(duì)象,即目標(biāo)對(duì)象 -->
    <bean id="testService" class="com.jasson.aop.TestService" />
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.jasson.aop.MyMethodBeforeAdvice" />
    <!-- 配置后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.jasson.aop.MyAfterReturningAdvice" />
    <!-- 配置環(huán)繞通知 -->
    <bean id="myMethodInterceptor" class="com.jasson.aop.MyMethodInterceptor" />
    <!-- 配置異常通知 -->
    <bean id="myThrowsAdvice" class="com.jasson.aop.MyThrowsAdvice" />

    <!-- 通知與正則表達(dá)式切入點(diǎn)一起配置 -->  
    <!-- Advisor等于切入點(diǎn)加通知,所有say開頭的方法添加前置通知 -->  
    <bean id="regexpPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">  
        <property name="advice" ref="myMethodBeforeAdvice"/>  
        <property name="patterns">  
            <list>  
                <value>.*say.*</value>  
            </list>  
        </property>  
    </bean>  

    <!-- 方法名匹配切入點(diǎn)配置器:只對(duì) sayHello方法添加環(huán)繞通知-->  
    <bean id="namePointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">  
        <property name="advice" ref="myMethodInterceptor"/>  
        <property name="mappedNames">  
            <list>  
                <value>sayHello</value>  
            </list>  
        </property>  
    </bean> 

    <!-- 配置代理對(duì)象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.jasson.aop.TestServiceInter1</value>
                <value>com.jasson.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知織入到代理對(duì)象  -->
        <property name="interceptorNames">
            <!-- 相當(dāng)于包MyMethodBeforeAdvice前置通知和代理對(duì)象關(guān)聯(lián),我們也
            可以把通知看出攔截器,struts2核心攔截器 -->
            <list>
                <value>namePointcutAdvisor</value>
                <value>myAfterReturningAdvice</value>
                <value>regexpPointcutAdvisor</value>
                <value>myThrowsAdvice</value>
            </list>
        </property>
        <!-- 配置被代理對(duì)象,即目標(biāo)對(duì)象 -->
        <property name="target" ref="testService"/>
    </bean>
    </beans>

    執(zhí)行結(jié)果如下:

    INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1ef9157: defining beans 
    [testService,myMethodBeforeAdvice,myAfterReturningAdvice,myMethodInterceptor,myThrowsAdvice,regexpPointcutAdvisor,namePointcutAdvisor,proxyFactoryBean]; 
    root of factory hierarchy
    環(huán)繞通知調(diào)用方法前
    前置通知調(diào)用 記錄日志sayHello
    sayHello() method 
    后置通知調(diào)用,關(guān)閉資源sayHello
    環(huán)繞通知調(diào)用方法后
    *******************************************
    前置通知調(diào)用 記錄日志sayBye
    sayBye() method
    后置通知調(diào)用,關(guān)閉資源sayBye
    *******************************************
    前置通知調(diào)用 記錄日志sayHi
    異常通知產(chǎn)生異常,進(jìn)行處理/ by zero
    Exception in thread "main" java.lang.ArithmeticException: / by zero


    -----------------------------------------------------
    Silence, the way to avoid many problems;
    Smile, the way to solve many problems;

    posted on 2012-12-27 11:30 Chan Chen 閱讀(216) 評(píng)論(0)  編輯  收藏 所屬分類: Scala / Java

    主站蜘蛛池模板: 亚洲黄色网址大全| 在线观看免费人成视频| 亚洲中文字幕人成乱码 | 久久亚洲春色中文字幕久久久 | 亚洲精品女同中文字幕| 亚洲酒色1314狠狠做| 亚洲色大成网站WWW久久九九| 午夜免费福利影院| 永久免费AV无码国产网站| 久久精品私人影院免费看| 午夜免费国产体验区免费的| 国产人成亚洲第一网站在线播放| 亚洲精品免费在线观看| 国产午夜亚洲不卡| 亚洲AV日韩精品一区二区三区 | 一本天堂ⅴ无码亚洲道久久| 麻豆亚洲av熟女国产一区二| 欧洲亚洲国产清在高| 中文字幕精品亚洲无线码一区应用| 暖暖在线日本免费中文| 在线观看免费宅男视频| 青青视频观看免费99| 777成影片免费观看| 8x成人永久免费视频| 99在线视频免费| 99久久人妻精品免费二区| 日本免费久久久久久久网站| a级毛片免费全部播放无码| 丝袜足液精子免费视频| 三级黄色免费观看| 国产精品偷伦视频观看免费| 国产午夜精品理论片免费观看 | 亚洲精品一品区二品区三品区| www.亚洲色图.com| 国产精品亚洲αv天堂无码| 亚洲精品无码成人片在线观看 | 一级女人18片毛片免费视频| 久久er国产精品免费观看8| 一个人看的www视频免费在线观看| 五月天婷婷精品免费视频| 中文字幕免费在线视频|