确保从非弹簧环境加载弹簧豆
我有弹簧应用程序(jersey2.6类和servlet)。
我需要从jersey / non spring环境中获取Spring bean,
类似的问题建议在上下文的静态包装中获取上下文
public static ApplicationContext getContext() { return context; }
如何确定上下文已加载或不为null?
如果我不能,我应该等待/检查,直到加载弹簧上下文?
在从泽西上下文调用或从简单的HttpServlet代码调用bean的情况下
编辑
Jersey使用jersey-spring3
依赖jar工作正常,所以我的问题只是关于Servlets的Spring控件
编辑2
该应用程序正在加载不同于@entpnerd建议文章的弹簧
它注册了一个实现WebApplicationInitializer
的Servlet
public class MyWebAppInitializer implements WebApplicationInitializer {
但是也在web.xml中配置了DispatcherServlet
如何在Spring加载后加载DispatcherServlet
?
因为我们在其init方法上添加了自动assemblyfunction:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()) .getAutowireCapableBeanFactory().autowireBean(this);
在提供请求之前添加超时是最喜欢的解决方案还是在类加载中有一个可以处理它的调整?
编辑3
我找到了注入的答案和答案 ,但不是为什么在Servlet之前加载Spring。
这个想法很简单,虽然实际的实现可能会有所不同,具体取决于Spring引导和Jersery初始化的确切方式。
一个主意:
Spring启动,作为一个纯粹的运行时框架,就是正确加载应用程序上下文(从问题的角度来看)。
因此,底线,当它加载时,内存中的某个应用程序上下文,并且可以从此应用程序上下文中访问bean。
现在,既然你说Jersey不是spring / spring-boot驱动的,那么这个应用程序上下文必须可以通过Jersey从某种静态全局变量中获得,它非常难看但是应该可行。
所以这个想法有两个步骤:
- 将应用程序上下文引用放到可从Jersey访问的某个静态持有者。
- 在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 { @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContextHolder .INSTANCE .setApplicationContext(event.getApplicationContext()); } }
现在步骤2是:
class MyJerseyOrWhateverComponentThatWantsToAccessApplicationContext { public void foo() { ApplicationContext ctx = ApplicationContextHolder.INSTANCE.getCtx(); ... ctx.getBean(...); } }
因此,可行的解决方案可能分两个阶段进行:
- Spring bean获取
ApplicationContext
实例并将其发送到Spring上下文之外的静态单例。 - 您的独立servlet从静态单例获取
ApplicationContext
实例,并validation是否已加载正确的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 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. } }