Spring获取当前的ApplicationContext


105

我将Spring MVC用于我的Web应用程序。我的豆子写在“ 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");

这该怎么做??


3
@Autowired MyClass myClass应该做的!
Mannekenpix 2014年

Answers:


160

只需注入即可。

@Autowired
private ApplicationContext appContext;

或实现此接口:ApplicationContextAware



以下ApplicationContextProvider.java答案似乎是对此最可靠的解决方案。
Ionut

1
每次都返回NULL。这里要提到的是,我是在一个既不是“ @RestController”也不是“ @Component”的普通类中执行此操作的
zulkarnain shah

1
根据Spring文档,由于某些问题,最好避免使用@Autowired。这是链接spring.io/understanding/application-context。最好的选择是实现ApplicationContextAware接口。
Durja Arai

89

我认为此链接展示了即使在非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);

干杯!!


1
我的编码类似于Vivek。但是我避免每次需要从上下文调用getBean()时都创建新的ApplicationContextProvider()。我所做的是使用静态 ApplicationContextProvider.getApplicationContext()方法。然后,当需要当前应用程序上下文时,我调用:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher,2015年

1
是的Panini Luncher,那还是不错的。根据您的建议,我将以这种方式进行更改。:)
Vivek

4
添加@ComponentApplicationContextProvider可避免配置aplication-context.xml
bluearrow

1
注意:上下文的getter和setter应该同步。您将避免很多特别针对单元/集成测试的头痛。在我的案例中,类似的ApplicationContextProvider保留了旧的上下文(来自先前的集成测试),这导致了许多棘手的错误。
Oleksandr_DJ

43

万一您需要从本身未由Spring实例化HttpServlet中访问上下文(因此@Autowire或ApplicationContextAware均不起作用)...

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

要么

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

至于其他一些答复,在执行此操作之前请三思:

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

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


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this)-在Liferay Portlet操作筛选器的init()方法中为我完成了工作。
Igor Baiborodine '16

太棒了,processInjectionBasedOnCurrentContext完成了我需要的所有工作。非常感谢@Jaroslav
亚德B.

在Vivek解决方案中使用@Component进行注释时,ApplicationContextAware确实对我
有用

警告... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 不会立即发生,因此您不能将其用作构造函数的第一行。
SledgeHammer

31

如果您实现的是Spring尚未实例化的类,例如JsonDeserializer,则可以使用:

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

8
它对我不起作用。我的课不在Spring上下文范围内。我尝试使用您的代码,但是它给了我null作为响应。我正在谈论ContextLoader.getCurrentWebApplicationContext()
R. Karlus

9

将此添加到您的代码

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

1

在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。

有关更多信息,请访问此线程

谢谢 :)


0

另一种方法是通过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。



0

即使在添加@Autowire之后,如果您的类不是RestController或Configuration类,applicationContext对象也将变为null。尝试使用下面的方法创建新类,并且运行良好:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
     BeansException {
    this.applicationContext=applicationContext;
   }
 }

然后,您可以根据需要在同一类中实现getter方法,例如通过以下方式获取Implemented类引用:

    applicationContext.getBean(String serviceName,Interface.Class)

-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

然后,您可以检索Bean:

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

参考:springbyexample.org


25
该答案没有提供您当前的上下文,而是创建了另一个实例。
JaroslavZáruba'15
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.