I am trying to inject an object to a class. However, the field is always null. I tried @Autowired
and @Resource
annotations. I am not creating the object with new
operator anywhere. The constructor of Foo
is called properly.
The minimal example of this problem:
Foo class
package foo.bar;
public class Foo {
Foo(){
System.out.println("Foo constructor");
}
public void func() {
System.out.println("func()");
}
}
Bar class
package foo.bar;
public class Bar {
@Autowired
private Foo foo;
public Bar() {
foo.func();
}
}
Entry point
package foo.bar;
public class HelloApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="foo.bar"/>
<bean id = "foo" class="foo.bar.Foo" />
<bean id = "bar" class="foo.bar.Bar" />
</beans>
Why is foo
field of Bar
class always null
? How can I fix this?
As @Mick pointed out, field injection necessarily takes place after the constructor is finished (there's no other way for Spring to see the instance and manipulate it). Modify your class to use constructor injection, and you'll both make your dependencies more explicit (and thus easier to test, for example) and eliminate what's essentially a race condition:
public class Bar {
private Foo foo;
@Autowired
public Bar(Foo foo) {
this.foo = foo;
foo.func();
}
}
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