Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 获取Spring应用程序上下文_Java_Spring_Configuration - Fatal编程技术网

Java 获取Spring应用程序上下文

Java 获取Spring应用程序上下文,java,spring,configuration,Java,Spring,Configuration,有没有一种方法可以在Spring应用程序中静态/全局地请求ApplicationContext的副本 假设主类启动并初始化应用程序上下文,它是否需要通过调用堆栈将其传递给任何需要它的类,或者类是否有方法请求先前创建的上下文?(我想这一定是一个单例?这里有一个很好的方法(不是我的,原始参考是: 我使用了这种方法,它工作得很好。基本上,它是一个简单的bean,保存对应用程序上下文的(静态)引用。通过在spring配置中引用它,它就被初始化了 看看原始的ref,它非常清楚。看看。它提供了静态访问器来

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

假设主类启动并初始化应用程序上下文,它是否需要通过调用堆栈将其传递给任何需要它的类,或者类是否有方法请求先前创建的上下文?(我想这一定是一个单例?

这里有一个很好的方法(不是我的,原始参考是:

我使用了这种方法,它工作得很好。基本上,它是一个简单的bean,保存对应用程序上下文的(静态)引用。通过在spring配置中引用它,它就被初始化了

看看原始的ref,它非常清楚。

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


它并不漂亮,也可能比您希望的更复杂,但它可以工作。

如果需要访问容器的对象是容器中的bean,只需实现或接口即可


如果容器外的对象需要访问容器,我将使用一个用于spring容器。这样,您的应用程序中只有一个单例,其余的都是容器中的单例bean。

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

  • 为什么我要尝试获取ApplicationContext
  • 我是否有效地将ApplicationContext用作服务定位器
  • 我可以完全避免访问ApplicationContext吗
这些问题的答案在某些类型的应用程序(例如Web应用程序)中比在其他应用程序中更容易回答,但无论如何都值得一问

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

我相信您可以使用。beanrefactory.xml文件将保存实际的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();