问题
I have the following scenario:
A bean Autowired in two classes, I populate the bean in one class, then I check the bean in the second class, it is not populated. Whereas, when I add a getter in the class where I populated the bean and call the getter, it returns the bean populated. Why can't I access that bean directly in the other class, shouldn't it be populated since it's acting as a singleton in spring context?
A JUnit4 test class loading the spring context from an xml file:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring/test-main-context.xml" })
public class MyTests {
@Autowired
MyObject myObject;
@Autowired
MyUtils myUtils;
@Test
public void testingContext() {
myUtils.setMyObjectFromDB();
System.out.println(myUtils.getMyObject().getId());
System.out.println(myObject.getId());
}
}
MyUtils:
public class MyUtils {
@Autowired MyObject myObject;
public void setMyObjectFromDB() {
MyObject myDBObject = new MyObject();
//
// getting myObjectFromDB;
//
myObject = myDBObject;
}
public MyObject getMyObject() {
return myObject;
}
}
In the test class, myUtils.getMyObject().getId()
returns a correct id but the second line myObject.getId()
it returns null.
Why is MyObject which is set in MyUtils class and is @Autowired in both classes is not being updated when I access it directly in the test class.
回答1:
When you're reassigning myObject = myDBObject;
in setMyObjectFromDB
method, you're creating a new object and saving it's referene in myObject
variable which is different from the one created with Autowired
.
When you use Autowired
, then it will assign the created bean's reference in the variable. But if you reassign that variable, it will point to the new object.
EDIT:
If you really need to update all the variables of myObject
with initialized with Autowired
, it is better to create a container class that stores myObject
variable.
public class MyObjectContainer {
@Autowired
MyObject myObject;
// Getters & Setters
}
In all the classes, where you're autowiring myObject
, use an object of MyObjectContainer
class instead. And when you want to update myObject
value, just update it in myObjectContainer
object with it's setter. So your MyUtils
would be like:
public class MyUtils {
@Autowired MyObjectContainer myObjectContainer;
public void setMyObjectFromDB() {
MyObject myDBObject = new MyObject();
//
// getting myObjectFromDB;
//
myObjectContainer.setMyObject(myDBObject);
}
public MyObjectContainer getMyObjectContainer() {
return myObjectContainer;
}
}
回答2:
Looking at the code, the MyObject
is not injected in either of the two classes. You got the impression that it was injected in the MyUtils
class because you actually created it manually in the setter method.
The brings the question to why MyObject
is not injected, and there could be many reasons for that one of which is that you do not have @Component
defined in the MyObject
class or it is not in your component scan path by adding @ComponentScan(basePackages = "put-your-base-package-name")
in your Spring application class.
来源:https://stackoverflow.com/questions/53830819/autowired-bean-in-two-classes-not-being-updated-after-accessing-it-from-the-seco