AOP 動態(tài)代理

AOP 術(shù)語

  • 1.target:目標(biāo)類:需要被代理的類. 例如:UserService
  • 2.Joinpoin:(連接點(diǎn)):所謂連接點(diǎn)是指那些可能被攔截到的點(diǎn)(方法).例如:所有的方法
  • 3.PointCut 切入點(diǎn): 已經(jīng)被增強(qiáng)的連接點(diǎn).例如:addUser()
  • 4.advice 通知/增強(qiáng),增強(qiáng)代碼.例如:joinpoint
  • 5.Weaving(織入):是指把增強(qiáng)advice應(yīng)用到目標(biāo)對象 target 來創(chuàng)建新的代理對象proxy 的過程
  • 6.proxy 代理類(一個類被AOP織入增強(qiáng)后,就產(chǎn)生一個結(jié)果代理類)
  • 7.Aspect(切面):是切入點(diǎn)pointCut和通知advice (引介)的結(jié)合

一個切入點(diǎn)和一個通知(增強(qiáng)) 就組成一個特殊的面

2.2.1 JDK動態(tài)代理

  • JDK動態(tài)代理對"裝飾者"設(shè)計模式簡化 .使用前提:必須有接口

1.目標(biāo)類:接口+實現(xiàn)類

2.切面類:用于存通知 MyAspect

3.工廠類:編寫工廠去生成代理

4.測試

2.2.2 CGLIB 字節(jié)碼增強(qiáng)

  • 沒有接口,只有實現(xiàn)類.
  • 采用字節(jié)碼增強(qiáng)框架 cglib,在運(yùn)行時創(chuàng)建目標(biāo)類的子類,從而對目標(biāo)類增強(qiáng).
  • 導(dǎo)入jar包:
    手動方式:
    自動方式:

2.4 Spring 編寫代理:半自動

  • 讓spring 創(chuàng)建代理對象,從spring容器中手動的獲取代理對象
<!--創(chuàng)建目標(biāo)類-->
    <bean id="userService" class="com.xft.b_factory_bean.UserServiceImpl"></bean>

    <!--創(chuàng)建處理類-->
    <bean id="myAspect" class="com.xft.b_factory_bean.MyAspect"></bean>

    <!--創(chuàng)建代理類
        使用工廠bean FactoryBean,底層調(diào)用getObject() 返回特殊bean
        ProxyFactoryBean 用于創(chuàng)建代理工廠bean,生成特殊代理對象
        interfaces : 需要的接口們
            通過<array>可以設(shè)置多個值
            只有一個值時,value=""
        target : 確定目標(biāo)類
        interceptorNames: 通知 切面類的名稱,類型是String[],如果設(shè)置一個值value=""
        optimize:強(qiáng)制使用CGLIB
                如果目標(biāo)類有接口,采用jdk動態(tài)代理
                如果沒有接口,采用cglib字節(jié)碼增強(qiáng)
                如果聲明 optimize = true ,無論是否有接口,都采用cglib

    -->
    <bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="com.xft.b_factory_bean.UserService"></property>
        <property name="target" ref="userService"></property>
        <property name="interceptorNames" value="myAspect"></property>
        <property name="optimize" value="true"></property>
    </bean>

2.5 spring aop編程:全自動 [掌握]

  • 從spring容器獲得目標(biāo)類,如果配置aop,spring將自動生成代理
  • 要確定目標(biāo)類,aspectj 切入點(diǎn)表達(dá)式
<!--創(chuàng)建目標(biāo)類-->
    <bean id="userService" class="com.xft.c_spring_aop.UserServiceImpl"></bean>

    <!--創(chuàng)建切面類(通知)-->
    <bean id="myAspect" class="com.xft.c_spring_aop.MyAspect"></bean>

    <!--3.aop編程
        3.1 導(dǎo)入命名空間
        3.2 使用 <aop:config> 進(jìn)行配置

            proxy-target-class="true" 聲明時使用cglib代理

            <aop:pointcut> 切入點(diǎn),從目標(biāo)對象獲得具體方法
            <aop:advisor> 特殊的切面,只有一個通知和一個切入點(diǎn)
                advice-ref 通知引用
                pointcut-ref 切入點(diǎn)引用
        3.3 切入點(diǎn)表達(dá)式
                execution(* com.xft.c_spring_aop.UserServiceImpl.*.*(..))
                選擇方法 返回值任意      包                    類名任意 方法名任意 參數(shù)任意
    -->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="myPointCut" expression="execution(* com.xft.c_spring_aop.*.*(..))" />
        <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut" />
    </aop:config>

3 AspectJ

3.1 介紹

  • AspectJ 是一個基于Java語言的AOP框架
  • Spring2.0以后新增了對AspectJ切點(diǎn)表達(dá)式支持
    @AspectJ 是AspectJ1.5新增功能通過JDK5 注解技術(shù),允許直接在Bean類中定義切面.新版本Spring框架,建議使用AspectJ方式來開發(fā)AOP
  • 主要用途:自定義開發(fā)

3.2 切入點(diǎn)表達(dá)式 {掌握}

1. execution() 用于描述方法
    語法:execution(修飾符  返回值  包.類.方法(參數(shù))throws 異常)
        修飾符,一般省略
            public  公共方法
            *       任意
        返回值,
            void    返回沒有值
            String  返回值字符串
            *       任意
        包,[省略]
            com.xft.xxx     固定包名
            com.xft.xxx*.service   xxx包下面子包任意  (例如:com.xft.xxx.ssss.service)
            com.xft.xxx..   xxx包下面所有子包
            com.xft.xxx.*.service.. xxx包下面任意包,固定目錄service,service目錄任意包
        類,[省略]
            UserServiceImpl     指定類
            *Impl               以Impl結(jié)尾
            User*               以User開頭
            *                   任意
        方法名,不能省略
            addUser         固定方法
            add*            以add開頭
            *Do             以Do結(jié)尾
            *               任意
        (參數(shù))
            ()              無參
            (int)           一個整型
            (int,int)       兩個整型
            (..)            任意參數(shù)
        throw,可以省略,一般不寫 
        
    綜合1 
    execution(* com.xft.xxx.*.service..*.*(..))
    綜合2 
    <aop:pointcut express="execution(* com.xft.*.withCommit*(..))||
                execution(* com.xft.*Service.*(..))" id="myPointCut">

2.within:匹配包或者子包中的方法
    within(cn.itcaset.aop..*)
    
3.this:匹配實現(xiàn)接口的代理對象中的方法
    this(cn.itcast.aop.user.UserDAO)

4.target:匹配實現(xiàn)接口的目標(biāo)對象中的方法
    target(cn.itcase.aop.user.UserDAO)
    
5.args:匹配參數(shù)格式符號標(biāo)準(zhǔn)的方法
    args(int,int )
    
6.bean(id) 對指定的bean所有的方法
    bean('userServiceId')

3.3 AspectJ 通知類型

  • aop聯(lián)盟定義的通知類型,具有特性接口,必須實現(xiàn),從而確定方法名稱
  • aspectj 通知類型,只定義類型名稱,已經(jīng)方法格式
  • 個數(shù):6種
    1. before前置通知(應(yīng)用:各種校驗) 在方法執(zhí)行前執(zhí)行,如果通知拋出異常,阻止方法運(yùn)行
    2. afterReturning:后置通知(應(yīng)用:常規(guī)數(shù)據(jù)處理) 方法正常返回后執(zhí)行,如果方法中拋出異常,通知無法執(zhí), 必須在方法執(zhí)行后才執(zhí)行,所以可以獲得方法的返回值
    3. around:環(huán)繞通知(應(yīng)用:十分強(qiáng)大,可以做任何事) 方法執(zhí)行前后分別執(zhí)行,可以阻止方法的執(zhí)行
    4. afterThrowing:拋出異常通知(應(yīng)用:包裝異常信息) 方法拋出異常后執(zhí)行,如果方法沒有拋出異常,無法執(zhí)行
    5. after:最終通知(應(yīng)用:清理現(xiàn)場) 方法執(zhí)行完畢后執(zhí)行,無論方法中是否出現(xiàn)異常

3.4 基于xml

  1. 目標(biāo)類:接口+實現(xiàn)
  2. 切面類:編寫多個通知,采用aspectj通知名稱任意(方法名任意)
  3. aop編程,將通知應(yīng)用到目標(biāo)類
  4. 測試

3.4 基于注解

3.4.1替換bean

 <!--創(chuàng)建目標(biāo)類-->
    <bean id="userService" class="com.xft.d_aspect.b_anno.UserServiceImpl"></bean>

    <!--創(chuàng)建切面類(通知)-->
    <bean id="myAspect" class="com.xft.d_aspect.b_anno.MyAspect"></bean>

aop注解總結(jié)

@Aspect 聲明切面,修飾切面類,從而獲得,通知
通知
    @Before 前置
    @AfterReturning 后置
    @Around 環(huán)繞
    @AfterThrowing 拋出異常
    @After 最終
切入點(diǎn)
    @PointCut,修飾方法 private void xxx(){} 之后通過"方法名"獲得切入點(diǎn)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本章內(nèi)容: 面向切面編程的基本原理 通過POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,408評論 0 9
  • **** AOP 面向切面編程 底層原理 代理!?。?今天AOP課程1、 Spring 傳統(tǒng) AOP2、 Spri...
    luweicheng24閱讀 1,502評論 0 1
  • AOP實現(xiàn)可分為兩類(按AOP框架修改源代碼的時機(jī)): 靜態(tài)AOP實現(xiàn):AOP框架在編譯階段對程序進(jìn)行修改,即實現(xiàn)...
    數(shù)獨(dú)題閱讀 2,399評論 0 22
  • 面向切面編程(AOP) 什么是面向切面編程 AOP是面向切面的編程,其編程思想是把散布于不同業(yè)務(wù)但功能相同的代碼從...
    cifang12閱讀 143評論 0 0
  • 故事的女主是我的大學(xué)同學(xué),雖然并不算很熟悉,但確是為數(shù)不多的能聊的來的好朋友。 前一段的某一天,她問我店里可以DI...
    西西愛木閱讀 353評論 2 5

友情鏈接更多精彩內(nèi)容