是否有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?
假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈向下传递给任何需要它的类,或者类是否有一种方法来请求先前创建的上下文?(我假设它必须是单例的?)
是否有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?
假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈向下传递给任何需要它的类,或者类是否有一种方法来请求先前创建的上下文?(我假设它必须是单例的?)
当前回答
请注意;下面的代码将创建新的应用程序上下文,而不是使用已经加载的上下文。
private static final ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
还要注意,beans.xml应该是src/main/resources的一部分,这意味着在war中它是WEB_INF/classes的一部分,其中真正的应用程序将通过Web.xml中提到的applicationContext.xml加载。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>
在ClassPathXmlApplicationContext构造函数中很难提及applicationContext.xml路径。ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")无法定位文件。
因此,最好通过使用注释来使用现有的applicationContext。
@Component
public class OperatorRequestHandlerFactory {
public static ApplicationContext context;
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) {
context = applicationContext;
}
}
其他回答
请注意,通过将当前ApplicationContext的任何状态或ApplicationContext本身存储在一个静态变量中(例如使用单例模式),如果使用Spring-test,您将使您的测试不稳定且不可预测。这是因为Spring-test在同一个JVM中缓存和重用应用程序上下文。例如:
测试运行并使用@ContextConfiguration({"classpath:foo.xml"})进行注释。 测试B运行并使用@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})进行注释 运行测试C,并且使用@ContextConfiguration({"classpath:foo.xml"})进行注释
当测试A运行时,将创建一个ApplicationContext,并且任何实现ApplicationContextAware或自动装配ApplicationContext的bean都可能写入静态变量。
当测试B运行时,同样的事情也会发生,并且静态变量现在指向测试B的ApplicationContext
当测试C运行时,没有bean被创建,因为测试A的TestContext(这里是ApplicationContext)被重用了。现在,您得到了一个指向另一个ApplicationContext的静态变量,而不是当前为您的测试保存bean的ApplicationContext。
你可以实现ApplicationContextAware或者使用@Autowired:
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
SpringBean将注入ApplicationContext,在其中实例化此bean。例如,如果你有一个非常标准的上下文层次结构的web应用程序:
main application context <- (child) MVC context
并且SpringBean是在主上下文中声明的,它将被注入主上下文; 否则,如果它是在MVC上下文中声明的,它将被注入MVC上下文。
如果你使用的是web应用,还有另一种不使用单例的方式来访问应用上下文,那就是使用servletfilter和ThreadLocal。在过滤器中,您可以使用WebApplicationContextUtils访问应用程序上下文,并在TheadLocal中存储应用程序上下文或所需的bean。
警告:如果你忘记撤消ThreadLocal,你将在尝试撤消应用程序时遇到严重的问题!因此,您应该设置它,并立即开始尝试,在最后部分取消对ThreadLocal的设置。
当然,这仍然使用一个单例:ThreadLocal。但实际的豆子不需要再这样了。它甚至可以是请求范围的,如果应用程序中有多个war,并且EAR中的库也可以使用此解决方案。不过,您可能会认为ThreadLocal的这种使用与普通单例的使用一样糟糕。;-)
也许Spring已经提供了类似的解决方案?我没有找到,但我不确定。
在Spring bean中进行自动装配,如下所示:
@Autowired
private ApplicationContext appContext;
您将得到ApplicationContext对象。
这里有一个很好的方法(不是我的,原始参考在这里: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
我使用过这种方法,效果很好。基本上,它是一个简单的bean,包含对应用程序上下文的(静态)引用。通过在spring配置中引用它来初始化它。
看看原来的裁判,非常清楚。