Springboot利用Aop捕捉注解實(shí)現(xiàn)業(yè)務(wù)異步執(zhí)行
在開發(fā)過(guò)程中,盡量會(huì)將比較耗時(shí)且并不會(huì)影響請(qǐng)求的響應(yīng)結(jié)果的業(yè)務(wù)放在異步線程池中進(jìn)行處理,那么到時(shí)什么任務(wù)在執(zhí)行的時(shí)候會(huì)創(chuàng)建單獨(dú)的線程進(jìn)行處理呢?我們可以在對(duì)應(yīng)的業(yè)務(wù)方法上打上自定義的注解,再利用AOP去捕捉這個(gè)注解,就可以利用環(huán)繞通知的特性進(jìn)行異步的設(shè)置。
一、先說(shuō)說(shuō)線程的幾種創(chuàng)建方式(簡(jiǎn)要列舉)
1、繼承Thread類,復(fù)寫run方法:
public class ExtendsThread extends Thread{ @Override public void run() { try{ System.out.println(Thread.currentThread().getName()+"執(zhí)行"); }catch (Exception e){ } } public static void main(String[] args) { new Thread(new ExtendsThread()).start(); } }
2、實(shí)現(xiàn)Runnable接口,重寫run方法:
public class ImplementsRunnable implements Runnable{ @Override public void run() { try{ System.out.println(Thread.currentThread().getName()+"執(zhí)行"); }catch (Exception e){ } } public static void main(String[] args) { new Thread(new ImplementsRunnable()).start(); //這里還可以使用匿名內(nèi)部類的寫法創(chuàng)建一個(gè)線程 new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"執(zhí)行"); } },"匿名內(nèi)部類實(shí)現(xiàn)Runnable接口的線程"); } }
3、實(shí)現(xiàn)Callable接口,使用FutureTask創(chuàng)建線程(可以獲得返回值):
public class CallableAndFuture implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"執(zhí)行"); return "success"; } public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<>(new CallableAndFuture()); // futureTask.run(); 主線程執(zhí)行call方法 new Thread(futureTask).start(); String result = futureTask.get(); System.out.println(result); } }
4、使用線程池創(chuàng)建線程(這里利用提供的線程池框架Executors創(chuàng)建線程池):
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()+"執(zhí)行"); } }); } }
二、再聊一聊spring自帶的@Async注解實(shí)現(xiàn)異步任務(wù)的方法
其實(shí)很簡(jiǎn)單,就是在應(yīng)用程序啟動(dòng)類上打@EnableAsync注解開啟異步注解的使用,再在業(yè)務(wù)類的某個(gè)方法上打@Async即可。
@SpringBootApplication @EnableAsync public class AopApplication { public static void main(String[] args) { SpringApplication.run(AopApplication.class, args); } }
業(yè)務(wù)類方法(舉例):
@Async public void insertDb(){ /*service code......*/ System.out.println("2----->收到請(qǐng)求,寫入數(shù)據(jù)庫(kù) "); }
三、那么就來(lái)設(shè)計(jì)一下怎么使用自定義的注解實(shí)現(xiàn)異步任務(wù)
首先我們寫一個(gè)注解:
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAsync { //規(guī)定value是異步開關(guān) boolean value() default false; }
我們讓注解中的value的值定為布爾類型,從而根據(jù)它的真假來(lái)決定異步線程的創(chuàng)建。
我們將它打在業(yè)務(wù)類的方法上:
@MyAsync(value = true) public void deleteDb(){ /*service code......*/ System.out.println("delete------>數(shù)據(jù)刪除"); }
然后我們利用AOP掃描這個(gè)注解:
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尋找執(zhí)行的線程中某個(gè)含有注解的方法棧,捕捉到之后就可以獲得對(duì)應(yīng)的連接點(diǎn)對(duì)象了。
利用可通過(guò)連接點(diǎn)對(duì)象ProcedJoinPoint的getSignture方法獲取簽名,可以將簽名強(qiáng)制轉(zhuǎn)化成方法簽名MethdSignture類型,從而利用該類型的getMethod方法獲取方法本身,接下來(lái)就可以獲取方法的注解,利用注解的屬性直接獲取value的真假,從而決定方法通過(guò)的方式是同步的還是異步的。(源碼利用到反射機(jī)制)。
到此這篇關(guān)于Springboot利用Aop捕捉注解實(shí)現(xiàn)業(yè)務(wù)異步執(zhí)行的文章就介紹到這了,更多相關(guān)Springboot業(yè)務(wù)異步執(zhí)行內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何使用elasticsearch進(jìn)行模糊查詢
這篇文章主要介紹了Java如何使用elasticsearch進(jìn)行模糊查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02MyBatis-Plus自動(dòng)化填充的踩坑記錄及解決
這篇文章主要介紹了MyBatis-Plus自動(dòng)化填充的踩坑記錄及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03java struts2學(xué)習(xí)筆記之線程安全
這篇文章主要為大家詳細(xì)介紹了java struts2學(xué)習(xí)筆記之線程安全,感興趣的朋友可以參考一下2016-04-04優(yōu)化spring?boot應(yīng)用后6s內(nèi)啟動(dòng)內(nèi)存減半
這篇文章主要為大家介紹了優(yōu)化spring?boot后應(yīng)用6s內(nèi)啟動(dòng)內(nèi)存減半的優(yōu)化示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-02-02給Java菜鳥的一些建議_關(guān)于Java知識(shí)點(diǎn)歸納(J2EE and Web 部分)
下面小編就為大家?guī)?lái)一篇給Java菜鳥的一些建議_關(guān)于Java知識(shí)點(diǎn)歸納(J2EE and Web 部分)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05spring學(xué)習(xí)之@SessionAttributes實(shí)例解析
這篇文章主要介紹了spring學(xué)習(xí)之@SessionAttributes實(shí)例解析,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02Java并發(fā)編程如何降低鎖粒度并實(shí)現(xiàn)性能優(yōu)化
這篇文章主要介紹了Java并發(fā)編程如何降低鎖粒度并實(shí)現(xiàn)性能優(yōu)化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08