springboot装配devtools后,类被加载两次的问题

场景:

    项目采用springboot+devtools热加载开发,在项目的某个角落有一个工具类,采用静态内部类做InstanceHolder,如下:

public final class ConnectionTool {
    private ConnectionTool() {}
	
	public static final ConnectionTool getInstance() {
		return MyHolder.getInstance();
	}
	
	public final class MyHolder {
		private MyHolder() {}
		
		private static final Object SYNC_OBJ = new Object();
		
		private static ConnectionTool instance;
		
		public static ConnectionTool getInstance() {
			final ConnectionTool pool;
			synchronized(SYNC_OBJ) {
				if(instance == null) {
					instance = new ConnectionTool();
				}
				pool = instance;
			}
			return pool;
		}
	}
}

在实际调用的时候,有两个地方,一个是controller中获取instance,另一个是schedule方法中获取instance。但是两个地方获取到的instance竟然不是同一个,换言之,本以为万无一失的单例终极之道竟然失效。。。忧伤

经过重重筛查,最终发现,两个地方的类的ClassLoader竟然不是同一个,controller中的classCloader是sun.misc.Launcher$AppClassLoader@18b4aac2,而线程中的是org.springframework.boot.devtools.restart.classloader.RestartClassLoader@68801664,换言之,这个类被加载了两次,so。

解决方案:

1. 去掉devtools,问题不攻自破

2.  用系统类加载器+反射来获取instance,如下:

try {
	ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
	Class<?> aClass = systemClassLoader.loadClass("com.a.b.c.ConnectionPool");
	Method getInstance = MethodUtils.getMatchingMethod(aClass, "getInstance");
	ConnectionPool invoke = (ConnectionPool)getInstance.invoke(null);
	System.out.println(aClass);
	System.out.println(aClass.getClassLoader());
}catch (Exception e) {
	e.printStackTrace();
}
from now on, everything will be ok, good lucks!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值