- 描述现象,启动报错
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mqServiceFactory' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.sendinfo.mq.service.impl.MqServiceFactory]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.sendinfo.usr.util.SysCacheUtil
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1035)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:939)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
... 77 more
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.sendinfo.usr.util.SysCacheUtil
看上去很奇怪,SysCacheUtil 类明明是存在的怎么会NoClassDefFoundError,不过后半句Could not initialize class com.sendinfo.usr.util.SysCacheUtil 也给出了说明,是因为类没有初始化成功所以才NoClassDefFoundError
- 看 SysCacheUtil 类
public class SysCacheUtil {
private static final MemcachedClient MEMCACHED_CLIENT;
// 问题出在这里,UserConfig.SYSCACHECLIENT的值返回为null,静态块就会null指针异常,由于static块在类加载的时候就执行,执行失败类加载也就失败
static {
String client =UserConfig.SYSCACHECLIENT;
String str[] =client.split(":");
if(str.length>1){
Integer port=11211;
try {
port=Integer.valueOf(str[1].trim());
} catch (Exception e) {
System.out.println("端口默认为:12222");
e.printStackTrace();
}
MEMCACHED_CLIENT= new MemcachedClient(str[0], port);
}else if(str.length>0){
MEMCACHED_CLIENT= new MemcachedClient(str[0], 12222);
}else{
MEMCACHED_CLIENT= new MemcachedClient("cache.memcached.server.2", 12222);
}}
/**
* 设置数据到MemCached中,如果已经存在则覆盖
* @param key 键
* @param value 值
* @return
*/
public static void addSysOption(String key, Object value, int expire) throws Exception {
MEMCACHED_CLIENT.set(key, value,expire);
}
/**
* 获取memcached
* @return
*/
public static String getSysOption(String key) throws Exception{
String value = MEMCACHED_CLIENT.get(key);
if (StringUtil.isNotTrimBlank(value)) {
return value;
}
return null;
}
/**
* 删除memecache值
* @param key
*/
public static void delSysOption(String key) throws Exception{
MEMCACHED_CLIENT.delete(key);
}
}
- UserConfig 的SYSCACHECLIENT 是怎么赋值的? 其实是通过set注入的
<!-- 工作台配置等 -->
<bean id="userConfig" class="com.sendinfo.usr.util.UserConfig" lazy-init="false">
<property name="sysCacheClient" value="${SysCache.client}" />
<property name="weixinDev" value="${weixin.Dev}" />
<property name="platformAppCode" value="${platform.appCode}" />
<property name="platformAppKey" value="${platform.appKey}" />
<property name="platformDomain" value="${platform.domain}" />
<property name="sysPictureUrl" value="${sys.Picture.Url}" />
</bean>
但是userConfig初始化的顺序迟于MqServiceFactory ,所以UserConfig.SYSCACHECLIENT静态变量的值还是空的
4. 解决方法,将SysCacheUtil 的初始化静态块逻辑,放到一个方法里,并
private static MemcachedClient getMemcaheClient() {
if(MEMCACHED_CLIENT != null){
return MEMCACHED_CLIENT;
}
if(MEMCACHED_CLIENT == null){
synchronized (SysCacheUtil.class){
if(MEMCACHED_CLIENT == null){
// 去掉对UserConfig的依赖,直接获取系统属性
// String client = UserConfig.SYSCACHECLIENT;
String client = System.getProperty("SysCache.client")
String str[] = client.split(":");
if (str.length > 1) {
Integer port = 11211;
try {
port = Integer.valueOf(str[1].trim());
} catch (Exception e) {
System.out.println("端口默认为:12222");
e.printStackTrace();
}
MEMCACHED_CLIENT = new MemcachedClient(str[0], port);
} else if (str.length > 0) {
MEMCACHED_CLIENT = new MemcachedClient(str[0], 12222);
} else {
MEMCACHED_CLIENT = new MemcachedClient("cache.memcached.server.2", 12222);
}
}
}
}
return MEMCACHED_CLIENT;
}
本问题涉及到spring bean初始化顺序, java 类加载相关知识点, 基本是绕过了这两个点解决了本问题