首頁  >  文章  >  Java  >  Springboot怎麼用Aop捕捉註解實現業務非同步執行

Springboot怎麼用Aop捕捉註解實現業務非同步執行

WBOY
WBOY轉載
2023-05-23 19:01:041191瀏覽

一、先說說線程的幾種創建方式(簡要列舉)

1、繼承Thread類,複寫run方法:

public class ExtendsThread extends Thread{
    @Override
    public void run() {
        try{
            System.out.println(Thread.currentThread().getName()+"执行");
        }catch (Exception e){
 
        }
    }
    public static void main(String[] args) {
        new Thread(new ExtendsThread()).start();
    }
}

2、實作Runnable接口,重寫run方法:

public class ImplementsRunnable implements Runnable{
    @Override
    public void run() {
        try{
            System.out.println(Thread.currentThread().getName()+"执行");
        }catch (Exception e){
 
        }
    }
    public static void main(String[] args) {
        new Thread(new ImplementsRunnable()).start();
        //这里还可以使用匿名内部类的写法创建一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"执行");
            }
        },"匿名内部类实现Runnable接口的线程");
    }
}

3、實作Callable接口,使用FutureTask建立執行緒(可以獲得回傳值):

public class CallableAndFuture implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(3000);
        System.out.println(Thread.currentThread().getName()+"执行");
        return "success";
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new CallableAndFuture());
//        futureTask.run();   主线程执行call方法
        new Thread(futureTask).start();
        String result = futureTask.get();
        System.out.println(result);
    }
}

4、使用執行緒池建立執行緒(這裡利用提供的執行緒池框架Executors創建執行緒池):

public class Executor {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"执行");
            }
        });
    }
}

二、再聊一聊spring自帶的@Async註解實現非同步任務的方法

其實很簡單,就是在應用程式啟動類別上打@EnableAsync註解開啟非同步註解的使用,再在業務類別的某個方法上打@Async即可。

@SpringBootApplication
@EnableAsync
public class AopApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopApplication.class, args);
    }
}

業務類別方法(舉例):

   @Async
    public void insertDb(){
        /*service code......*/
        System.out.println("2----->收到请求,写入数据库  ");
    }

三、那麼就來設計一下怎麼使用自訂的註解實現非同步任務

首先我們寫一個註解:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAsync {
    //规定value是异步开关
    boolean value() default false;
}

我們讓註解中的value的值定為布林類型,從而根據它的真假來決定非同步執行緒的建立。

我們將它打在業務類別的方法上:

  @MyAsync(value = true)
    public void deleteDb(){
        /*service code......*/
        System.out.println("delete------>数据删除");
    }

然後我們利用AOP掃描這個註解:

Aspect
@Component
public class AopUtils {
    @Around(value = "@annotation(com.example.aop.Aop异步.MyAsync)")
    public void listenMyAsync(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MyAsync annotation = method.getAnnotation(MyAsync.class);
        boolean value = annotation.value();
        if (value)
            new Thread(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    joinPoint.proceed();
                }
            }).start();
        else
            joinPoint.proceed();
    }
}

我們可以看到利用Around尋找執行的線程中某個含有註解的方法棧,捕捉到之後就可以獲得對應的連接點物件了。

利用可透過連接點物件ProcedJoinPoint的getSignture方法取得簽名,可以將簽名強制轉換成方法簽名MethdSignture類型,從而利用該類型的getMethod方法取得方法本身,接下來就可以取得方法的註解,利用註解的屬性直接取得value的真假,從而決定方法通過的方式是同步的還是非同步的。 (源碼利用到反射機制)。

以上是Springboot怎麼用Aop捕捉註解實現業務非同步執行的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除