我有弹簧应用程序(球衣2.6类和servlet)。
我需要从中获取Spring bean 球衣/ 非春天背景,
类似的question建议在上下文的静态包装中获取上下文
public static ApplicationContext getContext() {
return context;
}
如何确定上下文已加载或不为null?
如果我不能,我应该等待/检查,直到它加载弹簧上下文?
如果是来电话 泽西上下文或调用bean来自 一个简单的HttpServlet代码
编辑
Jersey使用jersey-spring3
依赖jar工作正常,所以我的问题只是关于Servlets的Spring控件
编辑2
该应用程序正在加载不同于@entpnerd建议的article 的弹簧
它注册了一个实现WebApplicationInitializer
的Servlet
public class MyWebAppInitializer implements WebApplicationInitializer {
但是也要在web.xml中配置DispatcherServlet
DispatcherServlet
如何才能在Spring加载后加载?
因为我们在其init方法上添加了自动装配功能:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
在提供请求之前添加超时是最喜欢的解决方案还是在类加载中有一个可以处理它的调整?
编辑3
这个想法很简单,虽然实际的实现可能会有所不同,具体取决于Spring引导和Jersery初始化的确切方式。
一个主意:
Spring启动,作为一个纯粹的运行时框架,就是正确加载应用程序上下文(从问题的角度来看)。
所以,底线,当它加载时,内存中有一个应用程序上下文,并且可以从这个应用程序上下文中访问bean。
现在,既然你说Jersey不是spring / spring-boot驱动的,那么这个应用程序上下文必须可以通过Jersey的某种静态全局变量来访问,它非常难看但是应该可行。
所以这个想法有两个步骤:
可能的实施
从技术上讲,第一步可以通过实现某种弹簧启动监听器来完成,该监听器将应用程序上下文存储在某种单例中:
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(...);
}
}
因此,可行的解决方案可能分两个阶段进行:
ApplicationContext
实例并将其发送到Spring上下文之外的静态单例。ApplicationContext
实例,并验证是否已加载正确的bean。请考虑以下代码作为示例:
spring meta bean.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);
}
}
application context holder.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();
}
}
my standalone Servlet.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.
}
}