确保从非 spring 上下文加载 spring bean
Ensure spring bean loaded from non spring context
我有 spring 应用程序以及 (jersey 2.6 classes 和 ) servlets .
我需要从 jersey/non spring 上下文中获取 Spring 个 bean,
类似question 建议在上下文的静态包装器中获取上下文
public static ApplicationContext getContext() {
return context;
}
如何确定上下文是否已加载或不为空?
如果我不能,我应该如何 wait/check 直到它 spring 上下文被加载?
如果从 jersey 上下文调用或从 调用 bean,一个简单的 HttpServlet 代码
编辑
Jersey 使用 jersey-spring3
依赖 jar 工作正常,所以 我的问题只是关于 Servlets 不受 Spring 控制
编辑 2
应用程序正在加载 spring 与 @entpnerd 建议的不同 article
它注册了一个实现 WebApplicationInitializer
的 Servlet
public class MyWebAppInitializer implements WebApplicationInitializer {
但在 web.xml
中也配置了 DispatcherServlet
怎么加载Spring后才加载DispatcherServlet
?
因为我们在它的 init 方法上添加了自动装配功能:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
在服务请求之前添加超时是最优选的解决方案,还是 class 加载中的调整可以解决这个问题?
编辑 3
我发现answers and answers注入了,但是没有为什么 Spring在Servlet之前加载
这个想法很简单,尽管实际实施可能会因 Spring 引导和 Jersery 初始化的确切方式而有所不同。
一个想法:
Spring boot 作为一个纯粹的运行时框架,就是正确加载应用程序上下文(从问题的角度来看)。
所以,最重要的是,当它被加载时,内存中某处有一个应用程序上下文,并且可以从该应用程序上下文访问 bean。
现在,由于您说 Jersey 不是 spring/spring-boot 驱动的,因此 Jersey 必须可以从某种静态全局变量访问此应用程序上下文,这很丑陋但应该可以工作。
所以这个想法有两个步骤:
- 将应用程序上下文引用放到一些可从 Jersey 访问的静态持有者。
- 从 Jersey 组件的一些基础架构级别代码中读取此值。
一个可能的实现
从技术上讲,第一步 可以通过实施某种 spring 启动侦听器来完成,它将应用程序上下文存储在某种单例中:
enum ApplicationContextHolder {
INSTANCE;
private ApplicationContext ctx;
void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}
ApplicationContext getCtx() {
return this.ctx;
}
}
// and a listener (spring boot provides many ways to register one, but the
// implementation should be something like this):
// The main point is that its managed by spring boot, and hence and access to
// the application context
class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContextHolder
.INSTANCE
.setApplicationContext(event.getApplicationContext());
}
}
现在 第 2 步 是:
class MyJerseyOrWhateverComponentThatWantsToAccessApplicationContext {
public void foo() {
ApplicationContext ctx = ApplicationContextHolder.INSTANCE.getCtx();
...
ctx.getBean(...);
}
}
因此,可行的解决方案可能分两个阶段进行:
- A Spring bean 获取
ApplicationContext
实例并将其发送到 Spring 上下文之外的静态单例。
- 您的独立 servlet 从静态单例中获取
ApplicationContext
实例并验证是否已加载正确的 bean。
以下面的代码为例:
SpringMetaBean.java
// @Component so that it's part of the Spring context
// Implement ApplicationContextAware so that the ApplicationContext will be loaded
// correctly
@Component
public class SpringMetaBean implements ApplicationContextAware {
private ApplicationContext appCtx;
public setApplicationContext(ApplicationContext appCtx) {
this.appCtx = appCtx;
}
// @PostConstruct so that when loaded into the Spring context, this method will
// automatically execute and notify ApplicationContextHolder with a reference to
// the ApplicationContext
@PostConstruct
public void setup() {
ApplicationContextHolder.set(this.appCtx);
}
}
ApplicationContextHolder.java
public class ApplicationContextHolder {
// ensure the reference is thread-safe because Spring and standalone Servlet will
// probably be running on different threads.
private final AtomicReference<ApplicationContext> appCtxContainer = new AtomicReference<>();
public void set(ApplicationContext appCtx) {
this.appCtxContainer.set(appCtx);
}
public ApplicationContext get() {
return this.appCtxContainer.get();
}
}
MyStandaloneServlet.java
public class MyStandaloneServlet {
// my request handler method
public void getResponse(HttpServletRequest rq) {
ApplicationContext springAppCtx = ApplicationContextHolder.get();
// if not null, we know that Spring has been loaded and we can dig into the
// application context.
}
}
我有 spring 应用程序以及 (jersey 2.6 classes 和 ) servlets .
我需要从 jersey/non spring 上下文中获取 Spring 个 bean,
类似question 建议在上下文的静态包装器中获取上下文
public static ApplicationContext getContext() {
return context;
}
如何确定上下文是否已加载或不为空?
如果我不能,我应该如何 wait/check 直到它 spring 上下文被加载?
如果从 jersey 上下文调用或从 调用 bean,一个简单的 HttpServlet 代码
编辑
Jersey 使用 jersey-spring3
依赖 jar 工作正常,所以 我的问题只是关于 Servlets 不受 Spring 控制
编辑 2
应用程序正在加载 spring 与 @entpnerd 建议的不同 article
它注册了一个实现 WebApplicationInitializer
public class MyWebAppInitializer implements WebApplicationInitializer {
但在 web.xml
中也配置了DispatcherServlet
怎么加载Spring后才加载DispatcherServlet
?
因为我们在它的 init 方法上添加了自动装配功能:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
在服务请求之前添加超时是最优选的解决方案,还是 class 加载中的调整可以解决这个问题?
编辑 3
我发现answers and answers注入了,但是没有为什么 Spring在Servlet之前加载
这个想法很简单,尽管实际实施可能会因 Spring 引导和 Jersery 初始化的确切方式而有所不同。
一个想法:
Spring boot 作为一个纯粹的运行时框架,就是正确加载应用程序上下文(从问题的角度来看)。
所以,最重要的是,当它被加载时,内存中某处有一个应用程序上下文,并且可以从该应用程序上下文访问 bean。
现在,由于您说 Jersey 不是 spring/spring-boot 驱动的,因此 Jersey 必须可以从某种静态全局变量访问此应用程序上下文,这很丑陋但应该可以工作。
所以这个想法有两个步骤:
- 将应用程序上下文引用放到一些可从 Jersey 访问的静态持有者。
- 从 Jersey 组件的一些基础架构级别代码中读取此值。
一个可能的实现
从技术上讲,第一步 可以通过实施某种 spring 启动侦听器来完成,它将应用程序上下文存储在某种单例中:
enum ApplicationContextHolder {
INSTANCE;
private ApplicationContext ctx;
void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}
ApplicationContext getCtx() {
return this.ctx;
}
}
// and a listener (spring boot provides many ways to register one, but the
// implementation should be something like this):
// The main point is that its managed by spring boot, and hence and access to
// the application context
class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContextHolder
.INSTANCE
.setApplicationContext(event.getApplicationContext());
}
}
现在 第 2 步 是:
class MyJerseyOrWhateverComponentThatWantsToAccessApplicationContext {
public void foo() {
ApplicationContext ctx = ApplicationContextHolder.INSTANCE.getCtx();
...
ctx.getBean(...);
}
}
因此,可行的解决方案可能分两个阶段进行:
- A Spring bean 获取
ApplicationContext
实例并将其发送到 Spring 上下文之外的静态单例。 - 您的独立 servlet 从静态单例中获取
ApplicationContext
实例并验证是否已加载正确的 bean。
以下面的代码为例:
SpringMetaBean.java
// @Component so that it's part of the Spring context
// Implement ApplicationContextAware so that the ApplicationContext will be loaded
// correctly
@Component
public class SpringMetaBean implements ApplicationContextAware {
private ApplicationContext appCtx;
public setApplicationContext(ApplicationContext appCtx) {
this.appCtx = appCtx;
}
// @PostConstruct so that when loaded into the Spring context, this method will
// automatically execute and notify ApplicationContextHolder with a reference to
// the ApplicationContext
@PostConstruct
public void setup() {
ApplicationContextHolder.set(this.appCtx);
}
}
ApplicationContextHolder.java
public class ApplicationContextHolder {
// ensure the reference is thread-safe because Spring and standalone Servlet will
// probably be running on different threads.
private final AtomicReference<ApplicationContext> appCtxContainer = new AtomicReference<>();
public void set(ApplicationContext appCtx) {
this.appCtxContainer.set(appCtx);
}
public ApplicationContext get() {
return this.appCtxContainer.get();
}
}
MyStandaloneServlet.java
public class MyStandaloneServlet {
// my request handler method
public void getResponse(HttpServletRequest rq) {
ApplicationContext springAppCtx = ApplicationContextHolder.get();
// if not null, we know that Spring has been loaded and we can dig into the
// application context.
}
}