Spring的refresh()方法相关异常解析
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003年兴起的一个轻量级的Java开发框架,由RodJohnson创建。简单来说,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方法中又干了些什么?
publicvoidrefresh()throwsBeansException,IllegalStateException{ synchronized(this.startupShutdownMonitor){ //刷新之前的准备工作,包括设置启动时间,是否激活标识位,初始化属性源(propertysource)配置 prepareRefresh(); //由子类去刷新BeanFactory(如果还没创建则创建),并将BeanFactory返回 ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory(); //准备BeanFactory以供ApplicationContext使用 prepareBeanFactory(beanFactory); try{ //子类可通过格式此方法来对BeanFactory进行修改 postProcessBeanFactory(beanFactory); //实例化并调用所有注册的BeanFactoryPostProcessor对象 invokeBeanFactoryPostProcessors(beanFactory); //实例化并调用所有注册的BeanPostProcessor对象 registerBeanPostProcessors(beanFactory); //初始化MessageSource initMessageSource(); //初始化事件广播器 initApplicationEventMulticaster(); //子类覆盖此方法在刷新过程做额外工作 onRefresh(); //注册应用监听器ApplicationListener registerListeners(); //实例化所有non-lazy-initbean finishBeanFactoryInitialization(beanFactory); //刷新完成工作,包括初始化LifecycleProcessor,发布刷新完成事件等 finishRefresh(); } catch(BeansExceptionex){ //Destroyalreadycreatedsingletonstoavoiddanglingresources. destroyBeans(); //Reset'active'flag. cancelRefresh(ex); //Propagateexceptiontocaller. throwex; } } }
与此三条异常消息相关的方法分别为:
finishRefresh();obtainFreshBeanFactory();initApplicationEventMulticaster();
protectedvoidfinishRefresh(){ ////初始化LifecycleProcessor initLifecycleProcessor(); //Propagaterefreshtolifecycleprocessorfirst. getLifecycleProcessor().onRefresh(); //Publishthefinalevent. publishEvent(newContextRefreshedEvent(this)); //ParticipateinLiveBeansViewMBean,ifactive. LiveBeansView.registerApplicationContext(this); }
如果没有调用finishRefresh方法,则lifecycleProcessor成员为null。
protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){ refreshBeanFactory();//刷新BeanFactory,如果beanFactory为null,则创建 ConfigurableListableBeanFactorybeanFactory=getBeanFactory(); if(logger.isDebugEnabled()){ logger.debug("Beanfactoryfor"+getDisplayName()+":"+beanFactory); } returnbeanFactory; }
refreshBeanFactory()为一抽象方法,真正实现在AbstractRefreshableApplicationContext类中:
@Override protectedfinalvoidrefreshBeanFactory()throwsBeansException{ if(hasBeanFactory()){//如果beanFactory已经不为null,则销毁beanFactory中的Bean后自行关闭 destroyBeans(); closeBeanFactory(); } try{ DefaultListableBeanFactorybeanFactory=createBeanFactory();//创建beanFactory beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized(this.beanFactoryMonitor){ this.beanFactory=beanFactory;//对beanFactory成员进行赋值 } } catch(IOExceptionex){ thrownewApplicationContextException("I/Oerrorparsingbeandefinitionsourcefor"+getDisplayName(),ex); } }
如果没有调用obtainFreshBeanFactory()方法则beanFactory成员为null。
protectedvoidinitApplicationEventMulticaster(){ ConfigurableListableBeanFactorybeanFactory=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("UsingApplicationEventMulticaster["+this.applicationEventMulticaster+"]"); } } else{ this.applicationEventMulticaster=newSimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME,this.applicationEventMulticaster); if(logger.isDebugEnabled()){ logger.debug("UnabletolocateApplicationEventMulticasterwithname'"+ APPLICATION_EVENT_MULTICASTER_BEAN_NAME+ "':usingdefault["+this.applicationEventMulticaster+"]"); } } }
而这三个方法调用都在refresh()方法中,由上面的分析可知,如果没有调用refresh方法,则上下文中的lifecycleProcessor,beanFactory,applicationEventMulticaster成员都会为null。至此可以来详细分析这三条异常消息的缘由了。
下面是针对上面三条异常消息的三段测试代码,顺序相对应:
1.publicstaticvoidmain(String[]args){ ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext(); applicationContext.setConfigLocation("application-context.xml"); applicationContext.start(); applicationContext.close(); } 2.publicstaticvoidmain(String[]args){ ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext(); applicationContext.setConfigLocation("application-context.xml"); applicationContext.getBean("xtayfjpk"); applicationContext.close(); } 3.publicstaticvoidmain(String[]args){ GenericApplicationContextparent=newGenericApplicationContext(); AnnotationConfigWebApplicationContextcontext=newAnnotationConfigWebApplicationContext(); context.setParent(parent); context.refresh(); context.start(); context.close(); }
对于第一条异常消息,异常堆栈出错在applicationContext.start();下面是start()方法源码:
publicvoidstart(){ getLifecycleProcessor().start(); publishEvent(newContextStartedEvent(this)); }
可以看到start()方法中要先获取lifecycleProcessor对象,而默认构造方法中并没用调用refresh方法,所以lifecycleProcessor为null,故而在getLifecycleProcessor()方法中抛出了此异常消息。这其中提到了生命周期方法,其实就是定义在org.springframework.context.Lifecycle接口中的start(),stop(),isRunning()三个方法,如果是刚开始学习Spring的话,创建ClassPathXmlApplicationContext对象时应该是这样的:ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("application-context.xml");这样直接调用start()方法却又不会出现异常,这是为什么呢?这是因为ClassPathXmlApplicationContext(StringconfigLocation)这个构造方法最终调用的是:
publicClassPathXmlApplicationContext(String[]configLocations,booleanrefresh,ApplicationContextparent)throwsBeansException{ super(parent); setConfigLocations(configLocations); if(refresh){//refresh传递值为true,这样就自动调用了refresh方法进行了刷新 refresh(); } }
第二条异常消息,异常堆栈出错在applicationContext.getBean("xtayfjpk"),applicationContext.getBean()方法调用的是上下文中beanFactory的getBean()方法实现的,获取BeanFactory对象的代码在其基类ConfigurableListableBeanFactory中的getBeanFactory()方法中:
@Override publicfinalConfigurableListableBeanFactorygetBeanFactory(){ synchronized(this.beanFactoryMonitor){ if(this.beanFactory==null){ thrownewIllegalStateException("BeanFactorynotinitializedoralreadyclosed-"+ "call'refresh'beforeaccessingbeansviatheApplicationContext"); } returnthis.beanFactory; } }
由于ClassPathXmlApplicationContext的默认构造方法没有调用refresh()方法,所以beanFactory为null,因此抛出异常。
第三条异常消息,异常堆栈出错在context.refresh(),但是如果没有设置父上下文的话context.setParent(parent),例子代码是不会出现异常的。这是因为在refresh方法中的finishRefresh()方法调用了publishEvent方法:
publicvoidpublishEvent(ApplicationEventevent){ Assert.notNull(event,"Eventmustnotbenull"); if(logger.isTraceEnabled()){ logger.trace("Publishingeventin"+getDisplayName()+":"+event); } getApplicationEventMulticaster().multicastEvent(event); if(this.parent!=null){ this.parent.publishEvent(event); } }
从上面可以看到:如果父上下文不为null,则还需要调用父容器的pushlishEvent方法,而且在该方法中调用了getApplicationEventMulticaster()方法以获取一个事件广播器,问题就出现在这里:
privateApplicationEventMulticastergetApplicationEventMulticaster()throwsIllegalStateException{ if(this.applicationEventMulticaster==null){//如果为null则抛异常 thrownewIllegalStateException("ApplicationEventMulticasternotinitialized-"+ "call'refresh'beforemulticastingeventsviathecontext:"+this); } returnthis.applicationEventMulticaster; }
而applicationEventMulticaster就是在refresh方法中的initApplicationEventMulticaster方法在实例化的,则于父上下文没有调用过refresh方法所以父上下文的applicationEventMulticaster成员为null,因此抛出异常。
综上所述,其实这三条异常消息的根本原因只有一个,就是当一个上下文对象创建后没有调用refresh()方法。在Spring中ApplicationContext实现类有很多,有些实现类在创建的过程中自动调用了refresh()方法,而有些又没有,如果没有则需要自己手动调用refresh()方法。一般说来实现WebApplicationContext接口的实现类以及使用默认构造方法创建上下文对象时不会自动refresh()方法,其它情况则会自动调用。
总结
以上就是本文关于Spring的refresh()方法相关异常的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:
Spring集成Redis详解代码示例
SpringAOP拦截-三种方式实现自动代理详解
spring配置扫描多个包问题解析
如有不足之处,欢迎留言指出。