Dependency injection (ioc di)
Two Methods of dependency injection:
1. set Injection
When Spring requires the set injection method, Bean needs to provide a construction method without parameters. And provides a property setter method. For example:
PackageCom. kay. bean; Public ClassUserServices { PrivateUserBean ub; Public VoidSetUb (UserBean ub ){ This. Ub = ub; } Public VoidAdd (){ Ub. add (); } } |
In the preceding example, if the UserServices class depends on the UserBean class, you can configure it in the configuration file.
Configuration method 1:
<! -- Hand over userBean to spring Management --> <Bean id = "userBean" class = "com. kay. bean. UserBean"/> <! -- Hand over userServics to spring Management --> <Bean id = "userServices" class = "com. kay. bean. UserServices"> <! -- Inject the setter method using the propterty node --> <Property name = "ub"> <ref bean = "userBean"/> </property> </Bean> |
The name attribute in the preperty node in the configuration file refers to the name of the set Method in the UserServices class, such as setXXX, which is irrelevant to the property name. The bean attribute of the ref node refers to a Bean to be referenced and injects the referenced Bean instance into the UserServices class.
Configuration method 2:
<Bean id = "userBean" class = "com. kay. bean. UserBean"/> <Bean id = "userServices" class = "com. kay. bean. UserServices"> <Property name = "ub"> <ref local = "userBean"/> </property> </Bean> |
The Configuration File above changes the bean attribute in the original ref node to local, so the local attribute requires that the referenced Bean must be in the same configuration file (Spring supports multiple configuration files ). However, bean attributes do not have this requirement.
Configuration method 3:
<Bean id = "userServices" class = "com. kay. bean. UserServices"> <Property name = "ub"> <Bean class = "com. kay. bean. UserBean"/> </Property> </Bean> |
The above configuration method becomes internal Bean configuration. You do not need to specify the id or name for the internal Bean definition. If you specify it, it will be ignored by the Spring container. The configuration defect is that the referenced Bean cannot be reused, and the internal Bean is prototype.
Configuration method 4:
<Bean id = "userBean" class = "com. kay. bean. UserBean"/> <Bean id = "userServices" class = "com. kay. bean. UserServices"> <Property name = "ub" ref = "userBean"/> </Bean> |
This is simply a short form of configuration method 1.
2. constructor Injection
From the injection name, we can see that this injection method mainly uses the constructor method. Modify the UserServices class:
PackageCom. kay. bean; Public ClassUserServices { PrivateUserBean userBean; Public UserServices (UserBean userBean ){ This. userBean = userBean; } Public VoidAdd (){ UserBean. add (); } } |
Configuration method 1:
<Bean id = "userBean" class = "com. kay. bean. UserBean"/> <Bean id = "userServices" class = "com. kay. bean. UserServices"> <Constructor-arg> <Ref bean = "userBean"/> </Constructor-arg> </Bean> |
The constructor-arg node is used above. The bean attribute of the ref subnode of the node specifies the Bean to be referenced.
If there is such a constructor in the UserServices class:
PackageCom. kay. bean; Public ClassUserServices { PrivateString name; Public IntA; PublicUserServices (String name,IntA ){ This. Name = name; This. A =; } } |
You can use configuration method 2 and configuration method 3 to solve the problem.
Configuration method 2:
<Bean id = "userServices" class = "com. kay. bean. UserServices"> <Constructor-arg type = "java. lang. String" value = "Tom"/> <Constructor-arg type = "int" value = "25"/> </Bean> |
In configuration method 2, the type attribute is used to specify the type of the constructor parameter, and the value is used to specify the value of the parameter.
Configuration method 3:
<Bean id = "userServices" class = "com. kay. bean. UserServices"> <Constructor-arg index = "0" value = "Tom"/> <Constructor-arg index = "1" value = "25"/> </Bean> |
In configuration method 3, use the index attribute to specify the order of parameters in the constructor.
Use constructor injection or set injection?
First, I will tell you that there is no answer to this question !!!
Reasons for Constructor injection:
N constructor injection uses strong dependency rules. If enough parameters are not provided, the object cannot be created.
N because Bean dependencies are all set through the constructor, no more set methods are required to reduce the amount of code.
Reasons for using set injection:
N if the Bean has many dependencies, the parameter list of the constructor will become very long.
N if an object has multiple constructor methods, the constructor will increase the amount of code.
N if there are two or more parameters of the same type in the constructor, it is difficult to determine the purpose of the parameter.
N ......
Set injection is recommended for Spring.
More injection:
Start with the User class:
Public ClassUser { Private IntAge; PrivateString name; Private DoubleScore; PrivateList fav; PrivateMap map; PrivateSet set; PrivateProperties pro; Public VoidSetAge (IntAge ){ This. Age = age; } Public VoidSetName (String name ){ This. Name = name; } Public VoidSetScore (DoubleScore ){ This. Score = score; } Public VoidSetFav (List fav ){ This. Fav = fav; } Public VoidSetMap (Map map ){ This. Map = map; } Public VoidSetSet (Set set ){ This. Set = set; } Public VoidSetPro (Properties pro ){ This. Pro = pro; } } |
1. Inject direct variables (basic data type, String type, etc)
<Bean id = "user" class = "com. kay. bean. User"> <Property name = "age" value = "45"> </property> <Property name = "name" value = "Tom"> </property> <Property name = "score" value = "45.5"> </property> </Bean> |
Or:
<Bean id = "user" class = "com. kay. bean. User"> <Property name = "age"> <Value> 45 </value> </Property> <Property name = "name"> <Value> Tom </value> </Property> <Property name = "score"> <Value> 45.5 </value> </Property> </Bean> |
Of course, the constructor injection method is also possible:
<Bean id = "user" class = "com. kay. bean. User"> <Constructor-arg type = "int" value = "45"> </constructor-arg> <Constructor-arg type = "double" value = "45.5"> </constructor-arg> <Constructor-arg type = "java. lang. String" value = "Tom"> </constructor-arg> </Bean> |
2. Set
A) List
<Property name = "fav"> <List> <Value> football </value> <Value> pingpang </value> <Value> swing </value> </List> </Property> |
B) Set
<Property name = "set"> <Set> <Value> set1 </value> <Value> set2 </value> <Value> set3 </value> </Set> </Property> |
C) Map
<Property name = "map"> <Map> <Entry> <Key> <Value> id </value> </Key> <Value> 001 </value> </Entry> <Entry> <Key> <Value> name </value> </Key> <Value> jerry </value> </Entry> </Map> </Property> |
D) Properties
<Property name = "pro"> <Props> <Prop key = "name"> Tom </prop> <Prop key = "age"> 15 </prop> </Props> </Property> |
3. Null
The configuration node <null/> is used to process the null value.
<Property name = "name"> <Null> </null> </Property> |
The above configuration is equivalent to setName (null );
If the configuration is as follows:
<Property name = "name"> <Value> </value> </Property> |
It is equivalent to setName ("");
4. Use the p namespace for property Injection
Modify the schema of the configuration file:
<? 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" Xmlns: p = "http://www.springframework.org/schema/p" Xsi: schemaLocation = "http://www.springframework.org/schema/beans Http://www.springframework.org/schema/beans/spring-beans-2.5.xsd Http://www.springframework.org/schema/context Http://www.springframework.org/schema/context/spring-context-2.5.xsd> </Beans> |
Injection attributes:
<Bean id = "user" class = "com. kay. bean. User" p: name = "tom" p: age = "45" p: score = "55.5"> </Bean> |
The namespace p is used in the preceding settings. p: name indicates that the name attribute is assigned a value. If the User class has an attribute that needs to reference other beans, you need to configure p as follows: property name-ref = "Bean to be referenced ":
<Bean id = "userBean" class = "com. kay. bean. UserBean"/> <Bean id = "user" class = "com. kay. bean. user "p: name =" tom "p: age =" 45 "p: score =" 55.5 "p: userbean-ref =" userBean "> </Bean> |
5. Automatic Bean assembly (injection)
Spring provides the following four automatic assembly types:
N byName à tries to find the Bean (or ID) with the same name as the property to be automatically assembled in the container ). If this attribute is not found, it is not matched.
N byType à tries to find a Bean of the same type as the property type to be automatically assembled in the container. If no matching Bean is found, this attribute is not assembled. If more than one matching Bean is found, the org. springframework. bean. factory. UnsatisfiedDependencyException will be thrown.
N Constructor à tries to find one or more beans in the container that are consistent with the Constructor of the Bean to be automatically assembled. The container throws an org. spingframework. beans. factory. UnsatisfiedDependencyException exception.
N Autodetect à first tries to use constrctor for assembly, and then uses byType. Uncertainty is handled in the same way as constrctor and byType.
Use byName for automatic assembly:
UserDAO class:
Public ClassUserDAO { Public VoidAdd (){ System.Out. Println ("add operations using JDBC "); } } |
UserServices class:
Public ClassUserServices { PrivateUserDAO userDAO; Public VoidSetUserDAO (UserDAO userDAO ){ This. UserDAO = userDAO; } Public VoidAdd (){ UserDAO. add (); } } |
Automatic Assembly using byName:
<Bean id = "userDAO" class = "com. kay. bean. UserDAO"> </bean> <Bean id = "userService" class = "com. kay. bean. UserServices" autowire = "byName"> </Bean> |
When using byName for automatic assembly, you need to set the injected attribute name in Bean to the same name as the Bean to be injected. (Yellow part)
Use byType for automatic assembly:
When byType is used for automatic assembly, it works in the same way as when byName is used for assembly, except that the Bean is searched for assembly by the attribute type.
<Bean id = "userDAO" class = "com. kay. bean. UserDAO"> </bean> <Bean id = "userService" class = "com. kay. bean. UserServices" autowire = "byType"> </Bean> |
When using buType for automatic assembly, if Spring finds more than one Bean of the same type as the Bean to be injected, Spring does not decide which Bean to inject, but directly throws an exception.
Use constructor for automatic assembly:
Modify the UserService class:
Public ClassUserServices { PrivateUserDAO userDAO; PublicUserServices (UserDAO userDAO) { This. UserDAO = userDAO; } Public VoidAdd (){ UserDAO. add (); } } |
Modify the configuration file:
<Bean id = "userDAO" class = "com. kay. bean. UserDAO"> </bean> <Bean id = "userService" class = "com. kay. bean. UserServices" autowire = "constructor"> </Bean> |
When constructor is used for automatic forwarding, the Spring container will find beans matching the Bean constructor's constructor for injection. Like ByType, if the container finds more than one matching Bean, it does not decide which Bean to inject, but throws an exception.
Automatic Assembly with autodetect:
<Bean id = "userService" class = "com. kay. bean. UserServices" autowire = "autodetect"> </Bean> |
When the atuowire attribute value is set to autodetect, the Spring container determines which assembly method to use. The container first tries to use constructor for assembly. If it fails, it uses byTyep for assembly.
By default, the Spring container will not be automatically assembled unless the autowire attribute is set in the configuration file. If the default-autowire attribute of the beans node is set, all beans are automatically assembled.
<Beans default-autowire = "byName"> </Beans> |
After the preceding settings are used, all beans are assembled in byName mode.