97色伦色在线综合视频,无玛专区,18videosex性欧美黑色,日韩黄色电影免费在线观看,国产精品伦理一区二区三区,在线视频欧美日韩,亚洲欧美在线中文字幕不卡

免費網(wǎng)站個人注冊網(wǎng)站seo李守洪排名大師

鶴壁市浩天電氣有限公司 2026/01/24 06:42:29
免費網(wǎng)站個人注冊,網(wǎng)站seo李守洪排名大師,seo系統(tǒng)培訓(xùn)哪家好,大學(xué)生活動策劃書模板SpringAOP本筆記整合了 AOP 基礎(chǔ)理論、核心概念、進階用法#xff0c;并結(jié)合真實登錄日志記錄案例#xff0c;采用“由外到內(nèi)、逐步迭代”的開發(fā)思路#xff0c;幫助理解如何從零構(gòu)建一個健壯的 AOP 切面。AOP Aspect Oriented Programming#xff08;面向切面編程、面向方…SpringAOP本筆記整合了 AOP 基礎(chǔ)理論、核心概念、進階用法并結(jié)合真實登錄日志記錄案例采用“由外到內(nèi)、逐步迭代”的開發(fā)思路幫助理解如何從零構(gòu)建一個健壯的 AOP 切面。AOPAspect Oriented Programming面向切面編程、面向方面編程可簡單理解為面向特定方法編程典型場景部分業(yè)務(wù)方法運行較慢需統(tǒng)計每個方法的執(zhí)行耗時優(yōu)勢減少重復(fù)代碼代碼無侵入不修改原有業(yè)務(wù)邏輯提高開發(fā)效率維護方便AOP 基礎(chǔ)AOP 快速入門需求統(tǒng)計所有業(yè)務(wù)層方法的執(zhí)行耗時步驟導(dǎo)入依賴在pom.xml中引入 Spring AOP 依賴Spring Boot Web 默認(rèn)包含編寫 AOP 程序針對特定方法按需編程// AOP 程序 - RecordTimeAspectAspectComponentpublicclassRecordTimeAspect{Around(execution(* com.itheima.service.impl.*.*(..)))publicObjectrecordTime(ProceedingJoinPointpjp)throwsThrowable{// 1. 記錄方法運行的開始時間longbeginSystem.currentTimeMillis();// 2. 執(zhí)行原始的方法Objectresultpjp.proceed();// 3. 記錄方法運行的結(jié)束時間計算執(zhí)行耗時longendSystem.currentTimeMillis();log.info(方法 {} 執(zhí)行耗時: {}ms,pjp.getSignature(),end-begin);returnresult;}}常見應(yīng)用場景記錄系統(tǒng)操作日志事務(wù)管理權(quán)限控制性能監(jiān)控異常統(tǒng)一處理AOP 核心概念概念說明連接點JoinPoint可被 AOP 控制的方法含執(zhí)行時上下文信息通知Advice重復(fù)的共性邏輯最終體現(xiàn)為一個方法切入點Pointcut匹配連接點的條件決定哪些方法會被增強切面Aspect描述“通知”與“切入點”的關(guān)系用Aspect聲明目標(biāo)對象Target被通知所應(yīng)用的對象即原始業(yè)務(wù)對象AOP 執(zhí)行流程Spring 使用動態(tài)代理技術(shù)創(chuàng)建代理對象代理對象在目標(biāo)方法前后插入通知邏輯實現(xiàn)“頭尾原方法”結(jié)構(gòu)AOP 進階通知類型按執(zhí)行時機分類類型注解執(zhí)行時機特點使用頻率環(huán)繞通知Around目標(biāo)方法前 后可控制是否執(zhí)行原方法可獲取返回值/異常?????最常用前置通知Before目標(biāo)方法執(zhí)行前無法阻止方法執(zhí)行??后置通知After目標(biāo)方法執(zhí)行后無論成功/異常類似 finally??返回后通知AfterReturning目標(biāo)方法成功返回后異常時不執(zhí)行?異常后通知AfterThrowing目標(biāo)方法拋出異常后僅異常時執(zhí)行?重點Around是唯一能控制原方法是否執(zhí)行的通知類型對于Around必須使用ProceedingJoinPoint并調(diào)用proceed()否則原方法不會執(zhí)行切點表達式Pointcut Expression作用描述哪些方法需要被增強常見形式1.execution(...)—— 按方法簽名匹配語法execution(訪問修飾符? 返回值 包名.類名.?方法名(參數(shù)) throws 異常?)通配符*匹配單個任意符號如*Service、save*、String參數(shù)等..匹配任意層級包或任意數(shù)量/類型參數(shù)示例// 匹配 service.impl 下所有類的所有方法execution(*com.itheima.service.impl.*.*(..))// 匹配所有以 update 開頭的方法execution(*com.itheima..*.*update*(..))2.annotation(...)—— 按注解匹配推薦用于業(yè)務(wù)標(biāo)記// 匹配所有標(biāo)注了 LoginIn 的方法annotation(com.rudyj.anno.LoginIn)?最佳實踐優(yōu)先使用自定義注解方式解耦且靈活避免過度使用..縮小匹配范圍提升性能方法命名規(guī)范如login,saveXxx便于表達式匹配切點復(fù)用PointcutPointcut(annotation(com.rudyj.anno.LoginIn))publicvoidpt(){}// public 可被其他切面引用Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{// ...}??注意若在Around中使用了額外參數(shù)如LoginIn anno則pt()方法也必須聲明對應(yīng)參數(shù)否則報錯Unbound pointcut parameter xxx通知執(zhí)行順序多個切面匹配同一方法時默認(rèn)按切面類名的字母順序執(zhí)行可用Order(n)顯式控制數(shù)字越小優(yōu)先級越高前置階段Order(1)先于Order(2)后置階段Order(1)后于Order(2)類似棧Order(5)AspectComponentpublicclassRecordTimeAspect{...}連接點信息獲取JoinPoint用于Before/After等通知可獲取getArgs()方法參數(shù)getSignature()方法簽名含類名、方法名getTarget()目標(biāo)對象ProceedingJoinPointJoinPoint的子類僅用于Around額外提供proceed()執(zhí)行原方法proceed(Object[])傳入新參數(shù)執(zhí)行原方法AOP 實戰(zhàn)案例登錄日志記錄需求記錄用戶登錄行為到數(shù)據(jù)庫包含用戶名、是否成功、JWT、耗時等。數(shù)據(jù)庫表結(jié)構(gòu)-- 登錄日志表CREATETABLEemp_login_log(idINTUNSIGNEDPRIMARYKEYAUTO_INCREMENTCOMMENTID,usernameVARCHAR(20)COMMENT用戶名,passwordVARCHAR(32)COMMENT密碼脫敏存儲,login_timeDATETIMECOMMENT登錄時間,is_successTINYINTUNSIGNEDCOMMENT是否成功, 1:成功, 0:失敗,jwtVARCHAR(1000)COMMENTJWT令牌,cost_timeBIGINTUNSIGNEDCOMMENT耗時, 單位:ms)COMMENT登錄日志表;實體類DataNoArgsConstructorAllArgsConstructorpublicclassEmpLoginLog{privateIntegerid;privateStringusername;privateStringpassword;// 注意生產(chǎn)環(huán)境不應(yīng)存明文privateLocalDateTimeloginTime;privateShortisSuccess;// 1:成功, 0:失敗privateStringjwt;privateLongcostTime;}控制器已存在RestControllerpublicclassLoginController{AutowiredprivateEmpServiceempService;LoginInPostMapping(/login)publicResultlogin(RequestBodyEmpemp){LoginInfologinInfoempService.login(emp);if(loginInfonull){CurrentHolder.setJwt();returnResult.error(用戶名或密碼錯誤);}CurrentHolder.setJwt(loginInfo.getToken());returnResult.success(loginInfo);}} 由外到內(nèi)五步構(gòu)建登錄日志 AOP開發(fā)哲學(xué)每一步只解決一個問題驗證通過后再進入下一步。第 0 步前提準(zhǔn)備已有? 自定義注解LoginIn已定義? Controller 方法已加LoginIn?EmpLoginLog實體 OperateLoginMapper.insert()已實現(xiàn)? 項目能正常啟動登錄接口可調(diào)用 Step 1讓 AOP “跑起來” —— 最小可行切面目標(biāo)確認(rèn) AOP 能攔截到/login方法。AspectComponentpublicclassOperateLoginAspect{Pointcut(annotation(com.rudyj.anno.LoginIn))publicvoidpt(){}Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{System.out.println(? AOP 攔截成功方法: joinPoint.getSignature().getName());returnjoinPoint.proceed();// 必須調(diào)用 proceed()}}?驗證調(diào)用/login看控制臺是否打印日志。? 若未打印檢查Component是否被掃描、Spring Boot 是否啟用 AOP默認(rèn)開啟。 Step 2提取方法參數(shù)用戶名、密碼目標(biāo)從joinPoint.getArgs()中拿到Emp對象。Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{Stringusernamenull,passwordnull;for(Objectarg:joinPoint.getArgs()){if(arginstanceofEmp){Empemp(Emp)arg;usernameemp.getUsername();passwordemp.getPassword();break;}}System.out.println( 用戶名: username);returnjoinPoint.proceed();}?驗證傳{ username: tom, password: 123 }看是否打印tom。? 若為null檢查Emp是否有 getter 方法或參數(shù)是否確實是Emp類型。 Step 3計算耗時 捕獲返回值目標(biāo)記錄執(zhí)行時間并確保異常時也能記錄。Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{// 提取參數(shù)略longstartSystem.currentTimeMillis();Objectresultnull;try{resultjoinPoint.proceed();}finally{longcostSystem.currentTimeMillis()-start;System.out.println(?? 耗時: costms);}returnresult;}?驗證看控制臺是否打印耗時如50ms。finally確保即使登錄失敗拋異常耗時也能記錄。 Step 4判斷登錄是否成功 提取 JWT目標(biāo)從ResultLoginInfo中提取 token。Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{// 提取參數(shù)略longstartSystem.currentTimeMillis();Objectresultnull;ShortisSuccess0;Stringjwtnull;try{resultjoinPoint.proceed();if(resultinstanceofResult){Result?res(Result?)result;// 根據(jù)實際 Result 結(jié)構(gòu)調(diào)整判斷邏輯if(res.getCode()!nullres.getCode()200){isSuccess1;if(res.getData()instanceofLoginInfo){jwt((LoginInfo)res.getData()).getToken();}}}returnresult;}finally{longcostSystem.currentTimeMillis()-start;System.out.println(? 成功: (isSuccess1), JWT: jwt);}}?驗證成功登錄 → 打印true和 token錯誤密碼 → 打印false和null?? 注意根據(jù)你項目的Result實際結(jié)構(gòu)code/msg調(diào)整成功判斷邏輯。 Step 5保存日志到數(shù)據(jù)庫 安全加固目標(biāo)構(gòu)建EmpLoginLog并插入同時避免記錄明文密碼。AutowiredprivateOperateLoginMapperoperateLoginMapper;Around(pt())publicObjectrecordLogin(ProceedingJoinPointjoinPoint)throwsThrowable{// 1. 提取參數(shù)Stringusernamenull;for(Objectarg:joinPoint.getArgs()){if(arginstanceofEmp){Empemp(Emp)arg;usernameemp.getUsername();break;}}// 2. 初始化日志字段LocalDateTimeloginTimeLocalDateTime.now();longstartSystem.currentTimeMillis();Objectresultnull;ShortisSuccess0;Stringjwtnull;// 3. 執(zhí)行原方法并解析結(jié)果try{resultjoinPoint.proceed();if(resultinstanceofResult){Result?res(Result?)result;if(res.getCode()!nullres.getCode()200){isSuccess1;if(res.getData()instanceofLoginInfo){jwt((LoginInfo)res.getData()).getToken();}}}returnresult;}catch(Exceptione){throwe;// 重新拋出異常保證原邏輯不變}finally{// 4. 構(gòu)建日志實體關(guān)鍵密碼脫敏EmpLoginLoglogEntrynewEmpLoginLog();logEntry.setUsername(username);logEntry.setPassword(******);// ?? 絕不記錄明文密碼logEntry.setLoginTime(loginTime);logEntry.setIsSuccess(isSuccess);logEntry.setJwt(jwt);logEntry.setCostTime(System.currentTimeMillis()-start);// 5. 保存日志失敗不影響主流程try{operateLoginMapper.insert(logEntry);}catch(Exceptionex){log.error(? 保存登錄日志失敗,ex);}}}?最終驗證成功登錄 → 查數(shù)據(jù)庫is_success1jwt非空失敗登錄 →is_success0jwtnullpassword字段為******非明文補充說明查漏補缺1. 關(guān)于ThreadLocal與 AOP 的關(guān)系你在LoginController中使用了CurrentHolder.setJwt(...)這是完全獨立于 AOP 的邏輯AOP不需要也不應(yīng)該操作CurrentHolderThreadLocal的清理應(yīng)由Filter 或 Interceptor在請求結(jié)束后完成// TokenFilter 示例try{chain.doFilter(request,response);}finally{CurrentHolder.remove();// 防止內(nèi)存泄漏}2. 安全警告永遠(yuǎn)不要記錄明文密碼即使是開發(fā)/測試環(huán)境也應(yīng)養(yǎng)成習(xí)慣如果業(yè)務(wù)確實需要記錄“密碼特征”如哈希值應(yīng)在 Service 層處理而非 AOP3. 切點參數(shù)綁定錯誤回顧若使用Pointcut(annotation(loginIn))publicvoidpt(LoginInloginIn){}Around(pt(loginIn))publicObjectaround(ProceedingJoinPointpjp,LoginInloginIn){...}→ 必須保證pt()方法參數(shù)名與Around中一致否則編譯報錯Unbound pointcut parameter4. 異常處理原則AOP 中捕獲異常后必須 re-throw否則會吞掉異常導(dǎo)致前端收不到錯誤信息日志保存等輔助操作應(yīng)單獨 try-catch避免影響主流程5. 性能建議AOP 邏輯應(yīng)盡量輕量如異步寫日志若日志量大可考慮使用消息隊列解耦
版權(quán)聲明: 本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請聯(lián)系我們進行投訴反饋,一經(jīng)查實,立即刪除!

上海谷歌推廣鎮(zhèn)江搜索優(yōu)化技巧

上海谷歌推廣,鎮(zhèn)江搜索優(yōu)化技巧,值得關(guān)注的優(yōu)秀設(shè)計作品,網(wǎng)頁設(shè)計培訓(xùn)的課程5步解鎖KH Coder#xff1a;讓文本數(shù)據(jù)開口說話的智能分析工具 【免費下載鏈接】khcoder KH Coder: f

2026/01/22 22:27:01

外包公司做網(wǎng)站深圳公司網(wǎng)站建設(shè)哪里專業(yè)

外包公司做網(wǎng)站,深圳公司網(wǎng)站建設(shè)哪里專業(yè),建設(shè)網(wǎng)站的英語怎么說,找做cad彩拼的網(wǎng)站YOLO鏡像支持多GPU并行訓(xùn)練#xff1f;實測擴展性表現(xiàn) 在工業(yè)質(zhì)檢線上#xff0c;一張高清圖像的缺陷檢測任務(wù)

2026/01/23 06:42:01