确认

  • [X] 我使用的版本是最新版, 并且使用插件确认过项目里无依赖版本冲突
  • [X] 我已经在 issue 中搜索过, 确认问题没有被提出过
  • [X] 我已经修改标题, 将标题中的 描述 替换为遇到的问题

当前程序版本

3.5.7

问题描述

我项目原先用的tkmybatis,然后在改成mybatis-plus后发现项目启动非常慢,依赖引入了mybatis-plus 3.5.7和mybatis-plus-join-boot-starter 1.4.13。通过BeanPostProcessor打印项目启动时的bean加载时间,发现所有mapper加载了两次,且第二次加载的时间非常缓慢,大概在一两千毫秒。

详细堆栈日志

2024-09-25 19:04:40.048  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomApRelMapper, init cost 2ms
2024-09-25 19:04:41.286  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomApRelMapper, init cost 1240ms
2024-09-25 19:04:41.777  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomApRelServiceImpl, init cost 487ms
2024-09-25 19:04:41.783  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomTcpRelMapper, init cost 1ms
2024-09-25 19:04:43.315  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomTcpRelMapper, init cost 1533ms
2024-09-25 19:04:43.320  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName tcpConfigMapper, init cost 1ms
2024-09-25 19:04:45.010  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName tcpConfigMapper, init cost 1691ms
2024-09-25 19:04:45.026  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomNodeRelMapper, init cost 1ms
2024-09-25 19:04:46.883  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomNodeRelMapper, init cost 1858ms
2024-09-25 19:04:46.887  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName nodeMapper, init cost 1ms
2024-09-25 19:04:49.114  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName nodeMapper, init cost 2228ms
2024-09-25 19:04:49.120  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomNodeLayoutMapper, init cost 0ms
2024-09-25 19:04:51.658  INFO 15620 --- [           main] c.d.c.BeanInitCostTimeBeanPostProcessor  : beanName roomNodeLayoutMapper, init cost 2538ms

Comment From: fengyujun

是不是应该把mybatis-plus-join-boot-starter包去掉启动看看有没有问题,再确定是否是mp问题

Comment From: qmdx

up

Comment From: huangdinghe

会不会是读取hostname的问题

Comment From: H-Knight

是不是应该把mybatis-plus-join-boot-starter包去掉启动看看有没有问题,再确定是否是mp问题

去掉过,依然启动很慢

Comment From: H-Knight

会不会是读取hostname的问题

你说的读取hostname具体指的什么?

Comment From: huangdinghe

生成雪花id会用hostname

Comment From: H-Knight

生成雪花id会用hostname

没有,我的ID目前用的UUID,而且是项目启动的时候慢,应该跟这里没关系吧

Comment From: H-Knight

@Aspect @Component public class LogAspect {

private final ThreadLocal<LogCenter> logThreadLocal = new ThreadLocal<>();

@Autowired
private LogCenterService logCenterService;

@Autowired
private ThreadPoolTaskExecutor commonThreadPool;

@Pointcut("execution (public * com.dm.api.*.*.*(..))")
public void logAspect() {
}

@Before(value = "logAspect() && @annotation(log)")
public void doBefore(JoinPoint joinPoint, Log log) throws Throwable {
    try {
        LoginUserDetails loginUserDetails = (LoginUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        // 参数名
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        // 参数值
        Object[] args = joinPoint.getArgs();
        Map<Object, Object> objectMap = new HashMap<>(16);
        //joinPoint中的参数名与参数值一一对应,所以组装成map对象
        for (int i = 0; i < argNames.length; i++) {
            objectMap.put(argNames[i], args[i]);
        }
        //当前时间
        Date nowDate = new Date();
        String title = log.title();
        LogEvent event = log.event();
        String memo = log.memo();
        String module = log.module();
        LogLevel logLevel = LogLevel.info;
        Integer readType = (Integer) objectMap.get("readType");
        if (readType != null) {
            String valueByCode = LogReadType.getValueByCode(readType);
            title = valueByCode;
        }
        //方法调用参数
        String argsStr = null;

        //非文件类 保存参数
        if (!log.event().equals(LogEvent.file)) {
            argsStr = joinPoint.getArgs() == null || joinPoint.getArgs().length == 0 ? null : JSONObject.toJSONString(joinPoint.getArgs());
        }
        //当事件为保存时 判断是修改/添加
        if (log.event() == LogEvent.save) {

            //从参数中获取PKID 如果存在且不为空则认定为修改 否则新增
            if (StringUtils.isNotEmpty(argsStr)) {

                JSONObject arsgJson = JSONObject.parseObject(argsStr);

                if (StringUtils.isNotEmpty(arsgJson.getString("PKID"))) {

                    event = LogEvent.add;
                } else {
                    event = LogEvent.edit;
                }

            }
        }

        LogCenter logCenter = new LogCenter();
        // 创建人信息请根据实际项目获取方式获取
        logCenter.setLogMemo(memo);
        logCenter.setLogEvent(event.getValue());
        logCenter.setSourceModule(module);
        logCenter.setLogTitle(title);
        logCenter.setLogData(argsStr);
        logCenter.setLogLevel(logLevel.getValue());
        logCenter.setHostIp(ServletUtil.getClientIP(request));
        logCenter.setOperateUserId(loginUserDetails.getUser().getPkid());
        logCenter.setCreateTime(nowDate);
        logThreadLocal.set(logCenter);

    } catch (Exception e) {

    }
}

@AfterReturning(pointcut = "logAspect()", returning = "ret")
public void doAfterReturning(Object ret) {
    LogCenter logCenter = logThreadLocal.get();
    if (logCenter != null) {
        commonThreadPool.execute(new SaveLogThread(logCenter, logCenterService));
        logThreadLocal.remove();
    }
}

@AfterThrowing(pointcut = "logAspect()", throwing = "e")
public void doAfterThrowable(Throwable e) {
    LogCenter logCenter = logThreadLocal.get();
    if (logCenter != null) {
        // 设置日志级别
        if (e instanceof OtherException || e.getCause() instanceof OtherException) {
            logCenter.setLogEvent(LogLevel.warning.getValue());
        } else {
            logCenter.setLogEvent(LogLevel.error.getValue());
        }
        logCenter.setLogTitle(e.getMessage());
        commonThreadPool.execute(new SaveLogThread(logCenter, logCenterService));
        logThreadLocal.remove();
    }
}

private static class SaveLogThread extends Thread {
    private final LogCenter logCenter;
    private final LogCenterService logCenterService;

    public SaveLogThread(LogCenter logCenter, LogCenterService logCenterService) {
        this.logCenter = logCenter;
        this.logCenterService = logCenterService;
    }

    @Override
    public void run() {
        logCenterService.save(logCenter);
    }
}

} 我发现启动慢是因为这个切面导致的,我在去掉这个类后项目启动速度是正常的,一旦加上后,mapper初始化就会变得非常非常慢