一、了解JDK、CGLIB代理的区别
JDK动态代理和CGLIB动态代理是两种不同的方式来实现代理模式。
实现方式
JDK动态代理是基于接口的代理,
而CGLIB动态代理则是基于类的代理。
代理区别
JDK动态代理要求目标对象实现接口
CGLIB动态代理则可以代理没有实现接口的类
二、 AsyncConfig 异步配置
前置:增加以下2个注解
注解:
@EnableAsync(proxyTargetClass = true): 开启异步配置,proxyTargetClass 表示用CGLIB代理@Configuration 交由spring管理@EnableAsync(proxyTargetClass = true) @Configuration public class AsyncConfig extends AsyncConfigurerSupport {
1-首先要配置线程池
类路径: com.ruoyi.framework.config.ThreadPoolConfig (上篇文章:线程池配置类有)
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(core,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
2-配置类具体代码
实现逻辑:AsyncConfigurerSupport 配置类 ,继承了AsyncConfigurerSupport 类重写其方法
- getAsyncExecutor 定义异步线程池
- getAsyncUncaughtExceptionHandler 定义异步线程处理
package com.ruoyi.framework.config;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
/**
* 异步配置
*
* @author Lion Li
*/
@EnableAsync(proxyTargetClass = true)
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
/**
* <简述>
* <详细描述> com.ruoyi.framework.config.ThreadPoolConfig 类中配置线程池
* @author syf
* @date 2024/5/18 15:36
* @param null
* @return null
*/
@Autowired
@Qualifier("scheduledExecutorService")// @Qualifier 指的装配的bean
private ScheduledExecutorService scheduledExecutorService;
/**
* 自定义 @Async 注解使用系统线程池
*
*/
@Override
public Executor getAsyncExecutor() {
return scheduledExecutorService;
}
/**
* 异步执行异常处理
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
throwable.printStackTrace();
StringBuilder sb = new StringBuilder();
sb.append("Exception message - ").append(throwable.getMessage())
.append(", Method name - ").append(method.getName());
if (ArrayUtil.isNotEmpty(objects)) {
sb.append(", Parameter value - ").append(Arrays.toString(objects));
}
throw new ServiceException(sb.toString());
};
}
}
三、测试代码
controller 调用 service 层
@SaIgnore
@Slf4j
@RestController
@RequiredArgsConstructor
public class AsyncController {
AsyncService asyncService;
@GetMapping("async1")
public void async1(){
log.info("method1----------->主线程");
asyncService.method1();
}
}
service 层 @Component或者@Service 注解标注,交由spring管理
@Service
@Slf4j
public class AsyncService {
@Async
public void method1(){
ThreadUtil.sleep(3000);
log.info("method1----------->子线程");
}
}
结果:
子线程 schedule-pool-1 3秒后打印
2024-05-18 16:05:34 [XNIO-1 task-1] INFO c.r.demo.controller.AsyncController
- method1----------->主线程
2024-05-18 16:05:34 [XNIO-1 task-1] INFO c.r.f.i.PlusWebInvokeTimeInterceptor
- [PLUS]结束请求 => URL[GET /async1],耗时:[31]毫秒
2024-05-18 16:05:37 [schedule-pool-1] INFO c.ruoyi.demo.controller.AsyncService
- method1----------->子线程
四、注意 :
- 在子线程不需要返回结果时候 ,我们 @Async标注 异步执行 提高性能
- @Async注解标注的方法上标注 @Transactional注解,并且在该方法内抛出异常,才能被事务管理。(即 @Transactional、@Async同时标注的方法事务只会对该线程进行管理 )
@Async @Transactional public void method1(){ ThreadUtil.sleep(3000); iTestDemoService.deleteWithValidByIds(Arrays.asList(1L), false); log.info("method1----------->子线程"); throw new ServiceException("异常"); }