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()+"执行"); } }); } }
其實很簡單,就是在應用程式啟動類別上打@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中文網其他相關文章!