栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

实际项目中应该避免@Async注解同类调用问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

实际项目中应该避免@Async注解同类调用问题

同类中调用有@Async注解的方法异步不生效,

其实@Async的这个性质在官网上已经有过说明了,官网:https://www.baeldung.com/spring-async是这样说的:

“First – let’s go over the rules – @Async has two limitations:
it must be applied to public methods only
self-invocation – calling the async method from within the same class – won’t work
The reasons are simple – 「the method needs to be public」 so that it can be proxied. And 「self-invocation doesn’t work」 because it bypasses the proxy and calls the underlying method directly.”

@Async的两个限制,第一个是必须在public修饰的情况下使用,第二个就是调用自己类上的异步方法是不起作用的。

原因:注解其实是通过代理的方式来实现异步调用的。同理@Transactional注解也是

实践

之前项目中会发生使用不当的情况:

 
 	public Integer delete(PointAccountDTO pointAccountDTO) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", pointAccountDTO.getId()).last("limit 1");
        PointAccountDO pointAccountDO = pointAccountMapper.selectOne(queryWrapper);
        int count = pointAccountMapper.delete(queryWrapper);
        if (count > 0) {
            deleteMemberAnalysisPoints(pointAccountDTO.getId());
            deleteGradeConditionPoints(pointAccountDO.getCode());
        }
        return count;
    }

    @Async
    @Transactional
    public void deleteMemberAnalysisPoints(String id){}
     
    @Async
    @Transactional
    public void deleteGradeConditionPoints(String code){}

正确使用场景,先建立异步工具类

@Component
@Slf4j
public class AsyncUtils {

    private static final ExecutorService EXECUTOR = new ThreadPoolExecutor(1, 5, 60,
            TimeUnit.MINUTES, new ArrayBlockingQueue<>(512));
    @Resource
    private AsyncTaskMapper asyncTaskMapper;

    public void execute(Runnable runnable, String param, String taskDesc) {
        AsyncTaskDO asyncTaskDO = AsyncTaskDO.builder()
                .param(param)
                .taskDesc(taskDesc)
                .build();
        asyncTaskMapper.insert(asyncTaskDO);
        EXECUTOR.submit(new TenantRunnableWrap(runnable, asyncTaskMapper, asyncTaskDO));

    }


    @Slf4j
    static class TenantRunnableWrap implements Runnable {
        private final Runnable task;
        private final AsyncTaskMapper asyncTaskMapper;
        private final AsyncTaskDO asyncTaskDO;

        public TenantRunnableWrap(Runnable task, AsyncTaskMapper asyncTaskMapper, AsyncTaskDO asyncTaskDO) {
            this.task = task;
            this.asyncTaskMapper = asyncTaskMapper;
            this.asyncTaskDO = asyncTaskDO;
        }

        @Override
        public void run() {
            try {
                task.run();
            } catch (Exception e) {
                asyncTaskDO.setExceptionDesc(e.getMessage());
                asyncTaskMapper.updateById(asyncTaskDO);
                return;
            }
            asyncTaskMapper.deleteById(asyncTaskDO);
        }
    }
}

先注入

@Autowired
private AsyncUtils asyncUtils;

注意,为了要让事务生效,一定要注入自身类

@Lazy
@Resource
PointAccountService pointAccountService;

使用

@Override
@Transactional
public Integer delete(PointAccountDTO pointAccountDTO) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", pointAccountDTO.getId()).last("limit 1");
        PointAccountDO pointAccountDO = pointAccountMapper.selectOne(queryWrapper);
        int count = pointAccountMapper.delete(queryWrapper);
        if (count > 0) {
            asyncUtils.execute(() -> pointAccountService.deleteMemberAnalysisPoints(pointAccountDTO.getId()), 
                    String.valueOf(pointAccountDTO.getId()),
                    "异步删除成员积分");
            asyncUtils.execute(() -> pointAccountService.deleteGradeConditionPoints(pointAccountDO.getCode()),
                    pointAccountDO.getCode(),
                    "异步删除等级积分");
//            deleteMemberAnalysisPoints(pointAccountDTO.getId());
//            deleteGradeConditionPoints(pointAccountDO.getCode());
        }
        return count;
    }

@Transactional
public void deleteGradeConditionPoints(String code) {}


执行是为了存表方便记录

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/590962.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号