Singleton bean and multi instance bean: Singleton means that only one instance object of a class can exist in a program cycle. Multiple instances means that there can be multiple instance objects.
In the xml definition of a bean, we can specify whether a bean is singleton or multi instance by setting the scope attribute. Where prototype represents multiple cases and singleton represents multiple cases.
Let's take a look at the specific usage of the two. The first is the single example:
<bean id="student_yqs" class="upc.yqs.Student" scope="singleton"> <property name="name" value="yqs"></property> <property name="age" value="18"></property> </bean>
I set the scope attribute of this bean to singleton, indicating that it is a singleton. Next, let's test it through the test program:
@Test public void singletonTest() { Student stu1 = (Student) context.getBean("student_yqs"); Student stu2 = (Student) context.getBean("student_yqs"); System.out.println("stu1 Address of:" + System.identityHashCode(stu1) + " stu2 Address of:" + System.identityHashCode(stu2)); }
Output:
stu1 Address of:757004314 stu2 Address of:757004314
We find that two objects point to the same object, which is the role of singleton mode.
So what happens if we define two bean s for the same class and specify both as singletons.
Let's modify the xml and add a bean, but point to the same class and set it to singleton
<bean id="student_yqs" class="upc.yqs.Student" scope="singleton"> <property name="name" value="yqs"></property> <property name="age" value="18"></property> </bean> <bean id="student_bbb" class="upc.yqs.Student" scope="singleton"> <property name="name" value="bbb"></property> <property name="age" value="17"></property> </bean>
Next, let's write another test program:
@Test public void singletonTest2() { Student stu_yqs1 = (Student) context.getBean("student_yqs"); Student stu_yqs2 = (Student) context.getBean("student_yqs"); Student stu_bbb1 = (Student) context.getBean("student_bbb"); Student stu_bbb2 = (Student) context.getBean("student_bbb"); System.out.println("stu_yqs1 Address of:" + System.identityHashCode(stu_yqs1)); System.out.println("stu_yqs2 Address of:" + System.identityHashCode(stu_yqs2)); System.out.println("stu_bbb1 Address of:" + System.identityHashCode(stu_bbb1)); System.out.println("stu_bbb2 Address of:" + System.identityHashCode(stu_bbb2)); }
Output:
stu_yqs1 Address of:757004314 stu_yqs2 Address of:757004314 stu_bbb1 Address of:996796369 stu_bbb2 Address of:996796369
You will find that the objects obtained by two IDs are not the same, but the same id is the same id no matter how many times it is obtained. In other words, the singleton in a bean is not a singleton in the traditional sense. The singleton in the traditional sense is for a class, but for a bean.
In many cases, similarly, we can set the scope property to prototype (note that the default value is singleton). In this way, the bean s we get each time will be different objects. With the above foundation, this is easy to understand and will not be demonstrated in detail.
Definition of bean with constructor
If we want to use the constructor to initialize our bean, we can use the < constructor Arg > tag to pass values to the parameters of the constructor.
For example, my student class has a constructor:
public Student(String name, int age) { this.name = name; this.age = age; }
To use this constructor, we just need to define it like this:
<bean id="student_asd" class="upc.yqs.Student" scope="singleton"> <constructor-arg name="name" value="asd"/> <constructor-arg name="age" value="5"/> </bean>
Note that when defining, we must match a constructor in this class, otherwise an error will be reported. For example, if I delete the second constructor Arg in the xml above, an error will be reported, because there is no constructor with only one age in the Student class.
If the number of parameters of two constructors is the same, in order to avoid ambiguity, we can explicitly specify the parameter type:
<bean id="student_asd" class="upc.yqs.Student" scope="singleton"> <constructor-arg type="java.lang.String" name="name" value="asd"/> <constructor-arg type="java.lang.Integer" name="age" value="5"/> </bean>
bean definition of constructor of special type for parameter
In fact, the above mentioned data are all simple data. If you encounter custom classes as parameters, or List and Map as parameters, you need some special syntax to help us implement it.
1. Custom class as parameter
Suppose the Student class has such a constructor:
public Student() { this.name="null"; this.age=-1; } public Student(Student npy) { this(); this.npy=npy; }
We pass in a student class object as a parameter, and npy represents the student's boyfriend / girlfriend (I really can't think of any other one-to-one relationship between students, is it father and son?)
When defining a bean, we can use the ref attribute (instead of value) to pass in a Student object:
<bean id="student_yqs" class="upc.yqs.Student" scope="prototype"> <property name="name" value="yqs"></property> <property name="age" value="18"></property> </bean> <bean id="student_yyy" class="upc.yqs.Student"> <constructor-arg type="upc.yqs.Student" name="npy" ref="student_yqs"/> </bean>
What is written in ref is beanID. If it is written here, it means that the npy of yyy is yqs.
Let's write a test program and try it:
@Test public void constructorTest2() { Student stu_yyy=(Student) context.getBean("student_yyy"); System.out.println(stu_yyy.npy); }
Output:
Student{name='yqs', age=18}
Meet our expectations
2. List as a parameter
For example, Student has a constructor:
public Student(List<Student> friends) { this.friends = friends; }
Then we can do this when defining:
<bean id="student_yyq" class="upc.yqs.Student"> <constructor-arg type="java.util.List" name="friends"> <list> <ref bean="student_yqs"></ref> <ref bean="student_yyy"></ref> <ref bean="student_asd"></ref> </list> </constructor-arg> </bean>
Write a test program:
@Test public void constructorTest3() { Student stu_yyq=(Student) context.getBean("student_yyq"); System.out.println(stu_yyq.friends); }
Output:
[Student{name='yqs', age=18}, Student{name='null', age=-1}, Student{name='asd', age=5}]
No problem.
3. map and set as parameters
The reason is similar. I won't be specific:
<bean id="student_msq" class="upc.yqs.Student"> <constructor-arg type="java.util.Map" name="map"> <map> <entry key="111" value="5"></entry> <entry key="222" value="6"></entry> <entry key="333" value="7"></entry> <entry key="444" value="8"></entry> </map> </constructor-arg> <constructor-arg type="java.util.Set" name="set"> <set> <value>9</value> <value>10</value> <value>11</value> </set> </constructor-arg> </bean>
Lazy loading
When defining a bean, if we lazy it_ If the init attribute is set to true (this attribute will take effect only when scope="singleton"), the bean will become lazy loading, that is, the bean will be loaded only when we use getBean (or refer to the bean with ref in other beans). If it is set to false (also false by default), the program will be loaded as soon as it runs.
Init method: this method is called when the container loads a Bean, which is similar to the init() method in the Servlet (it will only be called once when scope=singleton, and every time getBean is called when scope=prototype)
Destroy method: this method is called when the container deletes a Bean, similar to the destroy() method in the Servlet. This method is only valid when scope=singleton
The value of the parameter is filled in with the name of the member method of the class pointed to by the bean (which can be a static class)
Steal a lazy, don't post code, let's try it ourselves.