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

SpringBoot AOP注解失效問題排查與解決(調(diào)用內(nèi)部方法)

 更新時間:2024年04月02日 10:58:06   作者:園區(qū)阿祖  
這篇文章主要介紹了SpringBoot AOP注解失效問題排查與解決(調(diào)用內(nèi)部方法),文中通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

開發(fā)時,遇到這樣一個問題。項目使用springboot框架,項目中的task基于quartz實(shí)現(xiàn),其中有個BaseTask代碼實(shí)現(xiàn)quartz的Job接口,關(guān)鍵代碼如下:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public abstract class BaseTask implements Job {

    @Override
    public void execute(JobExecutionContext context) {
    	// do something before...
        doTask(taskDto);
        // do something after...
    }
    
    public abstract void doTask(TaskDTO taskDto);
}

項目中的所有task會繼承這個BaseTask,并重寫doTask方法,如下:

public class MyTask extends BaseTask {

    @Override
    public void doTask(TaskDTO taskDto) {
        // 在這里實(shí)現(xiàn)你的具體任務(wù)邏輯
        System.out.println("執(zhí)行MyTask的doTask方法");
    }
}

這時候因為做的業(yè)務(wù)會涉及很多類似的數(shù)據(jù)同步,有很多task,且都需要做如下操作:

1.實(shí)現(xiàn)并發(fā)鎖控制

2.讀取上次同步時間進(jìn)行增量同步操作

3.插入taskRecord記錄等

這些代碼會極大的冗余和重復(fù),故此想使用AOP的思想,使用注解的方式,將這些操作抽象整合,于是開干:

1.引入springboot的aop依賴

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

2.寫注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TaskRecord {

}

3.使用@Aspect寫切面

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TaskAspect {

    @Pointcut("execution(* com.example.task.*.doTask(..)) && @annotation(TaskRecord)")
    public void pointcut() {}

    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs(); // 獲取方法的參數(shù)
        System.out.println("方法參數(shù): " + args[0]);
    }
}

4.在MyTask類的方法里加上注解

public class MyTask extends BaseTask {

    @Override
    @TaskRecord
    public void doTask(TaskDTO taskDto) {
        // 在這里實(shí)現(xiàn)你的具體任務(wù)邏輯
        System.out.println("執(zhí)行MyTask的doTask方法");
    }
}

一番操作下來行云流水,心里默想:老子cv代碼天下第一,肯定沒問題。打斷點(diǎn)debug調(diào)試,發(fā)現(xiàn)問題出現(xiàn),根本進(jìn)不了@Before方法里啊

于是排查問題,百度chatgpt問了n²+1天,在試過如下方法如:

1.將MyTask,BaseTask加上@Component將bean加載到spring容器內(nèi)

2.啟動類增加@EnableAspectJAutoProxy注解(實(shí)際SpringBoot默認(rèn)自動配置AOP的)

3.聯(lián)想是否跟CGLIB或JDK動態(tài)代理有關(guān)

一系列操作,發(fā)現(xiàn)屢戰(zhàn)屢敗,于是擱置了數(shù)天,今天又心血來潮試了下,換了個思路去思考,查詢AOP失效的幾個場景,總結(jié)如下:

1.內(nèi)部方法調(diào)用:AOP通常不會攔截同一個類內(nèi)部的方法調(diào)用。如果一個被代理的方法調(diào)用了另一個被代理的方法,那么只有外部調(diào)用的方法會觸發(fā)AOP。

2.AOP配置問題:AOP切入點(diǎn)配置不正確,切入點(diǎn)表達(dá)式可能沒有正確應(yīng)用到目標(biāo)bean。

3.直接實(shí)例化對象:如直接使用new關(guān)鍵字創(chuàng)建了一個對象實(shí)例,AOP將無法攔截此對象的方法調(diào)用。需要通過Spring容器獲取對象,讓Spring負(fù)責(zé)bean的實(shí)例化,才能讓AOP生效。

嗯?好像有點(diǎn)思路了,很符合1的情況,于是在某個controller寫了個請求并加上注解,發(fā)現(xiàn)可以進(jìn)入,但是如果寫一個內(nèi)部方法,在內(nèi)部方法上加注解,請求的方法再去調(diào)用則會失效,如下:

這樣是ok的

 	@RequestMapping("/test")
    @ResponseBody
     @TaskRecord
    public String test(@RequestBody TestRequest request) {
        test1(request);
        return "執(zhí)行成功!";
    }

這樣是not ok的

 	@RequestMapping("/test")
    @ResponseBody
    public String test(@RequestBody TestRequest request) {
        test1(request);
        return "執(zhí)行成功!";
    }
    
    @TaskRecord
    public void test1(TestRequest request) {
        System.out.println(request.toString());
    }

所以思路就是在執(zhí)行內(nèi)部的doTask方法時,不能直接調(diào)用,需要通過代理類去調(diào)用才能讓AOP切面生效,改造如下:

1.新增接口

public interface JobCommonService {

    void doTaskNew(TaskDTO taskDTO) throws Exception;
}

2.BaseTask改造,不直接調(diào)用doTask

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public abstract class BaseTask implements Job {

    @Override
    public void execute(JobExecutionContext context) {
    	// do something before...
    	// 這是自建的一個spring容器工具類,可以獲取容器里的bean
    	JobCommonService jobService = SpringContextUtil.getBean(JobCommonService.class);
        jobService.doTaskNew(taskDTO);
        // do something after...
    }
    
    public abstract void doTask(TaskDTO taskDto);
}

3.具體task改造,實(shí)現(xiàn)JobCommon接口重寫doTaskNew方法

@Component
public class MyTask extends BaseTask implements JobCommonService{

    @Override
    public void doTask(TaskDTO taskDto) {
    	return;
    }

	@Override
    @TaskRecord
    public void doTaskNew(TaskDTO taskDTO) {
        // do something...
        return;
    }
}

至此打完收工,成功進(jìn)入@Before方法,下面關(guān)掉所有查詢的窗口,可以愉快的進(jìn)行其他操作啦!

到此這篇關(guān)于SpringBoot AOP注解失效問題排查與解決(調(diào)用內(nèi)部方法)的文章就介紹到這了,更多相關(guān)SpringBoot AOP注解失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • idea指定啟動參數(shù)、環(huán)境變量的過程

    idea指定啟動參數(shù)、環(huán)境變量的過程

    這篇文章主要介紹了idea指定啟動參數(shù)、環(huán)境變量的操作過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • IDEA解決src和resource下創(chuàng)建多級目錄的操作

    IDEA解決src和resource下創(chuàng)建多級目錄的操作

    這篇文章主要介紹了IDEA解決src和resource下創(chuàng)建多級目錄的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java獲取本機(jī)IP地址的方法代碼示例(內(nèi)網(wǎng)、公網(wǎng))

    Java獲取本機(jī)IP地址的方法代碼示例(內(nèi)網(wǎng)、公網(wǎng))

    在IT領(lǐng)域獲取本機(jī)IP地址是一項基礎(chǔ)但重要的任務(wù),特別是在網(wǎng)絡(luò)編程、遠(yuǎn)程協(xié)作和設(shè)備通信中,這篇文章主要給大家介紹了關(guān)于Java獲取本機(jī)IP地址的方法(內(nèi)網(wǎng)、公網(wǎng)),需要的朋友可以參考下
    2024-07-07
  • Javadoc 具體使用詳解

    Javadoc 具體使用詳解

    這篇文章主要介紹了Javadoc 具體使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 淺談Spring Security 對于靜態(tài)資源的攔截與放行

    淺談Spring Security 對于靜態(tài)資源的攔截與放行

    這篇文章主要介紹了淺談Spring Security 對于靜態(tài)資源的攔截與放行,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • java中接口冪等性的五種實(shí)現(xiàn)方法

    java中接口冪等性的五種實(shí)現(xiàn)方法

    在java中保證接口冪等性,即多次調(diào)用同一接口產(chǎn)生與單次調(diào)用相同的結(jié)果,不會引發(fā)副作用,需要結(jié)合業(yè)務(wù)場景選擇合適的方案,下面就來介紹五種實(shí)現(xiàn)方法,感興趣的可以了解一下
    2025-09-09
  • Java在Word中添加多行圖片水印

    Java在Word中添加多行圖片水印

    這篇文章主要介紹了Java在Word中添加多行圖片,圖文講解的很清晰,有對于這方面不懂得同學(xué)可以跟著研究下
    2021-02-02
  • IDEA Maven提示:未解析的依賴項的問題及解決

    IDEA Maven提示:未解析的依賴項的問題及解決

    這篇文章主要介紹了IDEA Maven提示:未解析的依賴項的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • MyBatis查詢返回Map示例代碼

    MyBatis查詢返回Map示例代碼

    這篇文章主要給大家介紹了關(guān)于MyBatis查詢返回Map的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • 前端dist包放到后端springboot項目下一起打包圖文教程

    前端dist包放到后端springboot項目下一起打包圖文教程

    這篇文章主要介紹了前端dist包放到后端springboot項目下一起打包的相關(guān)資料,具體步驟包括前端打包、將前端文件復(fù)制到后端項目的static目錄、后端打包、驗證部署成功等,需要的朋友可以參考下
    2025-01-01

最新評論

文登市| 穆棱市| 凌源市| 浦北县| 伊宁市| 铁岭市| 莎车县| 察隅县| 南岸区| 靖江市| 辉南县| 宁国市| 吉安县| 墨江| 北辰区| 乌拉特中旗| 宁武县| 大连市| 荣成市| 滨州市| 土默特左旗| 津市市| 丰原市| 浦东新区| 阳原县| 大安市| 乌拉特中旗| 东宁县| 当阳市| 泸州市| 鹤岗市| 扶绥县| 桃江县| 平湖市| 隆林| 巴彦淖尔市| 千阳县| 龙胜| 丽江市| 沙洋县| 定陶县|