1. Concept Introduction
As I said earlier, the core of the IOC container control inversion is di--dependency injection. Dependencies between objects are only implemented in the following ways: arguments to constructors, parameters of factory methods, or setting properties for objects created by constructors or factory methods. So, the work of the IOC container is to inject those dependencies when the bean is created.
Control is fundamentally reversed, as opposed to the 3 ways in which the bean itself controls its instantiation, specifying dependencies directly in the constructor, or similar to the service locator (Servicelocator) pattern, which is the reverse of control (inversionof Control, IoC) The origin of the name.
After applying the DI principle, the code becomes clearer. And when the bean itself is no longer concerned about the dependencies between objects (and when and where the actual class of dependencies and dependencies are specified), it is easier to achieve a higher level of loose coupling.
Here are two ways to inject Di, namely setter injection and constructor injection:
2. Setter injection
After you instantiate a bean by calling the parameterless constructor or the parameterless static factory method, you can implement a setter-based di by invoking the Bean's Setter method:
Package Com.bjpowernode.spring.manager;import Com.bjpowernode.spring.dao.userdao;import Com.bjpowernode.spring.dao.userdao4mysqlimpl;import Com.bjpowernode.spring.dao.userdao4oracleimpl;public Class Usermanagerimpl implements Usermanager {private Userdao userdao;//no parameter constructor public Usermanagerimpl () {super ();} Setter mode injected public void Setuserdao (Userdao userdao) {This.userdao = Userdao;} @Overridepublic void AddUser (string username, string password) {//Original way--by our program is responsible for service (object) management//userdao Userdao = new Userdao4mysqlimp ();//userdao Userdao = new Userdao4oracleimpl (); Userdao.adduser (username, password);}}
Configuration--applicationcontext.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:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:tx= " Http://www.springframework.org/schema/tx "xsi:schemalocation=" Http://www.springframework.org/schema/beans http:/ /www.springframework.org/schema/beans/spring-beans-2.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www. Springframework.org/schema/aop/spring-aop-2.0.xsd Http://www.springframework.org/schema/tx Http://www.springfram Ework.org/schema/tx/spring-tx-2.0.xsd "><bean id=" Userdao4mysqlimpl "class=" Com.bjpowernode.spring.dao.UserDao4MysqlImpl "/><bean id=" Userdao4oracleimpl "class=" Com.bjpowernode.spring.dao.UserDao4OracleImpl "/><bean id =" Usermanager "class=" Com.bjpowernode.spring.manager.UserManagerImpl "><!--<constructor-arg ref=" Userdao4oracleimpl "/>-- > <property name= "Userdao" ref="Userdao4oracleimpl"/></bean></beans>
3. Constructor injection
The constructor-based di is implemented by invoking a constructor with parameters, each representing a collaborator. In addition, you can construct a bean by passing parameters to the static factory method:
Package Com.bjpowernode.spring.manager;import Com.bjpowernode.spring.dao.userdao;import Com.bjpowernode.spring.dao.userdao4mysqlimpl;import Com.bjpowernode.spring.dao.userdao4oracleimpl;public Class Usermanagerimpl implements Usermanager {Private Userdao userdao;//constructor method injected public Usermanagerimpl (Userdao Userdao) { This.userdao = Userdao;} @Overridepublic void AddUser (string username, string password) {//Original way--by our program is responsible for service (object) management//userdao Userdao = new Userdao4mysqlimp ();//userdao Userdao = new Userdao4oracleimpl (); Userdao.adduser (username, password);}}
Configuration--applicationcontext.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:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:tx= " Http://www.springframework.org/schema/tx "xsi:schemalocation=" Http://www.springframework.org/schema/beans http:/ /www.springframework.org/schema/beans/spring-beans-2.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www. Springframework.org/schema/aop/spring-aop-2.0.xsd Http://www.springframework.org/schema/tx Http://www.springfram Ework.org/schema/tx/spring-tx-2.0.xsd "><bean id=" Userdao4mysqlimpl "class=" Com.bjpowernode.spring.dao.UserDao4MysqlImpl "/><bean id=" Userdao4oracleimpl "class=" Com.bjpowernode.spring.dao.UserDao4OracleImpl "/><bean id =" Usermanager "class=" Com.bjpowernode.spring.manager.UserManagerImpl "><constructor-arg ref=" Userdao4oracleimpl "/> <!--< Property Name= "Userdao" ref= "Userdao4OracleImpl "/>--></bean></beans>
4. Setter Injection Example
Whether it is an object or a property, spring can inject an object or property as long as the portal (set method) is given.
Spring can provide values in string type to various built-in types, such as int, long, String, Boolean, and so on. Examples are as follows:
"Class Bean1"
Package Com.bjpowernode.spring;import Java.util.date;import Java.util.list;import java.util.map;import Java.util.set;public class Bean1 {private String strvalue;private int intvalue;private List listvalue;private Set Setvalu E;private string[] arrayvalue;private Map mapvalue;public String getstrvalue () {return strvalue;} public void Setstrvalue (String strvalue) {this.strvalue = strvalue;} public int Getintvalue () {return intvalue;} public void Setintvalue (int intvalue) {this.intvalue = Intvalue;} Public List Getlistvalue () {return listvalue;} public void Setlistvalue (List listvalue) {this.listvalue = ListValue;} Public Set Getsetvalue () {return setValue;} public void Setsetvalue (Set setValue) {this.setvalue = SetValue;} Public string[] Getarrayvalue () {return arrayvalue;} public void Setarrayvalue (string[] arrayvalue) {this.arrayvalue = arrayvalue;} Public Map Getmapvalue () {return mapvalue;} public void Setmapvalue (Map mapvalue) {this.mapvalue = Mapvalue;}}
"Configure--applicationcontext.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:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:tx= " Http://www.springframework.org/schema/tx "xsi:schemalocation=" Http://www.springframework.org/schema/beans http:/ /www.springframework.org/schema/beans/spring-beans-2.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www. Springframework.org/schema/aop/spring-aop-2.0.xsd Http://www.springframework.org/schema/tx Http://www.springfram Ework.org/schema/tx/spring-tx-2.0.xsd "><bean id=" Bean1 "class=" Com.bjpowernode.spring.Bean1 ">< Property Name= "strvalue" value= "hello_spring"/><!--<property name= "intvalue" value= "123"/>-->< Property Name= "Intvalue" ><value>456</value></property><property name= "ListValue" >< List><value>list1</value><value>list2</value><value>list3</value></list></property><property name= "SetValue" ><set>< value>set1</value><value>set2</value><value>set3</value></set></ Property><property name= "Arrayvalue" ><list><value>array[0]</value><value>array [1]</value><value>array[2]</value></list></property><property name= "MapValue" ><map><entry key= "K1" value= "v1"/><entry key= "K2" value= "v1"/><entry key= "K3" value= "v1"/ ></map></property></bean></beans>
"Test Case-injectiontest"
Jar packages that need to introduce test cases-- Junit.jar, directory: spring-framework\lib\junit\ Junit.jar
Package Test;import Junit.framework.testcase;import Org.springframework.beans.factory.beanfactory;import Org.springframework.context.support.classpathxmlapplicationcontext;import Com.bjpowernode.spring.bean1;public Class Injectiontest extends TestCase {private beanfactory factory; @Overrideprotected void SetUp () throws Exception {facto ry = new Classpathxmlapplicationcontext ("Applicationcontext.xml");//read a configuration file} @Overrideprotected void TearDown () Throws Exception {///end the resource to be freed}public void TestInjection1 () {Bean1 bean1= (Bean1) Factory.getbean ("Bean1"); System.out.println ("bean1.strvalue=" + bean1.getstrvalue ()); System.out.println ("Bean1. Intvalue= "+ bean1.getintvalue ()); System.out.println ("bean1.listvalue=" + bean1.getlistvalue ()); System.out.println ("bean1.setvalue=" + bean1.getsetvalue ()); System.out.println ("bean1.arrayvalue=" + bean1.getarrayvalue ()); System.out.println ("bean1.mapvalue=" + bean1.getmapvalue ()); System.out.println ("bean1.datevalue=" + bean1.getdatevalue ());}}
Output Result:
You can see that the spring container has injected values into the properties of the Bean1.
5. Property Editor
As mentioned above, Spring is able to provide values in String type to convert int, long, String, Boolean, and other compatible types, but it cannot be converted directly to incompatible types such as date, so the conversion needs to be done by writing the property editor manually.
For example, in the example above, add a date-type property to Bean1, as follows:
Private date Datevalue;public Date Getdatevalue () {return dateValue;} public void Setdatevalue (Date dateValue) {this.datevalue = DateValue;}
In the spring configuration, it is straightforward to configure the following attribute mappings, which are quoted as error-type conversions:
<property name= "DateValue" value= "2014-11-27"/>
You also need to write a property editor manually to complete the conversion between the string and date type, as follows "class Utildatepropertyeditor":
Package Com.bjpowernode.spring;import Java.beans.propertyeditorsupport;import Java.text.parseexception;import Java.text.simpledateformat;import java.util.date;/** * Java.util.Date Property Editor */public class Utildatepropertyeditor Extends PropertyEditorSupport {@Overridepublic void Setastext (String text) throws IllegalArgumentException { SYSTEM.OUT.PRINTLN ("---utildatepropertyeditor.setastext ()--->" +text); try {Date date = new SimpleDateFormat (" Yyyy-mm-dd "). Parse (text); This.setvalue (date);} catch (ParseException e) {//TODO auto-generated catch Blocke.printstacktrace (); throw new IllegalArgumentException ();}}}
You then need to inject the property editor into the Customeditors property (the map type) of the Customeditorconfigurer class. Add a spring core configuration file "Applicationcontext-editor.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:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:tx= " Http://www.springframework.org/schema/tx "xsi:schemalocation=" Http://www.springframework.org/schema/beans http:/ /www.springframework.org/schema/beans/spring-beans-2.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www. Springframework.org/schema/aop/spring-aop-2.0.xsd Http://www.springframework.org/schema/tx Http://www.springfram Ework.org/schema/tx/spring-tx-2.0.xsd "><bean id=" customeditors "class=" Org.springframework.beans.factory.config.CustomEditorConfigurer "><property name=" Customeditors ">< Map><entry key= "java.util.Date" ><bean class= "Com.bjpowernode.spring.UtilDatePropertyEditor"/>< !--internal bean (without id attribute)--></entry></map></property></bean><!--<bean id= "utilDatepropertyeditor "class=" Com.bjpowernode.spring.UtilDatePropertyEditor "></bean>--></beans>
You can then change the test case, mainly by adding another spring profile that you just added when you construct the Beanfactory parameter:
string[] configlocations = new string[]{"Applicationcontext.xml", "applicationcontext-editor.xml"};//factory = new Classpathxmlapplicationcontext ("Applicationcontext.xml");//Read a configuration file factory = new Classpathxmlapplicationcontext ( configlocations);//Read multiple configuration files
You can then inject the string correctly into the properties of the date type.
6. Summary
Because a large number of constructor parameters can make the program awkward, especially if some properties are optional. Therefore, typically, the spring development team advocates the use of setter injection. And Setter di can reconfigure (or re-inject) The instance sometime later (JMX Mbean is a good example).
However, the constructor injection is very popular in some specific scenarios. There are no hard rules for the choice of injection type. Depending on the actual business scenario, any type of Di can be used, as long as it is suitable for your application.
Spring's Dependency Injection