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

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)



Solution 1:[1]

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 2:[2]

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 3:[3]

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 4:[4]

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 5:[5]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 glaz666
Solution 2 rand0m86
Solution 3 Raf
Solution 4 codeDr
Solution 5 mrek