In my project I am surprised to see that Spring (4.3) seems to attempt to autowire dependencies for classes even when they are manually instantiated.
MyClass.java
(note Lombok annotations):
@NoArgsConstructor
@AllArgsConstructor
public class MyClass {
@Autowired
private MyClassDependency dependency;
}
MyClassDependency.java
uses a factory method and no Spring annotations:
public class MyClassDependency {
public static MyClassDependency create() { return new MyClassDependency(); }
}
Spring config resulting in NoSuchBeanDefinitionException
:
@Configuration
public class SpringConfig {
@Bean
public MyClass myClass() {
return new MyClass(MyClassDependency.create());
}
}
Providing the bean makes Spring happy:
@Configuration
public class SpringConfig {
@Bean
public MyClass myClass() {
return new MyClass(); // let autowire inject dependencies
}
@Bean
public MyClassDependency myClassDependency() {
return MyClassDependency.create();
}
}
This was a big surprise to me. I'd like to have the simpler first version of the config... Where is this behavior coming from / controlled? (It's possible that I missed it or pulled it from some dependencies).
PS: To clarify, MyClass
code is outside of my control but I can change Spring config. I am looking to understand how Spring intercepts the constructor call withing a bean method and whether constructor can be used instead.
@Inject and @Autowired both annotations are used for autowiring in your application. @Inject annotation is part of Java CDI which was introduced in Java 6, whereas @Autowire annotation is part of spring framework. Both annotations fulfill same purpose therefore, anything of these we can use in our application.
if Spring encounters multiple beans with same type it checks field name. if it finds a bean with the name of the target field, it injects that bean into the field.
@Autowired on Setter Methods You can use @Autowired annotation on setter methods to get rid of the <property> element in XML configuration file. When Spring finds an @Autowired annotation used with setter methods, it tries to perform byType autowiring on the method.
We can also use @Autowired annotation on constructor for constructor based spring autowiring. For @Autowired annotation to work, we also need to enable annotation based configuration in spring bean configuration file. This can be done by context:annotation-config element or by defining a bean of type org.
The problem is the following:
So having @Bean, but manually injecting an @Autowired dependency conflicts each other, you may now understand, why - you shall not inject Autowired beans manually! Autowired is an annotation that tells he CI container to do some injection work.
There's a hacky way of doing that, as described in this old Stack Overflow thread.
public static <T> FactoryBean<T> preventAutowire(T bean) {
return new FactoryBean<T>() {
public T getObject() throws Exception {
return bean;
}
public Class<?> getObjectType() {
return bean.getClass();
}
public boolean isSingleton() {
return true;
}
};
}
...
@Bean
static FactoryBean<MyBean> myBean() {
return preventAutowire(new MyBean());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With