这篇“Springboot怎么用Aop捕捉注解实现业务异步执行”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Springboot怎么用Aop捕捉注解实现业务异步执行”文章吧。
一、先说说线程的几种创建方式(简要列举)
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的真假,从而决定方法通过的方式是同步的还是异步的。(源码利用到反射机制)。
版权声明:除特别声明外,本站所有文章皆是本站原创,转载请以超链接形式注明出处!