'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
- Spring Boot 2.0.3 with
Spring Neo4j & Aop starts(which is irrelevant anyway) - Instantiate a bean when
Spring Bootis ready using@Configurableapproach (usingApplicationRunner) - Gradle & Eclipse
Steps
I needed to follow the steps below in order to get it working
- The
@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)to be placed on top of yourBeanthat is to be manually instantiated. In my case theBeanthat is to be manually instantiated have@Autowiredservices hence, the props to above annotation. - Annotate the Spring Boot's main
XXXApplicaiton.java(or the file that is annotated with@SpringBootApplication) with the@EnableSpringConfiguredand@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED) - 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')andcompile('org.springframework:spring-aspects:5.0.7.RELEASE') - New+up your
Beanthat is annotated with@Configurableanywhere 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 |
