溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring中如何實現AOP

發布時間:2022-01-20 13:44:07 來源:億速云 閱讀:200 作者:小新 欄目:開發技術

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

    1、xml 的方式實現 AOP

    ①、接口 UserService

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

    ②、實現類 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 能獲取目標方法的一些基本信息
         * @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、創建目標類 -->
        <bean id="userService" class="com.ys.aop.UserServiceImpl"></bean>  
        <!--2、創建切面類(通知)  -->
        <bean id="myAspect" class="com.ys.aop.MyAspect"></bean>
        <!--3、aop編程 
            3.1 導入命名空間
            3.2 使用 <aop:config>進行配置
                    proxy-target-class="true" 聲明時使用cglib代理
                    如果不聲明,Spring 會自動選擇cglib代理還是JDK動態代理
                <aop:pointcut> 切入點 ,從目標對象獲得具體方法
                <aop:advisor> 特殊的切面,只有一個通知 和 一個切入點
                    advice-ref 通知引用
                    pointcut-ref 切入點引用
            3.3 切入點表達式
                execution(* com.ys.aop.*.*(..))
                選擇方法         返回值任意   包             類名任意   方法名任意   參數任意
        -->
        <aop:config>
            <aop:aspect ref="myAspect">
            <!-- 切入點表達式 -->
            <aop:pointcut expression="execution(* com.ys.aop.*.*(..))" id="myPointCut"/>
            <!-- 3.1 前置通知
                    <aop:before method="" pointcut="" pointcut-ref=""/>
                        method : 通知,及方法名
                        pointcut :切入點表達式,此表達式只能當前通知使用。
                        pointcut-ref : 切入點引用,可以與其他通知共享切入點。
                    通知方法格式:public void myBefore(JoinPoint joinPoint){
                        參數1:org.aspectj.lang.JoinPoint  用于描述連接點(目標方法),獲得目標方法名等
            -->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
            <!-- 3.2后置通知  ,目標方法后執行,獲得返回值
                    <aop:after-returning method="" pointcut-ref="" returning=""/>
                        returning 通知方法第二個參數的名稱
                    通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){
                        參數1:連接點描述
                        參數2:類型Object,參數名 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>

    ⑤、測試

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

    ⑥、控制臺打印結果

    Spring中如何實現AOP

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

    2、注解實現 AOP

    ①、導入相應的 jar 包,以及在 applicationContext.xml 文件中導入相應的命名空間。

    Spring中如何實現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、創建目標類 -->
    <bean id="userService" class="com.ys.aop.UserServiceImpl"></bean>  
    <!--2、創建切面類(通知)  -->
    <bean id="myAspect" class="com.ys.aop.MyAspect"></bean>
    注解配置:

    目標類:  

    Spring中如何實現AOP

    切面類:  

    Spring中如何實現AOP

    ③、配置掃描注解識別

    這個我們在前面也講過,上面配置的注解,Spring 如何才能識別這些類上添加了注解呢?我們必須告訴他。

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

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

    ④、注解配置 AOP

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

    Spring中如何實現AOP

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

    我們在切面類上添加 @Aspect 注解,如下:  

    Spring中如何實現AOP

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

    我們在 applicationContext.xml 文件中增加如下配置:

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

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

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

    那么注解的方式如下:  

    Spring中如何實現AOP

    四、注解配置后置通知

    xml 配置后置通知:

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

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

    注解配置如下:  

    Spring中如何實現AOP

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

    Spring中如何實現AOP

    3、注解改進  

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

    Spring中如何實現AOP

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

    解決辦法就是聲明公共切入點:

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

    Spring中如何實現AOP

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

    Spring中如何實現AOP

    4、總結

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

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

    通知

    • @Before 前置

    • @AfterReturning 后置

    • @Around 環繞

    • @AfterThrowing 拋出異常

    • @After 最終

    切入點

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

    感謝您的閱讀,希望您對“Spring中如何實現AOP”這一關鍵問題有了一定的理解,具體使用情況還需要大家自己動手實驗使用過才能領會,快去試試吧,如果想閱讀更多相關知識點的文章,歡迎關注億速云行業資訊頻道!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女