是否有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?
假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈向下传递给任何需要它的类,或者类是否有一种方法来请求先前创建的上下文?(我假设它必须是单例的?)
是否有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本?
假设主类启动并初始化了应用程序上下文,它是否需要通过调用堆栈向下传递给任何需要它的类,或者类是否有一种方法来请求先前创建的上下文?(我假设它必须是单例的?)
当前回答
在Spring bean中进行自动装配,如下所示:
@Autowired
private ApplicationContext appContext;
您将得到ApplicationContext对象。
其他回答
在你执行任何其他建议之前,问自己这些问题…
为什么我要获取ApplicationContext? 我是否有效地使用ApplicationContext作为服务定位器? 我可以完全避免访问ApplicationContext吗?
在某些类型的应用程序(例如Web应用程序)中,这些问题的答案比在其他应用程序中更容易,但无论如何都值得一问。
访问ApplicationContext确实违反了整个依赖注入原则,但有时您没有太多选择。
即使在添加了@Autowire之后,如果你的类不是一个RestController或Configuration class, applicationContext对象仍然是空的。尝试用下面创建新类,它工作正常:
@Component
public class SpringContext implements ApplicationContextAware{
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws
BeansException {
this.applicationContext=applicationContext;
}
}
然后,你可以在同一个类中根据你的需要实现一个getter方法,比如通过:
applicationContext.getBean(String serviceName,Interface.Class)
如果你使用的是web应用,还有另一种不使用单例的方式来访问应用上下文,那就是使用servletfilter和ThreadLocal。在过滤器中,您可以使用WebApplicationContextUtils访问应用程序上下文,并在TheadLocal中存储应用程序上下文或所需的bean。
警告:如果你忘记撤消ThreadLocal,你将在尝试撤消应用程序时遇到严重的问题!因此,您应该设置它,并立即开始尝试,在最后部分取消对ThreadLocal的设置。
当然,这仍然使用一个单例:ThreadLocal。但实际的豆子不需要再这样了。它甚至可以是请求范围的,如果应用程序中有多个war,并且EAR中的库也可以使用此解决方案。不过,您可能会认为ThreadLocal的这种使用与普通单例的使用一样糟糕。;-)
也许Spring已经提供了类似的解决方案?我没有找到,但我不确定。
方法1:您可以通过实现ApplicationContextAware接口来注入ApplicationContext。参考链接。
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
方法2:在任何spring托管bean中自动装配应用程序上下文。
@Component
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
参考链接。
你可以实现ApplicationContextAware或者使用@Autowired:
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
SpringBean将注入ApplicationContext,在其中实例化此bean。例如,如果你有一个非常标准的上下文层次结构的web应用程序:
main application context <- (child) MVC context
并且SpringBean是在主上下文中声明的,它将被注入主上下文; 否则,如果它是在MVC上下文中声明的,它将被注入MVC上下文。