How to inject dependencies into a self-instantiated object in Spring?

JavaSpringDependency Injection

Java Problem Overview


Let's say we have a class:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

Then we created an object of this class (or some other framework have created the instance of this class).

MyClass obj = new MyClass();

Is it possible to still inject the dependencies? Something like:

applicationContext.injectDependencies(obj);

(I think Google Guice has something like this)

Java Solutions


Solution 1 - Java

You can do this using the autowireBean() method of AutowireCapableBeanFactory. You pass it an arbitrary object, and Spring will treat it like something it created itself, and will apply the various autowiring bits and pieces.

To get hold of the AutowireCapableBeanFactory, just autowire that:

private @Autowired AutowireCapableBeanFactory beanFactory;

public void doStuff() {
   MyBean obj = new MyBean();
   beanFactory.autowireBean(obj);
   // obj will now have its dependencies autowired.
}

Solution 2 - Java

You can also mark your MyClass with @Configurable annotation:

@Configurable
public class MyClass {
   @Autowired private AnotherClass instance
}

Then at creation time it will automatically inject its dependencies. You also should have <context:spring-configured/> in your application context xml.

Solution 3 - Java

Just got the same need and in my case it was already the logic inside non Spring manageable java class which had access to ApplicationContext. Inspired by scaffman. Solved by:

AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);

Solution 4 - Java

I wanted to share my solution that follows the @Configurable approach as briefly mentioned in @glaz666 answer because

  • The answer by @skaffman is nearly 10 years old, and that does not mean not good enough or does not work
  • The answer by @glaz666 is brief and didn't really help me solve my problem but, did point me in the right direction

My setup

  1. Spring Boot 2.0.3 with Spring Neo4j & Aop starts (which is irrelevant anyway)
  2. Instantiate a bean when Spring Boot is ready using @Configurable approach (using ApplicationRunner)
  3. Gradle & Eclipse

Steps

I needed to follow the steps below in order to get it working

  1. The @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false) to be placed on top of your Bean that is to be manually instantiated. In my case the Bean that is to be manually instantiated have @Autowired services hence, the props to above annotation.

  2. Annotate the Spring Boot's main XXXApplicaiton.java (or the file that is annotated with @SpringBootApplication) with the @EnableSpringConfigured and @EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)

  3. Add the dependencies in your build file (i.e. build.gradle or pom.xml depending on which one you use) compile('org.springframework.boot:spring-boot-starter-aop') and compile('org.springframework:spring-aspects:5.0.7.RELEASE')

  4. New+up your Bean that is annotated with @Configurable anywhere and its dependencies should be autowired.

*In regards to point #3 above, I am aware that the org.springframework.boot:spring-boot-starter-aop transitively pulls the spring-aop (as shown here mavencentral) but, in my case the Eclipse failed to resolve the @EnableSpringConfigured annotations hence, why I explicitly added the spring-aop dependency in addition to the starter. Should you face the same issue, just declare the dependency or go on adventure of figuring out

  • Is there a version conflict
  • Why the org.springframework.context.annotation.aspect.* is not available
  • Is your IDE setup properly
  • Etc etc.

Solution 5 - Java

I used a different approach. I had spring loaded beans that I wanted to call from my extended classes of a third-party library that created its own threads.

I used approach I found here https://confluence.jaytaala.com/display/TKB/Super+simple+approach+to+accessing+Spring+beans+from+non-Spring+managed+classes+and+POJOs

In the non-managed class:

{
    [...]
    SomeBean bc = (SomeBean) SpringContext.getBean(SomeBean.class);

    [...]
    bc.someMethod(...)
}

And then as a helper class in the main application:

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

@Component
public class SpringContext implements ApplicationContextAware
{
    private static ApplicationContext context;

    public static <T extends Object> T getBean(Class<T> beanClass)
    {   
        return context.getBean(beanClass);
    }

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

Solution 6 - Java

This worked for me:

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }
}

See more information: https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIgor MukhinView Question on Stackoverflow
Solution 1 - JavaskaffmanView Answer on Stackoverflow
Solution 2 - Javaglaz666View Answer on Stackoverflow
Solution 3 - Javarand0m86View Answer on Stackoverflow
Solution 4 - JavaRafView Answer on Stackoverflow
Solution 5 - JavacodeDrView Answer on Stackoverflow
Solution 6 - JavamrekView Answer on Stackoverflow