最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringAOP四種通知類型+環(huán)繞通知說(shuō)明

 更新時(shí)間:2021年09月07日 09:13:25   作者:晚點(diǎn)喝可樂(lè)z  
這篇文章主要介紹了SpringAOP四種通知類型+環(huán)繞通知說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringAOP的四種通知類型:前置通知、異常通知、后置通知、異常通知

一、四種常見(jiàn)的通知類型

給出 賬戶的業(yè)務(wù)層接口 IAccountService.java,

為了便于演示這四種通知類型,我們就只留下了一個(gè)方法。

public interface IAccountService {
   void saveAccount();
}

給出 賬戶的業(yè)務(wù)層接口的實(shí)現(xiàn)類 AccountServiceImpl.java

public class AccountServiceImpl implements IAccountService{
    @Override
    public void saveAccount() {
        System.out.println("執(zhí)行了保存");
        //int i=1/0;
    }
}

給出一個(gè)日志類, 用于打印日志

public class Logger {
    /**
     * 前置通知
     */
    public  void beforePrintLog(){
        System.out.println("前置通知Logger類中的beforePrintLog方法開(kāi)始記錄日志了。。。");
    }
    /**
     * 后置通知
     */
    public  void afterReturningPrintLog(){
        System.out.println("后置通知Logger類中的afterReturningPrintLog方法開(kāi)始記錄日志了。。。");
    }
    /**
     * 異常通知
     */
    public  void afterThrowingPrintLog(){
        System.out.println("異常通知Logger類中的afterThrowingPrintLog方法開(kāi)始記錄日志了。。。");
    }
    /**
     * 最終通知
     */
    public  void afterPrintLog(){
        System.out.println("最終通知Logger類中的afterPrintLog方法開(kāi)始記錄日志了。。。");
    }
}

給出配置信息bean.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: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">
    <!-- 配置srping的Ioc,把service對(duì)象配置進(jìn)來(lái)-->
    <bean id="accountService" class="service.AccountServiceImpl"></bean>
    <!-- 配置Logger類 -->
    <bean id="logger" class="utils.Logger"></bean>
    <!--配置AOP-->
    <aop:config>
      <!--配置切入點(diǎn)表達(dá)式 -->
        <aop:pointcut id="pt1" expression="execution(* service.AccountServiceImpl.saveAccount())"></aop:pointcut>
        <!--配置切面 -->
        <aop:aspect id="logAdvice" ref="logger">
            <!-- 配置前置通知:在切入點(diǎn)方法執(zhí)行之前執(zhí)行-->
            <aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>
            <!-- 配置后置通知:在切入點(diǎn)方法正常執(zhí)行之后值-->
            <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>
            <!-- 配置異常通知:在切入點(diǎn)方法執(zhí)行產(chǎn)生異常之后執(zhí)行-->
            <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
            <!-- 配置最終通知:無(wú)論切入點(diǎn)方法是否正常執(zhí)行它都會(huì)在其后面執(zhí)行-->
            <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
            
        </aop:aspect>
    </aop:config>
</beans>

注意

1)異常通知和后置通知永遠(yuǎn)只能執(zhí)行一個(gè)

2)配置切入點(diǎn)表達(dá)式

此標(biāo)簽寫(xiě)在aop:aspect標(biāo)簽內(nèi)部只能當(dāng)前切面使用。

它還可以寫(xiě)在aop:aspect外面,此時(shí)就變成了所有切面可用

給出Test類

public class AOPTest {
    public static void main(String[] args) {
        //1.獲取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.獲取對(duì)象
        IAccountService as = (IAccountService)ac.getBean("accountService");
        //3.執(zhí)行方法
       as.saveAccount();
    }
}

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

在這里插入圖片描述

當(dāng)我們放開(kāi)AccountServiceImpl類中我們故意制造的異常 int i=1/0;時(shí):

在這里插入圖片描述

二、環(huán)繞通知

環(huán)繞通知,只需要稍稍微改變上面例子的兩點(diǎn)即可

1、改動(dòng)日志類 Logger.java

public class Logger {
    public Object aroundPringLog(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try{
            Object[] args = pjp.getArgs();//得到方法執(zhí)行所需的參數(shù)
            System.out.println("Logger類中的aroundPringLog方法開(kāi)始記錄日志了。。。前置");
            rtValue = pjp.proceed(args);//明確調(diào)用業(yè)務(wù)層方法(切入點(diǎn)方法)
            System.out.println("Logger類中的aroundPringLog方法開(kāi)始記錄日志了。。。后置");
            return rtValue;
        }catch (Throwable t){
            System.out.println("Logger類中的aroundPringLog方法開(kāi)始記錄日志了。。。異常");
            throw new RuntimeException(t);
        }finally {
            System.out.println("Logger類中的aroundPringLog方法開(kāi)始記錄日志了。。。最終");
        }
    }
}

注意:pjp.proceed(args)會(huì)報(bào)異常,必須用 Throwable t,因?yàn)镋xception攔不住它

2、改動(dòng)配置文件

<?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: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">
    <!-- 配置srping的Ioc,把service對(duì)象配置進(jìn)來(lái)-->
    <bean id="accountService" class="service.AccountServiceImpl"></bean>
    <!-- 配置Logger類 -->
    <bean id="logger" class="utils.Logger"></bean>
    <!--配置AOP-->
    <aop:config>
    	<!--配置切入點(diǎn)表達(dá)式 -->
        <aop:pointcut id="pt1" expression="execution(* service.AccountServiceImpl.saveAccount())"></aop:pointcut>
        <!--配置切面 -->
        <aop:aspect id="logAdvice" ref="logger">
            <!-- 配置環(huán)繞通知 詳細(xì)的注釋請(qǐng)看Logger類中-->
            <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

分析

  • spring中的環(huán)繞通知是spring框架為我們提供的一種可以在代碼中手動(dòng)控制增強(qiáng)方法何時(shí)執(zhí)行的方式。
  • Spring框架為我們提供了一個(gè)接口:ProceedingJoinPoint。該接口有一個(gè)方法proceed(),此方法就相當(dāng)于明確調(diào)用切入點(diǎn)方法。該接口可以作為環(huán)繞通知的方法參數(shù),在程序執(zhí)行時(shí),spring框架會(huì)為我們提供該接口的實(shí)現(xiàn)類供我們使用。

AOP機(jī)制之環(huán)繞通知的見(jiàn)解

我們都知道,AOP機(jī)制的核心是在不修改源碼的基礎(chǔ)上對(duì)業(yè)務(wù)層方法的增強(qiáng)。

其中有五個(gè)通知類型

  • 1、前置通知:在切入點(diǎn)方法之前執(zhí)行
  • 2、后置通知:在切入點(diǎn)方法之后通知
  • 3、異常通知:在執(zhí)行切入點(diǎn)方法過(guò)程中出現(xiàn)異常后執(zhí)行(因此異常通知和后置通知只能執(zhí)行一個(gè))
  • 4、最終通知:無(wú)論切入點(diǎn)方法是否正常執(zhí)行它都會(huì)執(zhí)行
  • 5、環(huán)繞通知: 當(dāng)配置環(huán)繞通知之后,在環(huán)繞通知里面必須要明確調(diào)用業(yè)務(wù)層的方法,如果不調(diào)用,就會(huì)出現(xiàn)只出現(xiàn)通知,而不執(zhí)行方法。其中原理和動(dòng)態(tài)代理是一樣的,代碼如下。
public AccountService getAccountService() {
        return (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Object rtValue=null;
                try {
                    //1、開(kāi)啟事務(wù)
                    txManager.beginTransaction();
                    //2、執(zhí)行操作,整個(gè)過(guò)程像對(duì)每個(gè)方法進(jìn)行了包裝,并返回新的accountService對(duì)象
                    rtValue=method.invoke(accountService,objects);
                    //3、提交事務(wù)
                    txManager.commit();
                    //4、返回結(jié)果
                    return rtValue;
                }catch (Exception e){
                    //5、回滾事務(wù)
                    txManager.rollback();
                    throw new RuntimeException(e);
                }finally {
                    //6、釋放連接
                    txManager.release();
                }
            }
        });
    }

如果不明確調(diào)用業(yè)務(wù)層方法,就像一個(gè)畫(huà)皮,沒(méi)有發(fā)揮本質(zhì)的作用。

除此之外,我認(rèn)為環(huán)繞通知可以代替其他的四個(gè)通知,

public Object aroundPrintLog(ProceedingJoinPoint pjp){//環(huán)繞通知是不是能夠代替其他的通知
        Object rtvalue=null;
        try {
            /**
             *這里的一切都是為都是給業(yè)務(wù)層方法進(jìn)行增強(qiáng),例如:把那些方法拿過(guò)來(lái),然后核心的還是rtvalue=pjp.proceed(args),
             *其他的輸出只不過(guò)是為核心的業(yè)務(wù)層方法進(jìn)行修飾
             */
            Object[] args=pjp.getArgs();//得到方法執(zhí)行所需的參數(shù)
            System.out.println("前置通知");
            rtvalue=pjp.proceed(args);//明確調(diào)用業(yè)務(wù)層方法
            System.out.println("后置通知");
            return rtvalue;
        }catch (Throwable e){
            System.out.println("異常通知");
            throw new RuntimeException(e);
        }finally {
            System.out.println("最終通知");
        }
    }

這個(gè)屬于典型的環(huán)繞通知,其中把輸出方法換成相應(yīng)的通知方法就可以(有不同觀點(diǎn)的可以說(shuō)出來(lái)一起討論)。

最后,分享一下我學(xué)這個(gè)知識(shí)的方法。方法增強(qiáng),本質(zhì)上就是對(duì)源碼不修改的情況下進(jìn)行方法的加工。就好像烤羊肉串一樣,其中的核心就是羊肉,就像公司給你的業(yè)務(wù)層方法(這個(gè)是不讓修改的)。在給顧客使用前,收先對(duì)羊肉進(jìn)行刷油、烤、撒料一系列過(guò)程,這一過(guò)程就是我們對(duì)業(yè)務(wù)層方法的增強(qiáng),使業(yè)務(wù)層的功能更加健壯,對(duì)應(yīng)的燒烤也就是更美味。核心的一點(diǎn)就是正確調(diào)用業(yè)務(wù)層的方法,不管在哪類通知中,都能對(duì)業(yè)務(wù)層方法進(jìn)行正確、有效地增強(qiáng)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java?NIO實(shí)現(xiàn)聊天系統(tǒng)

    Java?NIO實(shí)現(xiàn)聊天系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java?NIO實(shí)現(xiàn)聊天系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 淺談javap命令拆解字節(jié)碼文件

    淺談javap命令拆解字節(jié)碼文件

    這篇文章主要介紹了拆解字節(jié)碼文件javap命令,對(duì)反編譯感興趣的同學(xué)可以參考下
    2021-04-04
  • Java 超詳細(xì)圖解集合框架的數(shù)據(jù)結(jié)構(gòu)

    Java 超詳細(xì)圖解集合框架的數(shù)據(jù)結(jié)構(gòu)

    什么是集合框架呢?集合框架是為表示和操作集合而規(guī)定的一種統(tǒng)一的標(biāo)準(zhǔn)的體系結(jié)構(gòu)。最簡(jiǎn)單的集合如數(shù)組、列表和隊(duì)列等,任何集合框架一般包含:對(duì)外的接口、接口的實(shí)現(xiàn)和對(duì)集合運(yùn)算的算法
    2022-04-04
  • Java位集合之BitMap、BitSet和布隆過(guò)濾器示例解析

    Java位集合之BitMap、BitSet和布隆過(guò)濾器示例解析

    這篇文章主要介紹了Java中位集合的基本概念、實(shí)現(xiàn)方法以及應(yīng)用場(chǎng)景,包括Bit-Map、BitSet和BloomFilter,Bit-Map通過(guò)位操作高效地存儲(chǔ)和查詢?cè)貭顟B(tài),文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • spring boot(三)之Spring Boot中Redis的使用

    spring boot(三)之Spring Boot中Redis的使用

    這篇文章主要介紹了spring boot(三)之Spring Boot中Redis的使用,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-05-05
  • JavaWeb請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求包含實(shí)現(xiàn)過(guò)程解析

    JavaWeb請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求包含實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了JavaWeb請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求包含實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 淺析JAVA 循環(huán)結(jié)構(gòu)

    淺析JAVA 循環(huán)結(jié)構(gòu)

    這篇文章主要介紹了JAVA 循環(huán)結(jié)構(gòu)的相關(guān)資料,文中講解的非常細(xì)致,示例代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 利用Java查看進(jìn)程內(nèi)存占用情況的實(shí)現(xiàn)方法

    利用Java查看進(jìn)程內(nèi)存占用情況的實(shí)現(xiàn)方法

    在系統(tǒng)監(jiān)控和性能調(diào)優(yōu)中,了解各個(gè)進(jìn)程的內(nèi)存占用情況是非常重要的一環(huán),通過(guò)查看進(jìn)程內(nèi)存使用情況,開(kāi)發(fā)者和運(yùn)維人員可以及時(shí)發(fā)現(xiàn)異常進(jìn)程、資源瓶頸和內(nèi)存泄漏問(wèn)題,本項(xiàng)目旨在使用 Java 編寫(xiě)一個(gè)簡(jiǎn)單的程序,通過(guò)調(diào)用操作系統(tǒng)的命令來(lái)獲取系統(tǒng)中各個(gè)進(jìn)程的內(nèi)存使用情況
    2025-03-03
  • SpringBoot項(xiàng)目yml配置文件不自動(dòng)提示解決方案

    SpringBoot項(xiàng)目yml配置文件不自動(dòng)提示解決方案

    這篇文章主要介紹了SpringBoot項(xiàng)目配置文件.yaml/.yml文件編寫(xiě)時(shí)沒(méi)有自動(dòng)提示的解決方案,文章通過(guò)圖文結(jié)合的方式給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • springboot項(xiàng)目中PropertySource如何讀取yaml配置文件

    springboot項(xiàng)目中PropertySource如何讀取yaml配置文件

    這篇文章主要介紹了springboot項(xiàng)目中PropertySource如何讀取yaml配置文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論

宜阳县| 伊宁市| 德兴市| 定兴县| 巨野县| 岳阳县| 汝阳县| 芦溪县| 应城市| 家居| 穆棱市| 正阳县| 威远县| 云龙县| 拉孜县| 张掖市| 沈丘县| 辽宁省| 微山县| 井冈山市| 宣恩县| 临漳县| 苍溪县| 汤原县| 惠水县| 南澳县| 徐水县| 宣城市| 顺平县| 绍兴县| 毕节市| 临江市| 公主岭市| 正宁县| 阿鲁科尔沁旗| 桓台县| 伊金霍洛旗| 隆化县| 通城县| 墨竹工卡县| 荣昌县|