欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring的refresh()方法相关异常解析

程序员文章站 2024-04-01 20:47:58
spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。spring是于2003 年兴起的一个轻...

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类中:

@override
protected 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()方法中:

@override
public 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()方法相关异常的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

spring集成redis详解代码示例

spring aop拦截-三种方式实现自动代理详解

如有不足之处,欢迎留言指出。