如何 运行 带有 AnnotationConfigWebApplicationContext 的 SpringApplication?
How to run a SpringApplication with AnnotationConfigWebApplicationContext?
我们有一个使用默认 ApplicationContext 运行良好的 SpringApplication,但我们有一个场景需要刷新上下文,而默认上下文不允许我们这样做。我已经将我们的主应用程序 class 更新为如下所示:
// package and import lines not shown here but are included in original source
@ComponentScan("edge")
@EnableAutoConfiguration
@Configuration
@EnableTransactionManagement
@EnableAsync
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationContextClass(AnnotationConfigWebApplicationContext.class);
app.run(args);
}
按原样使用此代码,调用 app.run(args) 会产生以下堆栈跟踪:
Exception in thread "main" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:170)
at org.springframework.boot.context.event.EventPublishingRunListener.registerApplicationEventMulticaster(EventPublishingRunListener.java:70)
at org.springframework.boot.context.event.EventPublishingRunListener.contextPrepared(EventPublishingRunListener.java:65)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at edge.server.Application.main(Application.java:43)
单步执行 SpringApplication.run(),我注意到上下文的 BeanFactory 为空。如果我删除行 app.setApplicationContextClass(AnnotationConfigWebApplicationContext.class)
,从而将应用程序设置为使用默认上下文,代码将一直运行到我们调用 refresh() 的位置。该调用导致:
java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
有没有人按照我描述的方式在 SpringApplication 中使用 AnnotationConfigWebApplicationContext 并使其工作?如果是这样,您对让它发挥作用有什么建议吗?我尝试寻找在调用 app.run() 之前手动创建 BeanFactory 的方法,但似乎没有任何 public 方法可以做到这一点。在此先感谢您提供的任何帮助!
编辑澄清:
感谢到目前为止的评论和回答。关于需要刷新 ApplicationContext 的场景以及我尝试使用 AnnotationConfigWebApplicationContext,我应该在我原来的 post 中更明确。我们有一些代码在服务器启动后运行,用于备份和恢复目的,这涉及修改我们正在使用的 JpaRepositories 的内容。我的理解是,在 运行 这段代码之后,我们需要刷新 ApplicationContext 以便再次调用我们所有的 init 方法。
尝试使用默认上下文 class(AnnotationConfigEmbeddedWebApplicationContext,GenericApplicationContext 的子class)执行此操作会抛出我之前提到的 IllegalStateException (GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
)。该异常促使我尝试将上下文显式设置为 AnnotationConfigWebApplicationContext,它是 AbstractRefreshableApplicationContext 的子class。我的假设是我需要应用程序使用 AbstractRefreshableApplicationContext 以便成功地多次调用刷新方法。有没有办法让我上面的代码工作,或者有没有我应该采用的替代方法可以让我们多次刷新上下文?
您正在使用 Spring Boot,它已经为您完成了这项工作,您只是让它过于复杂了。将您的 class 更改为以下内容。
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
并确保它在 edge
包中,并确保您具有启用 Web 应用程序的 spring-boot-starter-web
依赖项。没有必要自己弄乱上下文 class。
我们有一个使用默认 ApplicationContext 运行良好的 SpringApplication,但我们有一个场景需要刷新上下文,而默认上下文不允许我们这样做。我已经将我们的主应用程序 class 更新为如下所示:
// package and import lines not shown here but are included in original source
@ComponentScan("edge")
@EnableAutoConfiguration
@Configuration
@EnableTransactionManagement
@EnableAsync
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationContextClass(AnnotationConfigWebApplicationContext.class);
app.run(args);
}
按原样使用此代码,调用 app.run(args) 会产生以下堆栈跟踪:
Exception in thread "main" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:170)
at org.springframework.boot.context.event.EventPublishingRunListener.registerApplicationEventMulticaster(EventPublishingRunListener.java:70)
at org.springframework.boot.context.event.EventPublishingRunListener.contextPrepared(EventPublishingRunListener.java:65)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at edge.server.Application.main(Application.java:43)
单步执行 SpringApplication.run(),我注意到上下文的 BeanFactory 为空。如果我删除行 app.setApplicationContextClass(AnnotationConfigWebApplicationContext.class)
,从而将应用程序设置为使用默认上下文,代码将一直运行到我们调用 refresh() 的位置。该调用导致:
java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
有没有人按照我描述的方式在 SpringApplication 中使用 AnnotationConfigWebApplicationContext 并使其工作?如果是这样,您对让它发挥作用有什么建议吗?我尝试寻找在调用 app.run() 之前手动创建 BeanFactory 的方法,但似乎没有任何 public 方法可以做到这一点。在此先感谢您提供的任何帮助!
编辑澄清:
感谢到目前为止的评论和回答。关于需要刷新 ApplicationContext 的场景以及我尝试使用 AnnotationConfigWebApplicationContext,我应该在我原来的 post 中更明确。我们有一些代码在服务器启动后运行,用于备份和恢复目的,这涉及修改我们正在使用的 JpaRepositories 的内容。我的理解是,在 运行 这段代码之后,我们需要刷新 ApplicationContext 以便再次调用我们所有的 init 方法。
尝试使用默认上下文 class(AnnotationConfigEmbeddedWebApplicationContext,GenericApplicationContext 的子class)执行此操作会抛出我之前提到的 IllegalStateException (GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
)。该异常促使我尝试将上下文显式设置为 AnnotationConfigWebApplicationContext,它是 AbstractRefreshableApplicationContext 的子class。我的假设是我需要应用程序使用 AbstractRefreshableApplicationContext 以便成功地多次调用刷新方法。有没有办法让我上面的代码工作,或者有没有我应该采用的替代方法可以让我们多次刷新上下文?
您正在使用 Spring Boot,它已经为您完成了这项工作,您只是让它过于复杂了。将您的 class 更改为以下内容。
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
并确保它在 edge
包中,并确保您具有启用 Web 应用程序的 spring-boot-starter-web
依赖项。没有必要自己弄乱上下文 class。