获取Spring应用程序上下文

时间:2020-03-06 14:40:59  来源:igfitidea点击:

有没有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?

假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈将其向下传递给需要它的任何类,还是有一种方法可以让一个类请求先前创建的上下文? (我认为必须是一个单身人士?)

解决方案

这是一个不错的方法(不是我的,原始参考在这里:
http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html

我已经使用了这种方法,并且效果很好。基本上,它是一个简单的bean,其中包含对应用程序上下文的(静态)引用。通过在spring config中引用它,可以对其进行初始化。

看一下原始的参考,这很清楚。

看一下ContextSingletonBeanFactoryLocator。它提供了静态访问器来获取Spring的上下文,并假设它们已经以某些方式进行了注册。

它并不漂亮,而且可能比我们想要的还要复杂,但是它可以工作。

如果需要访问容器的对象是容器中的Bean,则只需实现BeanFactoryAware或者ApplicationContextAware接口。

如果容器外部的对象需要访问该容器,那么我已经对弹簧容器使用了标准的GoF单例模式。这样,应用程序中只有一个单例,其余都是容器中的所有单例bean。

在实施任何其他建议之前,请先问自己以下问题...

  • 为什么我要获取ApplicationContext?
  • 我可以有效地将ApplicationContext用作服务定位器吗?
  • 我可以完全避免访问ApplicationContext吗?

这些问题的答案在某些类型的应用程序(例如Web应用程序)中比在其他类型的应用程序中容易,但是无论如何都值得提出。

访问ApplicationContext确实违反了整个依赖注入原理,但是有时我们没有太多选择。

我相信我们可以使用SingletonBeanFactoryLocator。 beanRefFactory.xml文件将保存实际的applicationContext,它将类似于以下内容:

<bean id="mainContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
     <constructor-arg>
        <list>
            <value>../applicationContext.xml</value>
        </list>
     </constructor-arg>
 </bean>

从任何地方从applicationcontext获取bean的代码都是这样的:

BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference bf = bfl.useBeanFactory("mainContext");
SomeService someService = (SomeService) bf.getFactory().getBean("someService");

Spring团队不鼓励使用此类和yadayada,但在使用该类的地方它非常适合我。

如果我们使用Web应用程序,则还有另一种方法可以通过使用servletfilter和ThreadLocal来访问应用程序上下文而不使用单例。在过滤器中,我们可以使用WebApplicationContextUtils访问应用程序上下文,并将应用程序上下文或者所需的bean存储在TheadLocal中。

警告:如果我们忘记取消设置ThreadLocal,则在尝试取消部署应用程序时会遇到讨厌的问题!因此,我们应该对其进行设置,然后立即开始尝试以在final-part中取消设置ThreadLocal。

当然,这仍然使用单例:ThreadLocal。但是实际的bean不再需要了。甚至可以在请求范围内使用,如果应用程序中有多个WAR,并且EAR中有库,则此解决方案也可以使用。不过,我们可能会认为ThreadLocal的使用与纯单例的使用一样糟糕。 ;-)

也许Spring已经提供了类似的解决方案?我没有找到一个,但我不确定。