日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

SpringBoot Aop 詳解和多種使用場(chǎng)景解析

瀏覽:167日期:2023-02-20 10:25:03
前言

aop面向切面編程,是編程中一個(gè)很重要的思想本篇文章主要介紹的是SpringBoot切面Aop的使用和案例

什么是aop

AOP(Aspect OrientedProgramming):面向切面編程,面向切面編程(也叫面向方面編程),是目前軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中的一個(gè)重要內(nèi)容。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。

使用場(chǎng)景

利用AOP可以對(duì)我們邊緣業(yè)務(wù)進(jìn)行隔離,降低無關(guān)業(yè)務(wù)邏輯耦合性。提高程序的可重用性,同時(shí)提高了開發(fā)的效率。一般用于日志記錄,性能統(tǒng)計(jì),安全控制,權(quán)限管理,事務(wù)處理,異常處理,資源池管理。使用場(chǎng)景

為什么需要面向切面編程

面向?qū)ο缶幊蹋∣OP)的好處是顯而易見的,缺點(diǎn)也同樣明顯。當(dāng)需要為多個(gè)不具有繼承關(guān)系的對(duì)象添加一個(gè)公共的方法的時(shí)候,例如日志記錄、性能監(jiān)控等,如果采用面向?qū)ο缶幊痰姆椒ǎ枰诿總€(gè)對(duì)象里面都添加相同的方法,這樣就產(chǎn)生了較大的重復(fù)工作量和大量的重復(fù)代碼,不利于維護(hù)。面向切面編程(AOP)是面向?qū)ο缶幊痰难a(bǔ)充,簡(jiǎn)單來說就是統(tǒng)一處理某一“切面”的問題的編程思想。如果使用AOP的方式進(jìn)行日志的記錄和處理,所有的日志代碼都集中于一處,不需要再每個(gè)方法里面都去添加,極大減少了重復(fù)代碼。

技術(shù)要點(diǎn) 通知(Advice)包含了需要用于多個(gè)應(yīng)用對(duì)象的橫切行為,完全聽不懂,沒關(guān)系,通俗一點(diǎn)說就是定義了“什么時(shí)候”和“做什么”。 連接點(diǎn)(Join Point)是程序執(zhí)行過程中能夠應(yīng)用通知的所有點(diǎn)。 切點(diǎn)(Poincut)是定義了在“什么地方”進(jìn)行切入,哪些連接點(diǎn)會(huì)得到通知。顯然,切點(diǎn)一定是連接點(diǎn)。 切面(Aspect)是通知和切點(diǎn)的結(jié)合。通知和切點(diǎn)共同定義了切面的全部?jī)?nèi)容——是什么,何時(shí),何地完成功能。 引入(Introduction)允許我們向現(xiàn)有的類中添加新方法或者屬性。 織入(Weaving)是把切面應(yīng)用到目標(biāo)對(duì)象并創(chuàng)建新的代理對(duì)象的過程,分為編譯期織入、類加載期織入和運(yùn)行期織入。整合使用導(dǎo)入依賴

在springboot中使用aop要導(dǎo)aop依賴

<!--aop 切面--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>

注意這里版本依賴于spring-boot-start-parent父pom中的spring-boot-dependencies

編寫攔截的bean

這里我們定義一個(gè)controller用于攔截所有請(qǐng)求的記錄

@RestControllerpublic class AopController { @RequestMapping('/hello') public String sayHello(){System.out.println('hello');return 'hello'; }}定義切面

SpringBoot在使用切面的時(shí)候采用@Aspect注解對(duì)POJO進(jìn)行標(biāo)注,該注解表明該類不僅僅是一個(gè)POJO,還是一個(gè)切面容器

定義切點(diǎn)

切點(diǎn)是通過@Pointcut注解和切點(diǎn)表達(dá)式定義的。

@Pointcut注解可以在一個(gè)切面內(nèi)定義可重用的切點(diǎn)。

由于Spring切面粒度最小是達(dá)到方法級(jí)別,而execution表達(dá)式可以用于明確指定方法返回類型,類名,方法名和參數(shù)名等與方法相關(guān)的部件,并且實(shí)際中,大部分需要使用AOP的業(yè)務(wù)場(chǎng)景也只需要達(dá)到方法級(jí)別即可,因而execution表達(dá)式的使用是最為廣泛的。如圖是execution表達(dá)式的語法:

SpringBoot Aop 詳解和多種使用場(chǎng)景解析

execution表示在方法執(zhí)行的時(shí)候觸發(fā)。以“”開頭,表明方法返回值類型為任意類型。然后是全限定的類名和方法名,“”可以表示任意類和任意方法。對(duì)于方法參數(shù)列表,可以使用“..”表示參數(shù)為任意類型。如果需要多個(gè)表達(dá)式,可以使用“&&”、“||”和“!”完成與、或、非的操作。

定義通知

通知有五種類型,分別是:

前置通知(@Before):在目標(biāo)方法調(diào)用之前調(diào)用通知 后置通知(@After):在目標(biāo)方法完成之后調(diào)用通知 環(huán)繞通知(@Around):在被通知的方法調(diào)用之前和調(diào)用之后執(zhí)行自定義的方法 返回通知(@AfterReturning):在目標(biāo)方法成功執(zhí)行之后調(diào)用通知 異常通知(@AfterThrowing):在目標(biāo)方法拋出異常之后調(diào)用通知

代碼中定義了三種類型的通知,使用@Before注解標(biāo)識(shí)前置通知,打印“beforeAdvice...”,使用@After注解標(biāo)識(shí)后置通知,打印“AfterAdvice...”,使用@Around注解標(biāo)識(shí)環(huán)繞通知,在方法執(zhí)行前和執(zhí)行之后分別打印“before”和“after”。這樣一個(gè)切面就定義好了,代碼如下:

@Aspect@Componentpublic class AopAdvice { @Pointcut('execution (* com.shangguan.aop.controller.*.*(..))') public void test() { } @Before('test()') public void beforeAdvice() {System.out.println('beforeAdvice...'); } @After('test()') public void afterAdvice() {System.out.println('afterAdvice...'); } @Around('test()') public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {System.out.println('before');try { proceedingJoinPoint.proceed();} catch (Throwable t) { t.printStackTrace();}System.out.println('after'); }}

運(yùn)行結(jié)果

SpringBoot Aop 詳解和多種使用場(chǎng)景解析

案例場(chǎng)景

這里我們通過一個(gè)日志記錄場(chǎng)景來完整的使用Aop切面業(yè)務(wù)層只需關(guān)心代碼邏輯實(shí)現(xiàn)而不用關(guān)心請(qǐng)求參數(shù)和響應(yīng)參數(shù)的日志記錄

那么首先我們需要自定義一個(gè)全局日志記錄的切面類GlobalLogAspect

然后在該類添加@Aspect注解,然后在定義一個(gè)公共的切入點(diǎn)(Pointcut),指向需要處理的包,然后在定義一個(gè)前置通知(添加@Before注解),后置通知(添加@AfterReturning)和環(huán)繞通知(添加@Around)方法實(shí)現(xiàn)即可

日志信息類

package cn.soboys.core;import lombok.Data;/** * @author kenx * @version 1.0 * @date 2021/6/18 18:48 * 日志信息 */@Datapublic class LogSubject { /** * 操作描述 */ private String description; /** * 操作用戶 */ private String username; /** * 操作時(shí)間 */ private String startTime; /** * 消耗時(shí)間 */ private String spendTime; /** * URL */ private String url; /** * 請(qǐng)求類型 */ private String method; /** * IP地址 */ private String ip; /** * 請(qǐng)求參數(shù) */ private Object parameter; /** * 請(qǐng)求返回的結(jié)果 */ private Object result; /** * 城市 */ private String city; /** * 請(qǐng)求設(shè)備信息 */ private String device;}全局日志攔截

package cn.soboys.core;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.reflect.MethodSignature;import java.lang.reflect.Method;/** * @author kenx * @version 1.0 * @date 2021/6/18 14:52 * 切面 */public class BaseAspectSupport { public Method resolveMethod(ProceedingJoinPoint point) {MethodSignature signature = (MethodSignature)point.getSignature();Class<?> targetClass = point.getTarget().getClass();Method method = getDeclaredMethod(targetClass, signature.getName(),signature.getMethod().getParameterTypes());if (method == null) { throw new IllegalStateException('無法解析目標(biāo)方法: ' + signature.getMethod().getName());}return method; } private Method getDeclaredMethod(Class<?> clazz, String name, Class<?>... parameterTypes) {try { return clazz.getDeclaredMethod(name, parameterTypes);} catch (NoSuchMethodException e) { Class<?> superClass = clazz.getSuperclass(); if (superClass != null) {return getDeclaredMethod(superClass, name, parameterTypes); }}return null; }}

GlobalLogAspect類

package cn.soboys.core;import cn.hutool.core.date.DateUtil;import cn.hutool.core.date.TimeInterval;import cn.hutool.json.JSONUtil;import cn.soboys.core.utils.HttpContextUtil;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.HttpServletRequest;import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @author kenx * @version 1.0 * @date 2021/6/18 15:22 * 全局日志記錄器 */@Slf4j@Aspect@Componentpublic class GlobalLogAspect extends BaseAspectSupport { /** * 定義切面Pointcut */ @Pointcut('execution(public * cn.soboys.mallapi.controller.*.*(..))') public void log() { } /** * 環(huán)繞通知 * * @param joinPoint * @return */ @Around('log()') public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {LogSubject logSubject = new LogSubject();//記錄時(shí)間定時(shí)器TimeInterval timer = DateUtil.timer(true);//執(zhí)行結(jié)果Object result = joinPoint.proceed();logSubject.setResult(result);//執(zhí)行消耗時(shí)間String endTime = timer.intervalPretty();logSubject.setSpendTime(endTime);//執(zhí)行參數(shù)Method method = resolveMethod(joinPoint);logSubject.setParameter(getParameter(method, joinPoint.getArgs()));HttpServletRequest request = HttpContextUtil.getRequest();// 接口請(qǐng)求時(shí)間logSubject.setStartTime(DateUtil.now());//請(qǐng)求鏈接logSubject.setUrl(request.getRequestURL().toString());//請(qǐng)求方法GET,POST等logSubject.setMethod(request.getMethod());//請(qǐng)求設(shè)備信息logSubject.setDevice(HttpContextUtil.getDevice());//請(qǐng)求地址logSubject.setIp(HttpContextUtil.getIpAddr());//接口描述if (method.isAnnotationPresent(ApiOperation.class)) { ApiOperation apiOperation = method.getAnnotation(ApiOperation.class); logSubject.setDescription(apiOperation.value());}String a = JSONUtil.toJsonPrettyStr(logSubject);log.info(a);return result; } /** * 根據(jù)方法和傳入的參數(shù)獲取請(qǐng)求參數(shù) */ private Object getParameter(Method method, Object[] args) {List<Object> argList = new ArrayList<>();Parameter[] parameters = method.getParameters();Map<String, Object> map = new HashMap<>();for (int i = 0; i < parameters.length; i++) { //將RequestBody注解修飾的參數(shù)作為請(qǐng)求參數(shù) RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); //將RequestParam注解修飾的參數(shù)作為請(qǐng)求參數(shù) RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); String key = parameters[i].getName(); if (requestBody != null) {argList.add(args[i]); } else if (requestParam != null) {map.put(key, args[i]); } else {map.put(key, args[i]); }}if (map.size() > 0) { argList.add(map);}if (argList.size() == 0) { return null;} else if (argList.size() == 1) { return argList.get(0);} else { return argList;} }}

到此這篇關(guān)于SpringBoot Aop 詳解和多種使用場(chǎng)景的文章就介紹到這了,更多相關(guān)SpringBoot Aop使用內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲精品一二三区区别| 久久久免费人体| 久久精品天堂| 免费亚洲一区| 精品三区视频| 欧美日韩在线观看首页| 国产精品原创| 99精品网站| 午夜久久久久| 日本不卡视频一二三区| 久久精品72免费观看| 国产精品欧美一区二区三区不卡 | 日本免费一区二区三区四区| 国产精品亚洲一区二区三区在线观看| av在线最新| 亚洲欧洲午夜| 日韩成人在线看| 蜜臀国产一区| 亚洲精品97| 国产欧美日韩一区二区三区在线| 国产精品白丝久久av网站| 成人在线视频区| 久久av一区二区三区| 国产精品综合| 久久久久久美女精品| 天堂va在线高清一区| 国产一区二区三区四区| 欧美中文一区二区| 欧美亚洲tv| 精品中文一区| 国产精品自拍区| 国产一区欧美| 国产日产一区| 视频一区二区三区在线| 久久91视频| 中文无码日韩欧| 日韩国产欧美一区二区| 日韩国产在线一| 激情六月综合| 久久精品系列| 日韩激情一区二区| 亚洲欧美综合| 97精品一区| 国产福利资源一区| 亚洲一区二区三区中文字幕在线观看| 超碰在线99| 久久精品网址| 蜜桃91丨九色丨蝌蚪91桃色| 亚洲成人国产| 亚洲欧洲美洲av| 国产精品久久国产愉拍| 日韩极品在线观看| 亚久久调教视频| 亚洲精品日韩久久| 视频一区视频二区中文| 欧美精选一区二区三区| 999久久久亚洲| 久久亚洲在线| 国产日本久久| 国产丝袜一区| 久久精品福利| 精品亚洲a∨| 国产精品黑丝在线播放| 国产一区日韩| 成人在线视频免费看| 久久福利毛片| 日韩精品一级中文字幕精品视频免费观看 | 日韩精品五月天| 日韩高清欧美激情| 日韩高清电影免费| 日韩精品久久理论片| 亚洲午夜久久| 国产精品一区二区三区四区在线观看 | 黄色成人91| 日本伊人午夜精品| 日本少妇一区| 国产精品a级| 日韩精品久久理论片| 日韩福利视频导航| 久久精品国产99国产| av资源亚洲| 视频一区在线播放| 国产精品magnet| 成人羞羞在线观看网站| 99国产精品久久久久久久成人热| 日韩高清国产一区在线| 国产成年精品| 四虎精品永久免费| 亚洲精品福利电影| 日韩精品一区二区三区中文在线 | 国产精品一线天粉嫩av| 国产乱码午夜在线视频| 国产亚洲精品久久久久婷婷瑜伽| 欧美中文一区| 欧美午夜精彩| 久久av影院| 在线免费观看亚洲| 久久久久久一区二区| 免费不卡在线视频| av综合电影网站| 欧美自拍一区| 黄色日韩在线| 麻豆成全视频免费观看在线看| 欧美日韩国产探花| 精品视频网站| 蜜臀av一区二区在线免费观看| 成人台湾亚洲精品一区二区| 香蕉久久久久久| 国产在线不卡| 欧美gv在线| 精品国产成人| 国产精品成人一区二区网站软件| 亚洲黄页一区| 国产一区日韩一区| 特黄毛片在线观看| 国产一区二区色噜噜| 欧美精品成人| 欧美日韩一区二区三区在线电影| 亚洲色图国产| 丝袜诱惑制服诱惑色一区在线观看 | 国产人成精品一区二区三| 视频在线观看一区二区三区| 香蕉久久精品| 免费毛片在线不卡| av一区二区高清| 久久中文视频| 免费视频一区三区| 亚洲v在线看| 99综合视频| 视频一区欧美日韩| 日韩av资源网| 欧美国产视频| 欧美精品高清| 蜜桃tv一区二区三区| 亚洲在线免费| 欧美综合精品| 黄色在线观看www| 欧美va天堂| 蜜桃视频免费观看一区| 青草久久视频| 欧美激情日韩| 日本免费久久| 在线亚洲欧美| 青青青国产精品| 国产传媒在线| 91精品电影| 69精品国产久热在线观看| 欧美激情福利| 久久理论电影| 青青草91久久久久久久久| 国产成人精品一区二区免费看京| 亚洲成av在线| 三级欧美在线一区| 久久精品日韩欧美| 日韩天堂av| 国产精久久久| 亚洲一级高清| 久久精品一区| 亚洲最大av| 欧美成人基地 | 国产精品久久久久久模特| 91精品综合| 国产精品v亚洲精品v日韩精品| 日韩精品欧美| 成人一区不卡| 国产欧美日韩精品一区二区免费 | 亚洲免费一区三区| 亚洲va中文在线播放免费| 亚洲我射av| 视频一区中文| 精品久久影院| 国产日韩一区二区三免费高清 | 久久最新视频| 国产a久久精品一区二区三区| 蜜臀精品一区二区三区在线观看| 高清不卡亚洲| 国产一区二区三区不卡视频网站| 欧美在线精品一区| 日本一不卡视频| 亚洲精品福利| 六月丁香综合| 91精品91| 巨乳诱惑日韩免费av| 国产精品毛片一区二区三区| 亚洲国产专区| 午夜影院欧美| 99国产精品久久久久久久 | 播放一区二区| 亚洲精品国产嫩草在线观看| 色爱综合网欧美| 午夜久久中文| 欧美日韩水蜜桃| 午夜久久福利| 免费观看久久久4p| 综合亚洲色图| 日韩不卡视频在线观看| 99久精品视频在线观看视频| 欧美久久久网站| 免费国产亚洲视频| 亚洲色诱最新|