Issue
I am new to Spring. Recently I encountered something weird, I was using @Autowired for Auto Injecting Name, Emotion in Person class(I have a different class for each Name, Emotion, Person). I encountered that the Person constructor was getting invoked even if I have not used @Autowired with it. Can anyone explain to me why this is happening?.
Is it related to the Automatic Invocation of Constructor after Object Creation(Person)? Also why Constructor is invoked before @Autowired Functions? (As u can see in the output)
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:annotation-config />
<bean id = "emotionAngry" class="gd.rf.anuragsaini.autowired.annotation.Emotion">
<property name="name" value="Angry :-O"></property>
</bean>
<bean id = "nameAnuragSaini" class="gd.rf.anuragsaini.autowired.annotation.Name">
<constructor-arg value="Anurag Saini"></constructor-arg>
</bean>
<bean id = "person" class="gd.rf.anuragsaini.autowired.annotation.Person"/>
</beans>
Emotion.java
package gd.rf.anuragsaini.autowired.annotation;
public class Emotion {
String name;
public void setName(String name) {
System.out.println("[EMOTION]:Setting Name of Emotion");
this.name = name;
}
@Override
public String toString() {
return "Emotion{" +
"name='" + name + '\'' +
'}';
}
}
Name.java
package gd.rf.anuragsaini.autowired.annotation;
public class Name {
String name;
public Name(String name) {
System.out.println("[NAME]: Setting Name Bean");
this.name = name;
}
@Override
public String toString() {
return "Name{" +
"name='" + name + '\'' +
'}';
}
}
Person.java
package gd.rf.anuragsaini.autowired.annotation;
import org.springframework.beans.factory.annotation.Autowired;
public class Person {
Name name;
Emotion emotion;
@Autowired
public void setName(Name name) {
System.out.println("[PERSON]: Setting Name of Person");
this.name = name;
}
@Autowired
public void setEmotion(Emotion emotion) {
System.out.println("[PERSON]: Setting Emotion of Person");
this.emotion = emotion;
}
public Person(Name name, Emotion emotion) {
System.out.println("[PERSON]: Constructor Setting Person");
this.name = name;
this.emotion = emotion;
}
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", emotion=" + emotion +
'}';
}
}
Main App.java
package gd.rf.anuragsaini.autowired.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext IOC = new ClassPathXmlApplicationContext("config.xml");
Person person1 = IOC.getBean("person", Person.class);//No need of Type Casting when class is specified
System.out.println(person1);
}
}
Output
[EMOTION]:Setting Name of Emotion
[NAME]: Setting Name Bean
[PERSON]: Constructor Setting Person
[PERSON]: Setting Name of Person
[PERSON]: Setting Emotion of Person
Person{name='Name{name='Anurag Saini'}', emotion=Emotion{name='Angry :-O'}}
Solution
You defined a Bean of Person class in your xml file, therefore Spring will create an instance of this class. And the constructor you have defined takes a Name and Emotion both other classes you have an instance of.
So Spring will create a Bean of Person even if you don't use it with Autowire
.
And it gets invoked before the '@Autowire functions' as you called them because they are methods and you need an instance to call them and the constructor gets called when you create an instance.
I hope I understood your question correct and this answers it.
Answered By - Ausgefuchster
Answer Checked By - Terry (JavaFixing Volunteer)