亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring的refresh()方法相關異常解析

2024-07-13 10:14:00
字體:
來源:轉載
供稿:網友

Spring是一個開放源代碼的設計層面框架,他解決的是業務邏輯層和其他各層的松耦合問題,因此它將面向接口的編程思想貫穿整個系統應用。Spring是于2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson創建。簡單來說,Spring是一個分層的JavaSE/EEfull-stack(一站式) 輕量級開源框架。

如果是經常使用Spring,特別有自己新建ApplicationContext對象的經歷的人,肯定見過這么幾條異常消息:

1.LifecycleProcessornotinitialized-call'refresh'beforeinvokinglifecyclemethodsviathecontext:......

2.BeanFactorynotinitializedoralreadyclosed-call'refresh'beforeaccessingbeansviatheApplicationContext

3.ApplicationEventMulticasternotinitialized-call'refresh'beforemulticastingeventsviathecontext:......

第一條消息是說LifecycleProcessor對象沒有初始化,在調用context的生命周期方法之前必須調用'refresh'方法

第二條消息是說BeanFactory對象沒有初始化或已經關閉了,使用ApplicationContext獲取Bean之前必須調用'refresh'方法

第三條消息是說ApplicationEventMulticaster對象沒有初始化,在context廣播事件之前必須調用'refresh'方法

這幾條異常消息都與refresh方法有關,那拋出這些異常的原因到底是什么,為什么在這么多情況下一定要先調用refresh方法(定義在AbstractApplicationContext類中),在此這前我們先看看refresh方法中又干了些什么?

public void refresh() throws BeansException, IllegalStateException {	synchronized (this.startupShutdownMonitor) {		//刷新之前的準備工作,包括設置啟動時間,是否激活標識位,初始化屬性源(property source)配置		prepareRefresh();		//由子類去刷新BeanFactory(如果還沒創建則創建),并將BeanFactory返回		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();		//準備BeanFactory以供ApplicationContext使用		prepareBeanFactory(beanFactory);		try {			//子類可通過格式此方法來對BeanFactory進行修改			postProcessBeanFactory(beanFactory);			//實例化并調用所有注冊的BeanFactoryPostProcessor對象			invokeBeanFactoryPostProcessors(beanFactory);			//實例化并調用所有注冊的BeanPostProcessor對象			registerBeanPostProcessors(beanFactory);			//初始化MessageSource			initMessageSource();			//初始化事件廣播器			initApplicationEventMulticaster();			//子類覆蓋此方法在刷新過程做額外工作			onRefresh();			//注冊應用監聽器ApplicationListener			registerListeners();			//實例化所有non-lazy-init bean			finishBeanFactoryInitialization(beanFactory);			//刷新完成工作,包括初始化LifecycleProcessor,發布刷新完成事件等			finishRefresh();		}		catch (BeansException ex) {			// Destroy already created singletons to avoid dangling resources.			destroyBeans();			// Reset 'active' flag.			cancelRefresh(ex);			// Propagate exception to caller.			throw ex;		}	}}

與此三條異常消息相關的方法分別為:

finishRefresh();obtainFreshBeanFactory();initApplicationEventMulticaster();

protected void finishRefresh() {	// //初始化LifecycleProcessor	initLifecycleProcessor();	// Propagate refresh to lifecycle processor first.	getLifecycleProcessor().onRefresh();	// Publish the final event.	publishEvent(new ContextRefreshedEvent(this));	// Participate in LiveBeansView MBean, if active.	LiveBeansView.registerApplicationContext(this);}

如果沒有調用finishRefresh方法,則lifecycleProcessor成員為null。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {  refreshBeanFactory();//刷新BeanFactory,如果beanFactory為null,則創建  ConfigurableListableBeanFactory beanFactory = getBeanFactory();  if (logger.isDebugEnabled()) {    logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);  }  return beanFactory;}

refreshBeanFactory()為一抽象方法,真正實現在AbstractRefreshableApplicationContext類中:

@Overrideprotected final void refreshBeanFactory() throws BeansException {  if (hasBeanFactory()) {//如果beanFactory已經不為null,則銷毀beanFactory中的Bean后自行關閉    destroyBeans();    closeBeanFactory();  }  try {    DefaultListableBeanFactory beanFactory = createBeanFactory();//創建beanFactory    beanFactory.setSerializationId(getId());    customizeBeanFactory(beanFactory);    loadBeanDefinitions(beanFactory);    synchronized (this.beanFactoryMonitor) {      this.beanFactory = beanFactory;//對beanFactory成員進行賦值    }  }  catch (IOException ex) {    throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);  }}

如果沒有調用obtainFreshBeanFactory()方法則beanFactory成員為null。

protected void initApplicationEventMulticaster() {  ConfigurableListableBeanFactory beanFactory = getBeanFactory();  if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {    this.applicationEventMulticaster =        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);    if (logger.isDebugEnabled()) {      logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");    }  }  else {    this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);    beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);    if (logger.isDebugEnabled()) {      logger.debug("Unable to locate ApplicationEventMulticaster with name '" +          APPLICATION_EVENT_MULTICASTER_BEAN_NAME +          "': using default [" + this.applicationEventMulticaster + "]");    }  }}

而這三個方法調用都在refresh()方法中,由上面的分析可知,如果沒有調用refresh方法,則上下文中的lifecycleProcessor,beanFactory,applicationEventMulticaster成員都會為null。至此可以來詳細分析這三條異常消息的緣由了。

下面是針對上面三條異常消息的三段測試代碼,順序相對應:

1. public static void main(String[] args) {  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();  applicationContext.setConfigLocation("application-context.xml");  applicationContext.start();  applicationContext.close();}2. public static void main(String[] args) {  ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();  applicationContext.setConfigLocation("application-context.xml");  applicationContext.getBean("xtayfjpk");  applicationContext.close();}3. public static void main(String[] args) {  GenericApplicationContext parent = new GenericApplicationContext();  AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();  context.setParent(parent);  context.refresh();  context.start();  context.close();}

對于第一條異常消息,異常堆棧出錯在applicationContext.start();下面是start()方法源碼:

public void start() {  getLifecycleProcessor().start();  publishEvent(new ContextStartedEvent(this));}

可以看到start()方法中要先獲取lifecycleProcessor對象,而默認構造方法中并沒用調用refresh方法,所以lifecycleProcessor為null,故而在getLifecycleProcessor()方法中拋出了此異常消息。這其中提到了生命周期方法,其實就是定義在org.springframework.context.Lifecycle接口中的start(),stop(),isRunning()三個方法,如果是剛開始學習Spring的話,創建ClassPathXmlApplicationContext對象時應該是這樣的:ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("application-context.xml");這樣直接調用start()方法卻又不會出現異常,這是為什么呢?這是因為ClassPathXmlApplicationContext(StringconfigLocation)這個構造方法最終調用的是:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {  super(parent);  setConfigLocations(configLocations);  if (refresh) {//refresh傳遞值為true,這樣就自動調用了refresh方法進行了刷新    refresh();  }}

第二條異常消息,異常堆棧出錯在applicationContext.getBean("xtayfjpk"),applicationContext.getBean()方法調用的是上下文中beanFactory的getBean()方法實現的,獲取BeanFactory對象的代碼在其基類ConfigurableListableBeanFactory中的getBeanFactory()方法中:

@Overridepublic final ConfigurableListableBeanFactory getBeanFactory() {  synchronized (this.beanFactoryMonitor) {    if (this.beanFactory == null) {      throw new IllegalStateException("BeanFactory not initialized or already closed - " +          "call 'refresh' before accessing beans via the ApplicationContext");    }    return this.beanFactory;  }}

由于ClassPathXmlApplicationContext的默認構造方法沒有調用refresh()方法,所以beanFactory為null,因此拋出異常。

第三條異常消息,異常堆棧出錯在context.refresh(),但是如果沒有設置父上下文的話context.setParent(parent),例子代碼是不會出現異常的。這是因為在refresh方法中的finishRefresh()方法調用了publishEvent方法:

public void publishEvent(ApplicationEvent event) {  Assert.notNull(event, "Event must not be null");  if (logger.isTraceEnabled()) {    logger.trace("Publishing event in " + getDisplayName() + ": " + event);  }  getApplicationEventMulticaster().multicastEvent(event);  if (this.parent != null) {    this.parent.publishEvent(event);  }}

從上面可以看到:如果父上下文不為null,則還需要調用父容器的pushlishEvent方法,而且在該方法中調用了getApplicationEventMulticaster()方法以獲取一個事件廣播器,問題就出現在這里:

private ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {  if (this.applicationEventMulticaster == null) {//如果為null則拋異常    throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +        "call 'refresh' before multicasting events via the context: " + this);  }  return this.applicationEventMulticaster;}

而applicationEventMulticaster就是在refresh方法中的initApplicationEventMulticaster方法在實例化的,則于父上下文沒有調用過refresh方法所以父上下文的applicationEventMulticaster成員為null,因此拋出異常。

綜上所述,其實這三條異常消息的根本原因只有一個,就是當一個上下文對象創建后沒有調用refresh()方法。在Spring中ApplicationContext實現類有很多,有些實現類在創建的過程中自動調用了refresh()方法,而有些又沒有,如果沒有則需要自己手動調用refresh()方法。一般說來實現WebApplicationContext接口的實現類以及使用默認構造方法創建上下文對象時不會自動refresh()方法,其它情況則會自動調用。

總結

以上就是本文關于Spring的refresh()方法相關異常的全部內容,希望對大家有所幫助。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美在线中文字幕| 97激碰免费视频| 日本不卡免费高清视频| 欧美日韩在线视频观看| 夜夜嗨av色一区二区不卡| 成人欧美在线视频| 91亚洲人电影| 2020久久国产精品| 亚洲r级在线观看| 亚洲国产精品免费| 亚洲天堂男人天堂女人天堂| 精品偷拍一区二区三区在线看| 日韩美女av在线免费观看| 欧美一级淫片aaaaaaa视频| 亚洲91精品在线观看| 日韩av电影手机在线观看| 欧美丰满老妇厨房牲生活| 亚洲经典中文字幕| 日韩视频免费大全中文字幕| 欧美日韩国产中字| 91性高湖久久久久久久久_久久99| 26uuu另类亚洲欧美日本一| 最近中文字幕mv在线一区二区三区四区| 91网站免费看| 秋霞av国产精品一区| 国产欧美亚洲精品| 国产成人中文字幕| 国产精品黄页免费高清在线观看| 色噜噜狠狠狠综合曰曰曰88av| 国产91在线高潮白浆在线观看| 亚洲自拍中文字幕| 国产不卡精品视男人的天堂| 97精品视频在线| 国产一区二区丝袜高跟鞋图片| 久久中文精品视频| 久青草国产97香蕉在线视频| 九九热视频这里只有精品| 中文字幕欧美专区| 欧美人与性动交| 亚洲激情久久久| 国产精品久久久久免费a∨| 欧美黑人性视频| 欧洲成人免费视频| 久精品免费视频| 欧美国产中文字幕| 亚洲成人久久久久| 精品人伦一区二区三区蜜桃免费| 欧美日韩一区二区精品| 亚洲区一区二区| 久久av资源网站| 91成人免费观看网站| 亚洲精品在线91| 91麻豆国产语对白在线观看| www.亚洲天堂| 亚洲日韩第一页| 欧美高清无遮挡| 2019亚洲日韩新视频| 57pao国产精品一区| 欧美性生交xxxxxdddd| 亚洲精品国精品久久99热一| 欧美国产视频一区二区| 欧美日韩中文字幕日韩欧美| 日韩在线精品一区| 国产成人欧美在线观看| 亚洲人午夜精品免费| 欧美成人免费在线视频| 九九热精品视频国产| 91精品国产自产91精品| 国产综合在线观看视频| 日韩精品视频免费在线观看| 91久久国产精品91久久性色| 亚洲色图日韩av| 久久这里只有精品99| 亚洲福利视频在线| 日韩免费观看视频| 久久久久久久久久婷婷| 欧美日韩成人在线播放| 2021国产精品视频| 日韩高清av一区二区三区| 国产欧美日韩丝袜精品一区| 2025国产精品视频| 亚洲一区二区三区在线视频| 欧美激情影音先锋| 亚洲国产另类 国产精品国产免费| 91亚洲精品久久久久久久久久久久| 国产精品免费视频xxxx| 欧美激情第1页| 亚洲免费视频在线观看| 亚洲人成网在线播放| 2021久久精品国产99国产精品| 亚洲国产97在线精品一区| 伊人亚洲福利一区二区三区| 久久久精品国产网站| 性欧美长视频免费观看不卡| 久久久久久久久综合| 国产精品久久久久久中文字| 欧美极品少妇xxxxx| 国产视频精品xxxx| 欧美洲成人男女午夜视频| 亚洲欧美激情视频| 精品中文字幕在线观看| 欧美激情aaaa| 精品国产91久久久久久| 亚洲free性xxxx护士hd| 日韩精品高清在线观看| 色爱av美腿丝袜综合粉嫩av| 国产一区二区丝袜高跟鞋图片| 欧美国产日产韩国视频| 一区二区三区精品99久久| 国产日韩欧美影视| 国产精品久久久亚洲| 欧美亚洲另类制服自拍| 国产欧美日韩中文字幕| 中文字幕亚洲第一| 欧美成人午夜剧场免费观看| 欧美xxxx14xxxxx性爽| 国产欧美精品一区二区三区介绍| 国产精品无av码在线观看| 国产香蕉一区二区三区在线视频| 久久福利网址导航| 亚洲综合精品伊人久久| 国产午夜精品一区二区三区| 欧美午夜激情在线| 97久久精品视频| 亚洲欧美另类自拍| 久久久久久这里只有精品| 91精品视频大全| 日日狠狠久久偷偷四色综合免费| 日韩欧美精品在线观看| 国产精品999999| 日韩欧美国产视频| 欧美尤物巨大精品爽| 这里只有精品视频在线| 日韩大胆人体377p| 精品美女永久免费视频| 国产精品精品久久久| 亚洲国产欧美一区二区三区同亚洲| 在线精品视频视频中文字幕| 久久躁日日躁aaaaxxxx| 国产精品美女视频网站| 91亚洲精华国产精华| 午夜精品一区二区三区av| 亚洲国产一区二区三区在线观看| 久久久久一本一区二区青青蜜月| 国产精品视频成人| 精品丝袜一区二区三区| 91视频-88av| 欧美福利视频网站| 日韩中文字幕欧美| 成人免费视频在线观看超级碰| 97精品国产97久久久久久春色| 国模精品系列视频| 亚洲在线免费视频| 日韩视频永久免费观看| 日本久久久久久| 中文精品99久久国产香蕉| 欧美午夜无遮挡| 亚洲欧美国产视频| 国产在线精品成人一区二区三区| 成人国产亚洲精品a区天堂华泰| 久久亚洲电影天堂| 国产精品国内视频| 91在线观看欧美日韩| 一区二区三区日韩在线|