illegalstateexception是什么异常_异常源码分析—告诉你学习“源码”究竟有什么用!...
點擊上方“服務端思維”,選擇“設為星標”
回復”669“獲取獨家整理的精選資料集
回復”加群“加入全國服務端高端社群「后端圈」
一、引言
最近接了個相當于外包的項目,在他們項目中集成一個WebSocket的服務端,嗯功能其實不難,但是前方有坑。
本文主要來記錄一下,如果沒有了百度,在項目啟動就拋異常、或者一些奇奇怪怪的問題,靠自己怎么去排查問題,同樣有時候并不是所有的問題都能夠通過搜索引擎來解決。
除了外力,那我們就只剩下:異常信息、源碼、和本身經驗。
項目框架用的是SpringBoot,然后集成WebSocket就行,在集成的過程中,其中有一步需要配置一個Bean。
@Component
public class WsConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter();
return serverEndpointExporter;
}然后在項目啟動的時候拋出了異常信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [org/springblade/modules/hol/config/WsConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:514)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:319)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:863)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
at org.springblade.core.launch.BladeApplication.run(BladeApplication.java:50)
at org.springblade.Application.main(Application.java:18)
Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
at org.springframework.util.Assert.state(Assert.java:73)
at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1828)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1765)
... 16 common frames omitted二、問題分析
Error creating bean with name 'serverEndpointExporter' defined in class path resource [org/springblade/modules/hol/config/WsConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
通過異常的第一行就能夠得知,是在Spring創建“serverEndpointExporter”bean的時候拋出來的,是這個WsConfig類,原因是:ServerContainer這個對象不可使用。
拋出異常的類是:AbstractAutowireCapableBeanFactory.java:1769
分析到這里就能夠得知,是在spring創建serverEndpointExporter的時候異常了,那么異常的原因是什么呢?,為什么ServerContainer不可用呢??接著分析
通過控制臺點擊到對應的源碼信息如下:AbstractAutowireCapableBeanFactory.java:1769
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
// 1769 這里就是1769行~~
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}通過查看源碼,是在1796行的catch里面拋出的異常的,catch是捕捉到invokeInitMethods這個方法異常,然后才拋出來的,這樣就可以開始進行Debug了。
既然是在創建serverEndpointExporter這個bean異常的,加一個篩選條件,beanName等于serverEndpointExporter,這樣就能過濾創建的其他bean。
斷點卡好了,接下來就Debug模式來啟動項目,然后F5進到invokeInitMethods方法,單步往下執行。
最后執行到了 ((InitializingBean) bean).afterPropertiesSet(); 這行代碼,bean對象是ServerEndpointExporter,調用了這個對象的afterPropertiesSet方法。
來到ServerEndpointExporter這個java類,其中就會有afterPropertiesSet方法,首先調用getServerContainer方法獲取serverContainer對象。
很明顯這里返回的肯定是null,null != null 結果肯定是false,最后就是這樣調用state(false,javax.websocket.server.ServerContainer not available)
通過state源碼得知,最后就會拋出這個異常:java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
三、解決問題
通過文章上述分析,可以確認是因為ServerEndpointExporter這個類中有一個對象叫做serverContainer,它為null了,所以才會異常。
接下來我們就需要去找,serverContainer這個對象是在哪里賦值的,找源碼就只有兩處賦值了,這就好辦了。
public class ServerEndpointExporter extends WebApplicationObjectSupport
implements InitializingBean, SmartInitializingSingleton {
@Nullable
private List> annotatedEndpointClasses;
@Nullable
private ServerContainer serverContainer;
// 有一個Set方法可以為serverContainer賦值
public void setServerContainer(@Nullable ServerContainer serverContainer) {
this.serverContainer = serverContainer;
}
@Nullable
protected ServerContainer getServerContainer() {
return this.serverContainer;
}
// 有一個init方法可以為serverContainer賦值
@Override
protected void initServletContext(ServletContext servletContext) {
if (this.serverContainer == null) {
this.serverContainer =
(ServerContainer) servletContext.getAttribute("javax.websocket.server.ServerContainer");
}
}
@Override
public void afterPropertiesSet() {
Assert.state(getServerContainer() != null, "javax.websocket.server.ServerContainer not available");
}
}通過IDEA的快捷方式,發現沒有其他地方調用了setServerContainer方法,那么就只有init方法了,那么就把斷點卡在initServletContext方法這。
通過Bebug就能夠發現,在從servletContext.getAttribute的時候,根本就沒有javax.websocket.server.ServerContainer,所以getAttribute返回就是一個null,最后賦值給了serverContainer,最后就導致異常了。
那為什么javax.websocket.server.ServerContainer會不存在呢?
來到這個ServerContainer對應的java類,原來是一個interface,那必然就會有對應的實現類,通過IDEA查看好家伙,到這小編大概就明白了,這個項目引用了其他jar包,導致了沖突。
最后定位到是哪個jar沖突了,直接通過IDEA定位功能就能夠定位到,最后通過maven helper工具定位到maven引用位置,然后移除掉。
最后刷新一下maven,項目就能夠正常啟動啦~~~~~
四、劃重點
本文并不是針對某一個異常、或者某一個具體的問題來進行分析,而是分享一下解決這個異常的一個過程。
最初的小編剛畢業那會,遇到個異常就百度,運氣好的話,很多人都踩過這個坑,能夠解決,萬一恰好沒有找到合適的文章,然后、然后就陷入了沉思,也不知道咋辦。
而且通過別人來解決的問題,肯定沒有自己解決問題的印象深刻,而且通過自己去找問題也是個有趣的過程。
也有很多小伙伴問過小編,學習一些框架源碼有什么用?會用不就行了嗎?
怎么說呢?當然確實會用就行了,話又說話來,難道你就不好奇它們這些技術到底是怎么實現的嗎?看源碼不僅僅能夠學習到其他大神編寫代碼的風格,而且對于使用也有會更加深一層次的理解。
久而久之,遇到問題,你的第一反應并不是直接去百度,而是會自己主動去摸索,到底是為啥子異常的,碰到一些看不懂的源碼,再去百度學習一下,進行分析。
就這樣不知不覺你的技術就會慢慢得到升華,那個時候感覺就特別明顯了。
— 本文結束 —
●?漫談設計模式在 Spring 框架中的良好實踐
●?顛覆微服務認知:深入思考微服務的七個主流觀點
●?人人都是 API 設計者
●?一文講透微服務下如何保證事務的一致性
●?要黑盒測試微服務內部服務間調用,我該如何實現?
關注我,回復 「加群」 加入各種主題討論群。
對「服務端思維」有期待,請在文末點個在看
喜歡這篇文章,歡迎轉發、分享朋友圈
在看點這里總結
以上是生活随笔為你收集整理的illegalstateexception是什么异常_异常源码分析—告诉你学习“源码”究竟有什么用!...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 花影塔罗是谁画的呢?
- 下一篇: 如何在notebook中的markdow