【问题标题】:Spring get current ApplicationContextSpring获取当前ApplicationContext
【发布时间】:2014-03-16 15:48:23
【问题描述】:

我正在为我的 Web 应用程序使用 Spring MVC。我的豆子写在“spring-servlet.xml”文件中

现在我有一个类 MyClass,我想使用 spring bean 访问这个类

spring-servlet.xml我写了以下

<bean id="myClass" class="com.lynas.MyClass" />

现在我需要使用ApplicationContext 访问它

ApplicationContext context = ??

这样我就可以了

MyClass myClass = (MyClass) context.getBean("myClass");

如何做到这一点??

【问题讨论】:

  • @Autowired MyClass myClass 应该可以胜任!

标签: java spring spring-mvc servlets


【解决方案1】:

只需注入它..

@Autowired
private ApplicationContext appContext;

或者实现这个接口:ApplicationContextAware

【讨论】:

  • 下面的ApplicationContextProvider.java 答案看起来是最可靠的解决方案。
  • 每次都返回NULL。在这里提一下,我是在一个既不是“@RestController”也不是“@Component”的普通类中执行此操作
  • 根据 Spring 文档,由于某些问题,最好避免使用 @Autowired。这是链接spring.io/understanding/application-context。最好的选择是实现 ApplicationContextAware 接口。
  • 我不确定这如何回答这个问题。您不能在不受 Spring 管理的对象中自动连接应用程序上下文。
【解决方案2】:

我认为link 展示了在任何地方获取应用程序上下文的最佳方式,即使在非 bean 类中也是如此。我觉得它非常有用。希望对你也一样。下面是它的抽象代码

新建一个类ApplicationContextProvider.java

package com.java2novice.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware{

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
    }
}

在 application-context.xml 中添加一个条目

<bean id="applicationContextProvider"
                        class="com.java2novice.spring.ApplicationContextProvider"/>

在注释情况下(而不是 application-context.xml)

@Component
public class ApplicationContextProvider implements ApplicationContextAware{
...
}

获取这样的上下文

TestBean tb = ApplicationContextProvider.getApplicationContext().getBean("testBean", TestBean.class);

干杯!!

【讨论】:

  • 我的编码类似于 Vivek。但是每次我需要从上下文中调用 getBean() 时,我都会避免创建新的 ApplicationContextProvider()。我所做的是拥有 static ApplicationContextProvider.getApplicationContext() 方法。然后,当需要当前应用上下文时,我调用:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
  • 是的帕尼尼午餐,那还是不错的。根据你的建议,我会这样改变。 :)
  • ApplicationContextProvider上添加@Component可以避免在aplication-context.xml中配置
  • 注意:上下文的getter和setter应该同步。您将避免很多专门针对单元/集成测试的头痛。在我的例子中,类似的 ApplicationContextProvider 持有旧的上下文(来自以前的集成测试),这导致了很多棘手的错误。
【解决方案3】:

如果您需要从 HttpServlet 中访问上下文,而该 HttpServlet 本身并没有被 Spring 实例化(因此@Autowire 和 ApplicationContextAware 都不起作用)...

WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

至于其他一些回复,请三思而后行:

new ClassPathXmlApplicationContext("..."); // are you sure?

...因为这不会为您提供当前上下文,而是为您创建它的另一个实例。这意味着 1) 大量内存和 2) bean 在这两个应用程序上下文之间不共享。

【讨论】:

  • SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this) - 在 Liferay portlet 操作过滤器的 init() 方法中为我完成了这项工作。
  • 太棒了,processInjectionBasedOnCurrentContext 完成了我需要的所有工作。非常感谢@Jaroslav
  • ApplicationContextAware 对我有用,当它像 Vivek 的解决方案一样用@Component 注释时(我通过扩展 AbstractContextLoaderInitializer / createRootApplicationContext 手动初始化 Spring 上下文)
  • 被警告... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);不会立即发生,因此您不能将其用作构造函数中的第一行。
  • 这在经典的 Java webapp(不是 spring-mvc 管理的)中完美运行。
【解决方案4】:

如果你正在实现一个没有被 Spring 实例化的类,比如你可以使用的 JsonDeserializer:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);

【讨论】:

  • 这对我不起作用。我的课不在 Spring 上下文中。我尝试使用您的代码,但它给了我一个 null 作为响应。我说的是ContextLoader.getCurrentWebApplicationContext()
【解决方案5】:

将此添加到您的代码中

@Autowired
private ApplicationContext _applicationContext;

//Add below line in your calling method
MyClass class = (MyClass) _applicationContext.getBean("myClass");

// Or you can simply use this, put the below code in your controller data member declaration part.
@Autowired
private MyClass myClass;

这只会将 myClass 注入到您的应用程序中

【讨论】:

    【解决方案6】:

    基于 Vivek 的回答,但我认为以下会更好:

    @Component("applicationContextProvider")
    public class ApplicationContextProvider implements ApplicationContextAware {
    
        private static class AplicationContextHolder{
    
            private static final InnerContextResource CONTEXT_PROV = new InnerContextResource();
    
            private AplicationContextHolder() {
                super();
            }
        }
    
        private static final class InnerContextResource {
    
            private ApplicationContext context;
    
            private InnerContextResource(){
                super();
            }
    
            private void setContext(ApplicationContext context){
                this.context = context;
            }
        }
    
        public static ApplicationContext getApplicationContext() {
            return AplicationContextHolder.CONTEXT_PROV.context;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext ac) {
            AplicationContextHolder.CONTEXT_PROV.setContext(ac);
        }
    }
    

    从实例方法写入静态字段是一种不好的做法,如果正在操作多个实例,则很危险。

    【讨论】:

    • org.springframework.core.io.ContextResource接口。我建议为内部类 ContextResource 选择不同的名称以避免混乱。
    • @AlexanderRadchenko 好的,我把它改成了 InnerContextResource
    【解决方案7】:

    在 Spring 应用程序中获取应用程序上下文的方法有很多。这些在下面给出:

    1. 通过 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;
      }
      }
      

    这里setApplicationContext(ApplicationContext applicationContext)方法你会得到applicationContext

    1. 通过自动接线

      @Autowired
      private ApplicationContext applicationContext;
      

    这里@Autowired 关键字将提供applicationContext。

    欲了解更多信息,请访问this thread

    谢谢:)

    【讨论】:

      【解决方案8】:

      如果您的类不是 RestController 或配置类,即使在添加 @Autowire 之后,applicationContext 对象仍为 null。尝试使用以下创建新类,它工作正常:

      @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)
      

      【讨论】:

        【解决方案9】:

        另一种方法是通过servlet注入applicationContext。

        这是一个使用 Spring Web 服务时如何注入依赖项的示例。

        <servlet>
                <servlet-name>my-soap-ws</servlet-name>
                <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
                <init-param>
                    <param-name>transformWsdlLocations</param-name>
                    <param-value>false</param-value>
                </init-param>
                <init-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>classpath:my-applicationContext.xml</param-value>
                </init-param>
                <load-on-startup>5</load-on-startup>
        
        </servlet>
        

        另一种方法是在您的 web.xml 中添加应用程序上下文,如下所示

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/classes/my-another-applicationContext.xml
                classpath:my-second-context.xml
            </param-value>
        </context-param>
        

        基本上你是想告诉 servlet 它应该寻找在这些上下文文件中定义的 bean。

        【讨论】:

          【解决方案10】:

          第一步:在类中注入以下代码

          @Autowired
          private ApplicationContext _applicationContext;
          

          第 2 步:编写 Getter 和 Setter

          第三步:在定义bean的xml文件中定义autowire="byType"

          【讨论】:

            【解决方案11】:

            比使用@Autowired 更好的是让它通过构造函数注入。找一些参数 pro 构造函数注入here

            @Component
            public class MyClass{
              private final ApplicationContext applicationContext;
            
              public MyClass(ApplicationContext applicationContext){
                this.applicationContext = applicationContext;
              }
            
              //here will be your methods using the applicationcontext
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-02-02
              • 1970-01-01
              • 2023-03-07
              • 2019-12-17
              • 2014-06-10
              • 1970-01-01
              • 2018-11-21
              相关资源
              最近更新 更多