我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring中refresh()方法有什么用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring中refresh()方法有什么用

这篇文章将为大家详细讲解有关Spring中refresh()方法有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。

如果是经常使用Spring,特别有自己新建ApplicationContext对象的经历的人,肯定见过这么几条异常消息:

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

BeanFactorynotinitializedoralreadyclosed-call'refresh'beforeaccessingbeansviatheApplicationContext

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);//初始化MessageSourceinitMessageSource();//初始化事件广播器initApplicationEventMulticaster();//子类覆盖此方法在刷新过程做额外工作onRefresh();//注册应用监听器ApplicationListenerregisterListeners();//实例化所有non-lazy-init beanfinishBeanFactoryInitialization(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() {// //初始化LifecycleProcessorinitLifecycleProcessor();// 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()方法有什么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring中refresh()方法有什么用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring中refresh()方法有什么用

这篇文章将为大家详细讲解有关Spring中refresh()方法有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题
2023-05-30

Spring中的refresh方法怎么用

这篇文章主要介绍“Spring中的refresh方法怎么用”,在日常操作中,相信很多人在Spring中的refresh方法怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring中的refresh方法
2023-06-30

Spring容器初始化register与refresh方法是什么

这篇文章主要讲解了“Spring容器初始化register与refresh方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring容器初始化register与refresh方法是
2023-07-02

页面刷新的reload()和refresh()方法有什么不同

reload()方法用于重新加载当前页面,它会从服务器重新加载页面资源,并丢失当前页面的任何已更改的状态。换句话说,它会重新加载整个页面。refresh()方法用于刷新当前页面,它会重新加载当前页面,但会保留当前页面的任何已更改的状态。换句
2023-09-20

spring中ContextLoaderListener有什么用

ContextLoaderListener是Spring框架中用于初始化Web应用程序上下文的监听器。它的主要作用有以下几个方面:1. 创建并初始化Spring的根应用程序上下文:ContextLoaderListener会在Web应用程序
2023-09-13

Spring中contextconfiglocation有什么用

在Spring中,`contextConfigLocation`属性用于指定要加载的Spring配置文件的位置。具体来说,`contextConfigLocation`属性用于告诉Spring容器去哪里寻找配置文件。它可以指定一个或多个配
Spring中contextconfiglocation有什么用
2023-10-28

Spring中spring-context-indexer依赖有什么用

这篇文章给大家分享的是有关Spring中spring-context-indexer依赖有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Spring spring-context-indexer依赖
2023-06-25

Spring中的applicationcontext有什么用

Spring中的ApplicationContext是Spring框架中的一个接口,它是一个高级的工厂类,用来管理Spring容器中的Bean对象。ApplicationContext可以帮助我们实现以下功能:Bean的管理:Applica
Spring中的applicationcontext有什么用
2024-03-07

Spring有什么用

这篇文章主要介绍了Spring有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、Spring介绍简介Spring 框架为现代基于 java 的企业应用程序提供了一个全
2023-06-20

Spring中controlleradvice注解有什么用

@ControllerAdvice注解在Spring中的使用有以下几个作用:1. 全局异常处理:使用@ControllerAdvice注解可以在应用程序中统一处理异常,避免在每个Controller中都重复处理异常。通过在@Controll
2023-10-12

Spring中@Import注解有什么用

这期内容当中小编将会给大家带来有关Spring中@Import注解有什么用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。认识@Import注解@Target(ElementType.TYPE)@Reten
2023-06-15

jQuery中toggle()方法有什么用

本篇文章为大家展示了jQuery中toggle()方法有什么用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。jquery是什么jquery是一个简洁而快速的JavaScript库,它具有独特的链式语
2023-06-14

javascript中Object.defineProperty()方法有什么用

这篇文章给大家分享的是有关javascript中Object.defineProperty()方法有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java的优点是什么1. 简单,只需理解基本的概念,就可以编
2023-06-14

python中filter()方法有什么用

这篇文章主要为大家展示了“python中filter()方法有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python中filter()方法有什么用”这篇文章吧。filter()方法(过
2023-06-17

JDBC 中 setAutoCommit() 方法有什么用

JDBC中的setAutoCommit()方法用于设置连接的自动提交模式。自动提交模式指的是每当执行一个SQL语句时是否立即将其提交到数据库中。默认情况下,连接的自动提交模式是打开的,也就是说每个SQL语句都会立即提交到数据库。在某些情况下
2023-10-10

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录