Java 获取Spring应用程序上下文
有没有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本 假设主类启动并初始化应用程序上下文,它是否需要通过调用堆栈将其传递给任何需要它的类,或者类是否有方法请求先前创建的上下文?(我想这一定是一个单例?这里有一个很好的方法(不是我的,原始参考是: 我使用了这种方法,它工作得很好。基本上,它是一个简单的bean,保存对应用程序上下文的(静态)引用。通过在spring配置中引用它,它就被初始化了 看看原始的ref,它非常清楚。看看。它提供了静态访问器来获取Spring的上下文,假设它们已经以某种方式注册Java 获取Spring应用程序上下文,java,spring,configuration,Java,Spring,Configuration,有没有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本 假设主类启动并初始化应用程序上下文,它是否需要通过调用堆栈将其传递给任何需要它的类,或者类是否有方法请求先前创建的上下文?(我想这一定是一个单例?这里有一个很好的方法(不是我的,原始参考是: 我使用了这种方法,它工作得很好。基本上,它是一个简单的bean,保存对应用程序上下文的(静态)引用。通过在spring配置中引用它,它就被初始化了 看看原始的ref,它非常清楚。看看。它提供了静态访问器来
它并不漂亮,也可能比您希望的更复杂,但它可以工作。如果需要访问容器的对象是容器中的bean,只需实现或接口即可
如果容器外的对象需要访问容器,我将使用一个用于spring容器。这样,您的应用程序中只有一个单例,其余的都是容器中的单例bean。在实施任何其他建议之前,请先问自己以下问题
- 为什么我要尝试获取ApplicationContext
- 我是否有效地将ApplicationContext用作服务定位器
- 我可以完全避免访问ApplicationContext吗
BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference bf = bfl.useBeanFactory("mainContext");
SomeService someService = (SomeService) bf.getFactory().getBean("someService");
../applicationContext.xml
从applicationcontext获取bean的代码如下:
BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference bf = bfl.useBeanFactory("mainContext");
SomeService someService = (SomeService) bf.getFactory().getBean("someService");
Spring团队不鼓励使用此类和yadayada,但它非常适合我使用它的地方。如果您使用web应用程序,还可以使用servletfilter和ThreadLocal访问应用程序上下文,而不使用Singleton。在该筛选器中,您可以使用WebApplicationContex访问应用程序上下文tUtils并将应用程序上下文或所需的bean存储在本地 警告:如果您忘记取消设置ThreadLocal,则在尝试取消部署应用程序时会遇到严重问题!因此,您应该设置它并立即开始在最后一部分中取消设置ThreadLocal的尝试
当然,这仍然使用单线程:线程本地。但是实际的bean不需要再使用。它甚至可以是请求范围,并且如果在应用程序中有多个在耳朵中的应用程序的冲突,这个解决方案也是有效的。但是,您可能会认为使用线程本地使用简单的单体是不好的。
也许Spring已经提供了类似的解决方案?我没有找到,但我不确定。您可以实现
ApplicationContextAware
或只使用@Autowired
:
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
SpringBean
将注入ApplicationContext
,在其中实例化此bean。例如,如果您的web应用程序具有相当标准的上下文层次结构:
main application context <- (child) MVC context
main application context请注意,通过将当前ApplicationContext
或ApplicationContext
本身的任何状态存储在静态变量中(例如使用单例模式),如果使用Spring test,将使测试变得不稳定和不可预测。这是因为SpringTest在同一个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被创建为TestContext
(这里是ApplicationContext
)从测试A中恢复。现在您得到了一个指向另一个ApplicationContext
的静态变量,而不是当前为您的测试保存bean的变量。请注意;下面的代码将创建新的应用程序上下文,而不是使用已加载的应用程序上下文
private static final ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
还请注意,beans.xml
应该是src/main/resources
的一部分,这意味着在战争中它是WEB\u INF/classes
的一部分,其中真正的应用程序将通过applicationContext.xml
加载
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>META-INF/spring/applicationContext.xml</param-value>
</context-param>
来源:我知道这个问题已经得到了回答,但我想与大家分享我为检索Spring上下文而编写的Kotlin代码
我不是专家,因此我愿意接受批评、评论和建议:
现在,spring上下文是公开可用的,可以独立于上下文(junit测试、bean、手动实例化类)调用相同的方法,就像在这个Java Servlet上一样:
@WebServlet(name = "MyWebHook", value = "/WebHook")
public class MyWebServlet extends HttpServlet {
private MyBean byBean
= SpringUtils.INSTANCE.ctx(this, true).getBean(MyBean.class);
public MyWebServlet() {
}
}
在Spring应用程序中获取应用程序上下文的方法有很多,如下所示:
通过ApplicationContextAware:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class AppContextProvider implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
@Autowired
private ApplicationContext applicationContext;
她
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class AppContextProvider implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
@Autowired
private ApplicationContext applicationContext;
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
private static ApplicationContext context;
// I believe this only runs during an embedded Tomcat with `mvn spring-boot:run`.
// I don't believe it runs when deploying to Tomcat on AWS.
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
DataSource dataSource = context.getBean(javax.sql.DataSource.class);
Logger.getLogger("Application").info("DATASOURCE = " + dataSource);
@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;
}
}
@Component
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
@Component
public class SpringContext implements ApplicationContextAware{
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws
BeansException {
this.applicationContext=applicationContext;
}
}
applicationContext.getBean(String serviceName,Interface.Class)
@Component
public class MyBean {
...
private static MyBean singleton = null;
public MyBean() {
...
singleton = this;
}
...
public void someMethod() {
...
}
...
public static MyBean get() {
return singleton;
}
}
MyBean.get().someMethod();