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

Spring AOP使用接口方式實(shí)現(xiàn)

 更新時(shí)間:2021年08月25日 15:16:32   作者:summerSunShine  
本文主要介紹了Spring AOP使用接口方式實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

Spring 提供了很多的實(shí)現(xiàn)AOP的方式:Spring 接口方式,schema配置方式和注解.

本文重點(diǎn)介紹Spring使用接口方式實(shí)現(xiàn)AOP. 研究使用接口方式實(shí)現(xiàn)AOP, 以了解為目的. 更好地理解spring使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP. 通常我們使用的更多的是使用注解的方式實(shí)現(xiàn)AOP

下面來看看如何實(shí)現(xiàn)接口方式的AOP

一. 環(huán)境準(zhǔn)備

要在項(xiàng)目中使用Spring AOP 則需要在項(xiàng)目中導(dǎo)入除了spring jar包之外, 還需要引入aspectjrt.jar,aspectjweaver.jar,aopalliance.jar ,spring-aop-3.2.0.M2.jar和cglib.jar

二、Spring接口方式實(shí)現(xiàn)AOP步驟

使用Spring aop接口方式實(shí)現(xiàn)aop, 可以通過自定義通知來供Spring AOP識(shí)別. 常見的自己定義通知有:前置通知, 后置通知, 返回通知, 異常通知, 環(huán)繞通知. 對(duì)應(yīng)實(shí)現(xiàn)的接口是:

  1. 前置通知: MethodBeforeAdvice
  2. 后置通知: AfterAdvice
  3. 返回通知:AfterReturningAdvice
  4. 異常通知:ThrowsAdvice
  5. 環(huán)繞通知:MethodInterceptor

實(shí)現(xiàn)步驟如下:

1. 業(yè)務(wù)接口實(shí)現(xiàn)

package com.lxl.www.aop.interfaceAop;

/**
 * 使用接口方式實(shí)現(xiàn)AOP, 默認(rèn)通過JDK的動(dòng)態(tài)代理來實(shí)現(xiàn). 非接口方式, 使用的是cglib實(shí)現(xiàn)動(dòng)態(tài)代理
 *
 * 業(yè)務(wù)接口類-- 計(jì)算器接口類
 *
 * 定義三個(gè)業(yè)務(wù)邏輯方法
 */
public interface IBaseCalculate {

    int add(int numA, int numB);

    int sub(int numA, int numB);

    int div(int numA, int numB);

    int multi(int numA, int numB);

    int mod(int numA, int numB);

}

2. 業(yè)務(wù)類

package com.lxl.www.aop.interfaceAop;//業(yè)務(wù)類,也是目標(biāo)對(duì)象

import com.lxl.www.aop.Calculate;

import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;

/**
 * 業(yè)務(wù)實(shí)現(xiàn)類 -- 基礎(chǔ)計(jì)算器
 */
@Service
public class BaseCalculate implements IBaseCalculate {

    @Override
    public int add(int numA, int numB) {
        System.out.println("執(zhí)行目標(biāo)方法: add");
        return numA + numB;
    }

    @Override
    public int sub(int numA, int numB) {
        System.out.println("執(zhí)行目標(biāo)方法: sub");
        return numA - numB;
    }

    @Override
    public int multi(int numA, int numB) {
        System.out.println("執(zhí)行目標(biāo)方法: multi");
        return numA * numB;
    }

    @Override
    public int div(int numA, int numB) {
        System.out.println("執(zhí)行目標(biāo)方法: div");
        return numA / numB;
    }

    @Override
    public int mod(int numA, int numB) {
        System.out.println("執(zhí)行目標(biāo)方法: mod");

        int retVal = ((Calculate) AopContext.currentProxy()).add(numA, numB);
        return retVal % numA;
    }
}

3. 通知類

前置通知

package com.lxl.www.aop.interfaceAop;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 定義前置通知
 */
@Component
public class BaseBeforeAdvice implements MethodBeforeAdvice {

    /**
     *
     * @param method 切入的方法
     * @param args 切入方法的參數(shù)
     * @param target 目標(biāo)對(duì)象
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("===========進(jìn)入beforeAdvice()============");

        System.out.println("目標(biāo)對(duì)象:" + target);
        System.out.println("方法名: "+method);

        System.out.println("即將進(jìn)入切入點(diǎn)方法");
    }
}

后置通知

package com.lxl.www.aop.interfaceAop;

import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

public class BaseAfterReturnAdvice implements AfterReturningAdvice {

    /**
     *
     * @param returnValue 切入點(diǎn)執(zhí)行完方法的返回值,但不能修改
     * @param method 切入點(diǎn)方法
     * @param args 切入點(diǎn)方法的參數(shù)數(shù)組
     * @param target 目標(biāo)對(duì)象
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("==========進(jìn)入afterReturning()=========== \n");
        System.out.println("切入點(diǎn)方法執(zhí)行完成");

        System.out.println("后置通知--目標(biāo)對(duì)象:" + target);
        System.out.println("后置通知--方法名: "+method);
        System.out.println("后置通知--方法入?yún)? "+ args.toString());
        System.out.println("后置通知--方法返回值: "+ returnValue);
    }
}

異常通知

package com.lxl.www.aop.interfaceAop;

import org.springframework.aop.ThrowsAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
@Component
public class BaseAfterThrowsAdvice implements ThrowsAdvice {

    /**
     * @param method    可選:切入的方法
     * @param args      可選:切入的方法的參數(shù)
     * @param target    可選:目標(biāo)對(duì)象
     * @param throwable 必填 : 異常子類,出現(xiàn)這個(gè)異常類的子類,則會(huì)進(jìn)入這個(gè)通知。
     */
    public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
        System.out.println("出錯(cuò)啦");
    }
}

環(huán)繞通知

package com.lxl.www.aop.interfaceAop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 環(huán)繞通知
 */
@Component
public class BaseAroundAdvice implements MethodInterceptor {

    /**
     * invocation :連接點(diǎn)
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("===========around環(huán)繞通知方法 開始===========");

        // 調(diào)用目標(biāo)方法之前執(zhí)行的動(dòng)作
        System.out.println("環(huán)繞通知--調(diào)用方法之前: 執(zhí)行");

        // 調(diào)用方法的參數(shù)
        Object[] args = invocation.getArguments();
        // 調(diào)用的方法
        Method method = invocation.getMethod();
        // 獲取目標(biāo)對(duì)象
        Object target = invocation.getThis();
        System.out.println("輸入?yún)?shù):" + args[0] + ";" + method + ";" + target);

        // 執(zhí)行完方法的返回值:調(diào)用proceed()方法,就會(huì)觸發(fā)切入點(diǎn)方法執(zhí)行
        Object returnValue = invocation.proceed();

        System.out.println("環(huán)繞通知--調(diào)用方法之后: 執(zhí)行");
      
        System.out.println("輸出參數(shù):" + args[0] + ";" + method + ";" + target + ";" + returnValue);

        System.out.println("===========around環(huán)繞通知方法  結(jié)束===========");

        return returnValue;
    }
}

4. 自定義切## 點(diǎn)

package com.lxl.www.aop.interfaceAop;

/**
 * 切點(diǎn)
 *
 * 繼承NameMatchMethodPointcut類,來用方法名匹配
 */
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Component
public class Pointcut extends NameMatchMethodPointcut {

    private static final long serialVersionUID = 3990456017285944475L;

    @SuppressWarnings("rawtypes")
    @Override
    public boolean matches(Method method, Class targetClass) {
        // 設(shè)置單個(gè)方法匹配
        this.setMappedName("add");
        // 設(shè)置多個(gè)方法匹配
        String[] methods = { "add", "div" };
      
        //也可以用“ * ” 來做匹配符號(hào)
        // this.setMappedName("get*");
      
        this.setMappedNames(methods);

        return super.matches(method, targetClass);
    }
}

5.配置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:p="http://www.springframework.org/schema/p"
       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-3.0.xsd

          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd

         http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
>

    <!-- ==============================aop配置================================ -->
    <!-- 聲明一個(gè)業(yè)務(wù)類 -->
    <bean id="baseCalculate" class="com.lxl.www.aop.interfaceAop.BaseCalculate"/>

    <!-- 聲明通知類 -->
    <bean id="baseBefore" class="com.lxl.www.aop.interfaceAop.BaseBeforeAdvice"/>
    <bean id="baseAfterReturn" class="com.lxl.www.aop.interfaceAop.BaseAfterReturnAdvice"/>
    <bean id="baseAfterThrows" class="com.lxl.www.aop.interfaceAop.BaseAfterThrowsAdvice"/>
    <bean id="baseAround" class="com.lxl.www.aop.interfaceAop.BaseAroundAdvice"/>

    <!-- 指定切點(diǎn)匹配類 -->
    <bean id="pointcut" class="com.lxl.www.aop.interfaceAop.Pointcut"/>

    <!-- 包裝通知,指定切點(diǎn) -->
    <bean id="matchBeforeAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut">
            <ref bean="pointcut"/>
        </property>
        <property name="advice">
            <ref bean="baseBefore"/>
        </property>
    </bean>

    <!-- 使用ProxyFactoryBean 產(chǎn)生代理對(duì)象 -->
    <bean id="businessProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理對(duì)象所實(shí)現(xiàn)的接口 ,如果有接口可以這樣設(shè)置 -->
        <property name="proxyInterfaces">
            <value>com.lxl.www.aop.interfaceAop.IBaseCalculate</value>
        </property>

        <!-- 設(shè)置目標(biāo)對(duì)象 -->
        <property name="target">
            <ref bean="baseCalculate"/>
        </property>
        <!-- 代理對(duì)象所使用的攔截器 -->
        <property name="interceptorNames">
            <list>
                <value>matchBeforeAdvisor</value>
                <value>baseAfterReturn</value>
                <value>baseAround</value>
            </list>
        </property>
    </bean>
</beans>

6. 方法入口

package com.lxl.www.aop.interfaceAop;

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

public class InterfaceMainClass{

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/aop.xml");
        BaseCalculate calculate = (BaseCalculate) context.getBean("baseCalculate");
        calculate.add(1, 3);
    }
}

三. 分析

各種類型通知的執(zhí)行順序: 前置方法會(huì)在切入點(diǎn)方法之前執(zhí)行,后置會(huì)在切入點(diǎn)方法執(zhí)行之后執(zhí)行,環(huán)繞則會(huì)在切入點(diǎn)方法執(zhí)行前執(zhí)行同事方法結(jié)束也會(huì)執(zhí)行對(duì)應(yīng)的部分。主要是調(diào)用proceed()方法來執(zhí)行切入點(diǎn)方法。來作為環(huán)繞通知前后方法的分水嶺
在xml 配置 businessProxy這個(gè)bean的時(shí)候,ProxyFactoryBean類中指定了,proxyInterfaces參數(shù)。這里把他配置了IBaseCalculate接口。因?yàn)樵陧?xiàng)目開發(fā)過程中,往往業(yè)務(wù)類都會(huì)有對(duì)應(yīng)的接口,以方便利用IOC解耦。但Spring AOP卻也能支持沒有接口的代理。這就是為什么需要導(dǎo)入cglib.jar包了。看過spring的源碼,知道在目標(biāo)切入對(duì)象如果有實(shí)現(xiàn)接口,spring會(huì)默認(rèn)使用jdk動(dòng)態(tài)代理來實(shí)現(xiàn)代理類。如果沒有接口,則會(huì)通過cglib來實(shí)現(xiàn)代理類。

這個(gè)業(yè)務(wù)類現(xiàn)在有 前置通知,后置通知,環(huán)繞三個(gè)通知同時(shí)作用,可能以及更多的通知進(jìn)行作用。那么這些通知的執(zhí)行順序是怎么樣的?就這個(gè)例子而言,同時(shí)實(shí)現(xiàn)了三個(gè)通知。在例 子xml中,則顯示執(zhí)行before通知,然后執(zhí)行around的前處理,執(zhí)行切點(diǎn)方法,再執(zhí)行return處理。最后執(zhí)行around的后處理。經(jīng)過測(cè) 試,知道spring 處理順序是按照xml配置順序依次處理通知,以隊(duì)列的方式存放前通知,以壓棧的方式存放后通知。所以是前通知依次執(zhí)行,后通知到切入點(diǎn)執(zhí)行完之后,從棧里 在后進(jìn)先出的形式把后通知執(zhí)行。

在實(shí)現(xiàn)過程中發(fā)現(xiàn)通知執(zhí)行對(duì)應(yīng)目標(biāo)對(duì)象的整個(gè)類中的方法,如何精確到某個(gè)方法,則需要定義一個(gè)切點(diǎn)匹配的方式:spring提供了方法名匹配或正則方式來匹配。然后通過DefaultPointcutAdvisor來包裝通知,指定切點(diǎn)。

使用接口方式配置起來,可見代碼還是非常的厚重的,定義一個(gè)切面就要定義一個(gè)切面類,然而切面類中,就一個(gè)通知方法,著實(shí)沒有必要。所以Spring提供了,依賴aspectj的schema配置和基于aspectj 注解方式。這兩種方式非常簡(jiǎn)單方便使用,也是項(xiàng)目中普遍的使用方式。

到此這篇關(guān)于Spring AOP使用接口方式實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Spring AOP 接口實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis中的test語(yǔ)句失效處理方式

    mybatis中的test語(yǔ)句失效處理方式

    這篇文章主要介紹了mybatis中的test語(yǔ)句失效處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springboot前后端分離集成CAS單點(diǎn)登錄(統(tǒng)一認(rèn)證)

    springboot前后端分離集成CAS單點(diǎn)登錄(統(tǒng)一認(rèn)證)

    單點(diǎn)登錄是一種身份認(rèn)證和授權(quán)技術(shù),允許用戶在多個(gè)應(yīng)用系統(tǒng)中使用同一套用戶名和密碼進(jìn)行登錄,本文主要介紹了springboot前后端分離集成CAS單點(diǎn)登錄,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-09-09
  • 一篇文章教你如何用多種迭代寫法實(shí)現(xiàn)二叉樹遍歷

    一篇文章教你如何用多種迭代寫法實(shí)現(xiàn)二叉樹遍歷

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)二叉樹遍歷的迭代算法,包括二叉樹的中序遍歷、先序遍歷及后序遍歷等,是非常經(jīng)典的算法,需要的朋友可以參考下
    2021-08-08
  • 聊聊Redis二進(jìn)制數(shù)組Bitmap

    聊聊Redis二進(jìn)制數(shù)組Bitmap

    這篇文章主要介紹了Redis二進(jìn)制數(shù)組Bitmap,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • QueryWrapper中or的使用技巧分享

    QueryWrapper中or的使用技巧分享

    在日常的開發(fā)工作中,處理數(shù)據(jù)庫(kù)查詢是一個(gè)非常常見的任務(wù),尤其是當(dāng)我們需要在復(fù)雜條件下篩選數(shù)據(jù)時(shí),如何編寫高效、簡(jiǎn)潔且可維護(hù)的查詢邏輯顯得尤為重要,本文給大家介紹了QueryWrapper中or的使用技巧,需要的朋友可以參考下
    2024-10-10
  • java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)

    java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)

    這篇文章主要給大家介紹了關(guān)于java對(duì)接微信支付之JSAPI支付(微信公眾號(hào)支付)的相關(guān)資料,微信JSAPI支付是近年來非常流行的一種支付方式,它使用了微信支付的SDK和demo來實(shí)現(xiàn)支付接口的對(duì)接,需要的朋友可以參考下
    2023-07-07
  • 使用Sentinel滑動(dòng)窗口實(shí)現(xiàn)限流和降級(jí)

    使用Sentinel滑動(dòng)窗口實(shí)現(xiàn)限流和降級(jí)

    Sentinel 是一個(gè)開源的高可用性、高擴(kuò)展性的實(shí)時(shí)流量控制框架,它可以用于保護(hù)服務(wù)穩(wěn)定性,防止系統(tǒng)因?yàn)榱髁窟^大而崩潰,這篇文章我們所介紹的是滑動(dòng)窗口,它是 Sentinel 實(shí)現(xiàn)限流和降級(jí)的重要組件之一,感興趣的同學(xué)跟著小編來看看吧
    2023-09-09
  • 再談java回調(diào)函數(shù)

    再談java回調(diào)函數(shù)

    個(gè)人對(duì)于回調(diào)函數(shù)的理解就是回調(diào)函數(shù)就是回頭再調(diào)用的函數(shù),哈哈,下面我們來詳細(xì)探討下回調(diào)函數(shù)。
    2015-07-07
  • Java 程序內(nèi)部是如何執(zhí)行的?

    Java 程序內(nèi)部是如何執(zhí)行的?

    這篇文章主要介紹了Java 程序內(nèi)部是如何執(zhí)行的,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • RabbitMQ修改默認(rèn)密碼的操作步驟

    RabbitMQ修改默認(rèn)密碼的操作步驟

    這篇文章主要給大家介紹了關(guān)于RabbitMQ修改默認(rèn)密碼的操作步驟,在RabbitMQ中默認(rèn)用戶guest的密碼是guest,出于安全考慮,最好不要在生產(chǎn)環(huán)境中使用默認(rèn)用戶和密碼,需要的朋友可以參考下
    2024-11-11

最新評(píng)論

贵阳市| 曲靖市| 油尖旺区| 沙坪坝区| 邹城市| 荣成市| 光山县| 化州市| 衡阳市| 伊金霍洛旗| 商都县| 越西县| 山阴县| 建始县| 塔城市| 炎陵县| 东乡族自治县| 五大连池市| 禄劝| 米林县| 奉新县| 贵州省| 泽普县| 布拖县| 甘德县| 彭泽县| 珠海市| 安顺市| 江川县| 香港| 盈江县| 外汇| 迁西县| 新民市| 连云港市| 资中县| 尼玛县| 隆林| 寿宁县| 闵行区| 桐乡市|