130

I am using Spring MVC for my web application. My beans are written in "spring-servlet.xml" file

Now I have a class MyClass and i want to access this class using spring bean

In the spring-servlet.xml i have written following

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

Now i need to access this using ApplicationContext

ApplicationContext context = ??

So that I can do

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

How to do this??

LynAs
  • 6,407
  • 14
  • 48
  • 83

11 Answers11

189

Simply inject it..

@Autowired
private ApplicationContext appContext;

or implement this interface: ApplicationContextAware

gipinani
  • 14,038
  • 12
  • 56
  • 85
  • Maybe this can work: http://stackoverflow.com/questions/11682858/spring-how-to-get-hold-of-application-context-in-webapp-and-standalone-program – gipinani Feb 17 '14 at 11:23
  • 1
    The following `ApplicationContextProvider.java` answer looks to be the most reliable solution for this. – Ionut Jan 17 '16 at 12:32
  • 5
    It's returning NULL everytime. To mention here that i am doing this inside a normal class that is neither a "@RestController" nor a "@Component" – zulkarnain shah Aug 30 '17 at 09:40
  • 1
    According to Spring documentation, it's best to avoid @Autowired due to some issues. Here is the link https://spring.io/understanding/application-context. The best option is to go with implementing the ApplicationContextAware interface. – Durja Dec 24 '18 at 04:09
  • 3
    I am not sure how does this answers the question. You cannot auto wire the application context in the object not managed by Spring. – TriCore Feb 09 '21 at 06:00
111

I think this link demonstrates the best way to get application context anywhere, even in the non-bean class. I find it very useful. Hope its the same for you. The below is the abstract code of it

Create a new class 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;
    }
}

Add an entry in application-context.xml

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

In annotations case (instead of application-context.xml)

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

Get the context like this

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

Cheers!!

Bruno Carletti
  • 273
  • 1
  • 3
  • 18
Vivek
  • 3,523
  • 2
  • 25
  • 41
  • 2
    I coded similar to Vivek. But I avoid creating new ApplicationContextProvider() everytime I need to call the getBean() from the context. What I did was to have **static** `ApplicationContextProvider.getApplicationContext()` method. Then, when it is time to need the current app context, I invoke: `ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()` – Panini Luncher Mar 26 '15 at 19:47
  • 1
    Yes Panini Luncher, that would still be good. As per your suggestion i will change it that way. :) – Vivek Apr 07 '15 at 10:23
  • 4
    Add `@Component` on `ApplicationContextProvider` can avoid configuration in `aplication-context.xml` – bluearrow Nov 07 '16 at 15:56
  • 1
    Note: getter and setter of context should be synchronized. You will avoid a lot of headache specially for unit/integration-tests. In my case similar ApplicationContextProvider held old context(from previous integration test) that caused a lot of tricky bugs. – Oleksandr_DJ Jun 26 '18 at 19:54
53

In case you need to access the context from within a HttpServlet which itself is not instantiated by Spring (and therefore neither @Autowire nor ApplicationContextAware will work)...

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

or

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

As for some of the other replies, think twice before you do this:

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

...as this does not give you the current context, rather it creates another instance of it for you. Which means 1) significant chunk of memory and 2) beans are not shared among these two application contexts.

Jaroslav Záruba
  • 4,694
  • 5
  • 39
  • 58
  • SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this) - did the job for me in the Liferay portlet action filter's init() method. – Igor Baiborodine Apr 06 '16 at 12:08
  • Awesome, the processInjectionBasedOnCurrentContext did all the job I needed. Many thanks @Jaroslav – Jad B. Jan 02 '18 at 08:56
  • ApplicationContextAware DOES work for me, when it is annotated with @Component as in Vivek's solution (I am initializing Spring context manually via extending AbstractContextLoaderInitializer / createRootApplicationContext) – hello_earth Jan 29 '19 at 14:45
  • Be warned... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); doesn't happen immediately, so you can't use it as the first line in your constructor for example. – SledgeHammer Jan 11 '20 at 18:17
  • This works perfectly in a classical Java webapp (not spring-mvc managed). – lainatnavi Aug 24 '20 at 11:08
  • Where should SpringBeanAutowiringSupport be called in my class? SledgeHammer says "not first line in constructor"... if not then where? – Alex Worden Apr 25 '21 at 16:23
35

If you're implementing a class that's not instantiated by Spring, like a JsonDeserializer you can use:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
buræquete
  • 14,226
  • 4
  • 44
  • 89
rzymek
  • 9,064
  • 2
  • 45
  • 59
  • 12
    It doesn't work to me. My class is out of Spring context. I've tried to use your code but it give me a **null** as response. I'm talking about `ContextLoader.getCurrentWebApplicationContext()` – R. Karlus Nov 08 '16 at 20:37
10

Add this to your code

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

This will simply inject myClass into your application

buræquete
  • 14,226
  • 4
  • 44
  • 89
Hitesh Kumar
  • 643
  • 1
  • 6
  • 22
8

based on Vivek's answer, but I think the following would be better:

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

Writing from an instance method to a static field is a bad practice and dangerous if multiple instances are being manipulated.

Juan
  • 544
  • 6
  • 20
1

Even after adding @Autowire if your class is not a RestController or Configuration Class, the applicationContext object was coming as null. Tried Creating new class with below and it is working fine:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

you can then implement a getter method in the same class as per your need like getting the Implemented class reference by:

    applicationContext.getBean(String serviceName,Interface.Class)
0

Step 1 :Inject following code in class

@Autowired
private ApplicationContext _applicationContext;

Step 2 : Write Getter & Setter

Step 3: define autowire="byType" in xml file in which bean is defined

Ashish Aggarwal
  • 3,018
  • 2
  • 23
  • 46
0

Another way is to inject applicationContext through servlet.

This is an example of how to inject dependencies when using Spring web services.

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

Alternate way is to add application Context in your web.xml as shown below

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

Basically you are trying to tell servlet that it should look for beans defined in these context files.

Ashish Aggarwal
  • 3,018
  • 2
  • 23
  • 46
vsingh
  • 6,365
  • 3
  • 53
  • 57
0

Even better than having it with @Autowired is to let it be injected via constructor. Find some arguments pro constructor injection here

@Component
public class MyClass{
  private final ApplicationContext applicationContext;

  public MyClass(ApplicationContext applicationContext){
    this.applicationContext = applicationContext;
  }

  //here will be your methods using the applicationcontext
}
hecko84
  • 1,224
  • 1
  • 16
  • 29
0

If your main() method has SpringApplication.run() method then you should remember ,it by default, returns the ApplicationContext object. See this. Meaning,you can do this:

ApplicationContext context=SpringApplication.run(YourMainMethodClassName.class,args);
MyClass obj=(MyClass)context.getBean(MyClass.class);