溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring中如何實(shí)現(xiàn)AOP

發(fā)布時(shí)間:2022-01-20 13:44:07 來源:億速云 閱讀:190 作者:小新 欄目:開發(fā)技術(shù)

這篇“Spring中如何實(shí)現(xiàn)AOP”除了程序員外大部分人都不太理解,今天小編為了讓大家更加理解“Spring中如何實(shí)現(xiàn)AOP”,給大家總結(jié)了以下內(nèi)容,具有一定借鑒價(jià)值,內(nèi)容詳細(xì)步驟清晰,細(xì)節(jié)處理妥當(dāng),希望大家通過這篇文章有所收獲,下面讓我們一起來看看具體內(nèi)容吧。

    1、xml 的方式實(shí)現(xiàn) AOP

    ①、接口 UserService

    package com.ys.aop;
    public interface UserService {
        //添加 user
        public void addUser();
        //刪除 user
        public void deleteUser();
    }

    ②、實(shí)現(xiàn)類 UserServiceImpl

    package com.ys.aop;
    public class UserServiceImpl implements UserService{
        @Override
        public void addUser() {
            System.out.println("增加 User");
        }
        @Override
        public void deleteUser() {
            System.out.println("刪除 User");
        }
    }

    ③、切面類,也就是通知類 MyAspect

    package com.ys.aop;
    import org.aspectj.lang.JoinPoint;
    public class MyAspect {
        /**
         * JoinPoint 能獲取目標(biāo)方法的一些基本信息
         * @param joinPoint
         */
        public void myBefore(JoinPoint joinPoint){
            System.out.println("前置通知 : " + joinPoint.getSignature().getName());
        }
        public void myAfterReturning(JoinPoint joinPoint,Object ret){
            System.out.println("后置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret);
        }
        public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
            System.out.println("拋出異常通知 : " + e.getMessage());
        }
        public void myAfter(){
            System.out.println("最終通知");
        }
    }

    ④、AOP配置文件 applicationContext.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:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/aop
                               http://www.springframework.org/schema/aop/spring-aop.xsd
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context.xsd">   
        <!--1、創(chuàng)建目標(biāo)類 -->
        <bean id="userService" class="com.ys.aop.UserServiceImpl"></bean>  
        <!--2、創(chuàng)建切面類(通知)  -->
        <bean id="myAspect" class="com.ys.aop.MyAspect"></bean>
        <!--3、aop編程 
            3.1 導(dǎo)入命名空間
            3.2 使用 <aop:config>進(jìn)行配置
                    proxy-target-class="true" 聲明時(shí)使用cglib代理
                    如果不聲明,Spring 會(huì)自動(dòng)選擇cglib代理還是JDK動(dòng)態(tài)代理
                <aop:pointcut> 切入點(diǎn) ,從目標(biāo)對(duì)象獲得具體方法
                <aop:advisor> 特殊的切面,只有一個(gè)通知 和 一個(gè)切入點(diǎn)
                    advice-ref 通知引用
                    pointcut-ref 切入點(diǎn)引用
            3.3 切入點(diǎn)表達(dá)式
                execution(* com.ys.aop.*.*(..))
                選擇方法         返回值任意   包             類名任意   方法名任意   參數(shù)任意
        -->
        <aop:config>
            <aop:aspect ref="myAspect">
            <!-- 切入點(diǎn)表達(dá)式 -->
            <aop:pointcut expression="execution(* com.ys.aop.*.*(..))" id="myPointCut"/>
            <!-- 3.1 前置通知
                    <aop:before method="" pointcut="" pointcut-ref=""/>
                        method : 通知,及方法名
                        pointcut :切入點(diǎn)表達(dá)式,此表達(dá)式只能當(dāng)前通知使用。
                        pointcut-ref : 切入點(diǎn)引用,可以與其他通知共享切入點(diǎn)。
                    通知方法格式:public void myBefore(JoinPoint joinPoint){
                        參數(shù)1:org.aspectj.lang.JoinPoint  用于描述連接點(diǎn)(目標(biāo)方法),獲得目標(biāo)方法名等
            -->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
            <!-- 3.2后置通知  ,目標(biāo)方法后執(zhí)行,獲得返回值
                    <aop:after-returning method="" pointcut-ref="" returning=""/>
                        returning 通知方法第二個(gè)參數(shù)的名稱
                    通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){
                        參數(shù)1:連接點(diǎn)描述
                        參數(shù)2:類型Object,參數(shù)名 returning="ret" 配置的
            -->
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
            <!-- 3.3 最終通知 -->        
            <aop:after method="myAfter" pointcut-ref="myPointCut"/>  
            </aop:aspect>
        </aop:config>
    </beans>

    ⑤、測(cè)試

    @Test
    public void testAop(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService useService = (UserService) context.getBean("userService");
        useService.addUser();
        useService.deleteUser();
    }

    ⑥、控制臺(tái)打印結(jié)果

    Spring中如何實(shí)現(xiàn)AOP

    上面的例子很簡(jiǎn)單,就是在 UserService 的 addUser()方法和 deleteUser()方法增加前置通知和后置通知,這在實(shí)際操作中很好理解。比如這是和數(shù)據(jù)庫打交道的話,那么我們?cè)赼ddUser() 或者deleteUser() 時(shí),必須要在前面開始事務(wù),操作完畢后提交事務(wù)。下面我們就用注解的方式來配置。

    2、注解實(shí)現(xiàn) AOP

    ①、導(dǎo)入相應(yīng)的 jar 包,以及在 applicationContext.xml 文件中導(dǎo)入相應(yīng)的命名空間。

    Spring中如何實(shí)現(xiàn)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:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/aop
                               http://www.springframework.org/schema/aop/spring-aop.xsd
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context.xsd">   
    </beans>

    ②、注解配置 bean

    xml配置:
    <!--1、創(chuàng)建目標(biāo)類 -->
    <bean id="userService" class="com.ys.aop.UserServiceImpl"></bean>  
    <!--2、創(chuàng)建切面類(通知)  -->
    <bean id="myAspect" class="com.ys.aop.MyAspect"></bean>
    注解配置:

    目標(biāo)類:  

    Spring中如何實(shí)現(xiàn)AOP

    切面類:  

    Spring中如何實(shí)現(xiàn)AOP

    ③、配置掃描注解識(shí)別

    這個(gè)我們?cè)谇懊嬉仓v過,上面配置的注解,Spring 如何才能識(shí)別這些類上添加了注解呢?我們必須告訴他。

    applicationContext.xml 文件中添加如下配置:

    <!-- 配置掃描注解類
            base-package:表示含有注解類的包名。
            如果掃描多個(gè)包,則下面的代碼書寫多行,改變 base-package 里面的內(nèi)容即可!
        -->
        <context:component-scan base-package="com.ys.aop"></context:component-scan>

    ④、注解配置 AOP

    一、我們用xml配置過如下:  

    Spring中如何實(shí)現(xiàn)AOP

    這是告訴 Spring 哪個(gè)是切面類。下面我們用注解配置

    我們?cè)谇忻骖惿咸砑?@Aspect 注解,如下:  

    Spring中如何實(shí)現(xiàn)AOP

    二、如何讓 Spring 認(rèn)識(shí)我們所配置的 AOP 注解?
    光有前面的類注解掃描是不夠的,這里我們要額外配置 AOP 注解識(shí)別。

    我們?cè)?applicationContext.xml 文件中增加如下配置:

    <!--2、確定 aop 注解生效  -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    三、注解配置前置通知

    我們先看 xml 配置前置通知如下:

    <!-- 切入點(diǎn)表達(dá)式 -->
            <aop:pointcut expression="execution(* com.ys.aop.*.*(..))" id="myPointCut"/>
            <!-- 3.1 前置通知
                    <aop:before method="" pointcut="" pointcut-ref=""/>
                        method : 通知,及方法名
                        pointcut :切入點(diǎn)表達(dá)式,此表達(dá)式只能當(dāng)前通知使用。
                        pointcut-ref : 切入點(diǎn)引用,可以與其他通知共享切入點(diǎn)。
                    通知方法格式:public void myBefore(JoinPoint joinPoint){
                        參數(shù)1:org.aspectj.lang.JoinPoint  用于描述連接點(diǎn)(目標(biāo)方法),獲得目標(biāo)方法名等
            -->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>

    那么注解的方式如下:  

    Spring中如何實(shí)現(xiàn)AOP

    四、注解配置后置通知

    xml 配置后置通知:

    <!-- 3.2后置通知  ,目標(biāo)方法后執(zhí)行,獲得返回值
                    <aop:after-returning method="" pointcut-ref="" returning=""/>
                        returning 通知方法第二個(gè)參數(shù)的名稱
                    通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){
                        參數(shù)1:連接點(diǎn)描述
                        參數(shù)2:類型Object,參數(shù)名 returning="ret" 配置的
            -->
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />

    注意看,后置通知有個(gè) returning="ret" 配置,這是用來獲得目標(biāo)方法的返回值的。

    注解配置如下:  

    Spring中如何實(shí)現(xiàn)AOP

    五、測(cè)試
    @Test
        public void testAopAnnotation(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_Annotation.xml");
            UserService useService = (UserService) context.getBean("userService");
            useService.addUser();
            useService.deleteUser();
        }
    六、控制臺(tái)打印結(jié)果  

    Spring中如何實(shí)現(xiàn)AOP

    3、注解改進(jìn)  

    我們可以看前置通知和后置通知的注解配置:  

    Spring中如何實(shí)現(xiàn)AOP

    注意看紅色框住的部分,很顯然這里是重復(fù)的,而且如果我們有多個(gè)通知方法,那就得在每個(gè)方法名都寫上該注解,而且如果包名夠復(fù)雜,也很容易寫錯(cuò)。那么怎么辦呢?

    解決辦法就是聲明公共切入點(diǎn):

    ①、在 切面類 MyAspect.java 中新增一個(gè)切入點(diǎn)方法 myPointCut(),然后在這個(gè)方法上添加@Pointcut 注解

    Spring中如何實(shí)現(xiàn)AOP

    ②、那么前置通知和后置通知,我們可以進(jìn)行如下改寫配置:  

    Spring中如何實(shí)現(xiàn)AOP

    4、總結(jié)

    上面我們只進(jìn)行了前置通知和后置通知的講解,還有比如最終通知、環(huán)繞通知、拋出異常通知等,配置方式都差不多,這里就不進(jìn)行一一講解了。然后我們看一下這些通知的注解:

    @Aspect 聲明切面,修飾切面類,從而獲得 通知。

    通知

    • @Before 前置

    • @AfterReturning 后置

    • @Around 環(huán)繞

    • @AfterThrowing 拋出異常

    • @After 最終

    切入點(diǎn)

    • @PointCut ,修飾方法 private void xxx(){} 之后通過“方法名”獲得切入點(diǎn)引用

    感謝您的閱讀,希望您對(duì)“Spring中如何實(shí)現(xiàn)AOP”這一關(guān)鍵問題有了一定的理解,具體使用情況還需要大家自己動(dòng)手實(shí)驗(yàn)使用過才能領(lǐng)會(huì),快去試試吧,如果想閱讀更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注億速云行業(yè)資訊頻道!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI