Java项目启动时间过长的问题
问题描述:
项目启动缓慢,且中间有部分时间出现日志打印卡住的情况,极大的影响本地调试的效率
原因总结:
项目中引用了jOOQ ,导致@execution的aspectj扫描大量的实例和方法,影响项目启动速度
修改方式:
在不影响切面功能的基础上,用within代替execution,目前排查下来的只有一个针对所有controller的切面使用到了,修改掉项目启动速度由150s降到98s左右
参考:jOOQ,spring-boot and aop. · Issue #5902 · jOOQ/jOOQ (github.com)
排查过程
查看启动时的打印日志,确定下项目启动时缓慢的时间段
使用 BeanPostProcessor获取启动时加载时间大于1s的bean对象
逐步排查到dslContext的加载速度比较缓慢,直接从网上查询到相似问题,使用对应解决方案,over
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Configuration
@Slf4j
public class BeanCostTimePostProcessor implements BeanPostProcessor {
/**
* 项目启动时会执行此方法 实现了BeanPostProcessor接口,充当钩子函数,记录bean加载的时间
*/
private static final ConcurrentHashMap<String,Long> TIME_MAP = new ConcurrentHashMap<>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
TIME_MAP.put(beanName,System.currentTimeMillis());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Long time = TIME_MAP.get(beanName);
if (Objects.nonNull(time)){
long end = System.currentTimeMillis();
long cost = end - time;
if (cost > 1000L) {
log.info("=======================slow beanName:{} class path :{} , cost :{}", beanName, bean.getClass().getName(), cost);
}
}
return bean;
}
}