一. Spring DI 依赖注入
利用spring IOC实例化了对象,而DI将实例化的对象注入到需要对象的地方,完成初始化任务。
对象由spring创建,之后再由spring给属性赋值
spring提供两种方式设置属性值:
① setter方法注入
②构造方法注入
二. set方法注入
2.1单值注入
Cat有type和age属性,采用单值注入的方式,进行初始化。
1 package com.hdu.setter; 2 3 import java.io.Serializable; 4 5 public class Cat implements Serializable{ 6 7 private static final long serialVersionUID = 1L; 8 9 private String type; 10 private int age; 11 12 public String getType() { 13 return type; 14 } 15 public void setType(String type) { 16 this.type = type; 17 } 18 public int getAge() { 19 return age; 20 } 21 public void setAge(int age) { 22 this.age = age; 23 } 24 }
<!-- 实例化Cat对象 <bean>节点是用来告知spring实例化对象 <property>节点,是用来告知spring对象有注入 name="type" type->Type->setType 把名字的第一个字母大写,前面用字符串连接一个set,构建出一个新字符串, 拿着个字符串去class属性所对应的类中寻找是否有此方法签名的方法. 如果有就反射调用此setter方法.setter方法的参数是value="smallCat" --> <bean id="cat" class="com.hdu.setter.Cat"> <!-- 单值注入 --> <property name="type" value="smallCat"></property> <property name="age" value="3"></property> </bean>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.setter.Cat; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_object.xml"); 13 Cat cat = context.getBean("cat",Cat.class); 14 System.out.println(cat.getType()+" "+cat.getAge()); 15 } 16 }
2.2对象注入
人人有猫。将Cat对象注入到Person对象中。
1 package com.hdu.setter; 2 3 public class Person { 4 private String name; 5 private int age; 6 private Cat cat; 7 public String getName() { 8 return name; 9 } 10 public void setName(String name) { 11 this.name = name; 12 } 13 public int getAge() { 14 return age; 15 } 16 public void setAge(int age) { 17 this.age = age; 18 } 19 public Cat getCat() { 20 return cat; 21 } 22 public void setCat(Cat cat) { 23 this.cat = cat; 24 } 25 }
<!-- 实例化Cat对象 --> <bean id="cat" class="com.hdu.setter.Cat"> <!-- 单值注入 --> <property name="type" value="smallCat"></property> <property name="age" value="3"></property> </bean> <!-- name="cat" cat->Cat->setCat ref="cat" 引用对象,cat是spring容器中的唯一id,指上面已经实例化的cat对象 --> <bean id="person" class="com.hdu.setter.Person"> <!-- 单值注入 --> <property name="name" value="kuotian"></property> <property name="age" value="23"></property> <!-- 对象注入 --> <property name="cat" ref="cat"></property> </bean>
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.setter.Person; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_object.xml"); 13 //对象都是由spring创建和管理,对象的关系也要由spring来维护 14 Person person = context.getBean("person",Person.class); 15 System.out.println("Person:name="+person.getName()); 16 System.out.println("Person:age="+person.getAge()); 17 System.out.println("Person:Cat:type="+person.getCat().getType()); 18 System.out.println("Person:Cat:age="+person.getCat().getAge()); 19 } 20 }
2.3集合注入
toString是为了便于测试。
1 package com.hdu.setter; 2 3 import java.util.List; 4 import java.util.Map; 5 import java.util.Properties; 6 import java.util.Set; 7 8 public class Message { 9 private List list; 10 private Set set; 11 private Map map; 12 private Properties pros; 13 public void setList(List list) { 14 this.list = list; 15 } 16 public void setSet(Set set) { 17 this.set = set; 18 } 19 public void setMap(Map map) { 20 this.map = map; 21 } 22 public void setPros(Properties pros) { 23 this.pros = pros; 24 } 25 @Override 26 public String toString() { 27 return "Message [list=" + list + ", set=" + set + ", map=" + map + ", pros=" + pros + "]"; 28 } 29 }
2.3.1直接注入
<!-- 实例化Cat对象 --> <bean id="cat" class="com.hdu.setter.Cat"> <!-- 单值注入 --> <property name="type" value="smallCat"></property> <property name="age" value="3"></property> </bean> <!-- 直接集合注入 --> <bean id="message" class="com.hdu.setter.Message"> <property name="list"> <list> <!-- value引用的是单值 ref引用的事对象 --> <value>杭州</value> <value>17</value> <ref bean="cat" /> </list> </property> <property name="set"> <set> <value>杭州</value> <value>17</value> <ref bean="cat" /> </set> </property> <property name="map"> <map> <entry key="bj" value="北京"></entry> <entry key="hz" value="杭州"></entry> <entry key="cc" value-ref="cat"></entry> </map> </property> <property name="pros"> <props> <prop key="bj">北京</prop> <prop key="hz">杭州</prop> <prop key="sh">上海</prop> </props> </property> </bean>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.setter.Message; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_collection.xml"); 13 //直接注入 14 Message msg = context.getBean("message",Message.class); 15 System.out.println(msg); 16 } 17 }
2.3.2间接注入
间接注入,集合可复用多次。
beans需要引入util命名空间。
<?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" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 实例化Cat对象 --> <bean id="cat" class="com.hdu.setter.Cat"> <!-- 单值注入 --> <property name="type" value="smallCat"></property> <property name="age" value="3"></property> </bean> <!-- 间接集合注入 --> <util:list id="list"> <value>杭州</value> <value>17</value> <ref bean="cat" /> </util:list> <util:set id="set"> <value>杭州</value> <value>17</value> <ref bean="cat" /> </util:set> <util:map id="map"> <entry key="bj" value="北京"></entry> <entry key="hz" value="杭州"></entry> <entry key="cc" value-ref="cat"></entry> </util:map> <util:properties id="props"> <prop key="bj">北京</prop> <prop key="hz">杭州</prop> <prop key="sh">上海</prop> </util:properties> <bean id="message1" class="com.hdu.setter.Message"> <property name="list" ref="list"></property> <property name="set" ref="set"></property> <property name="map" ref="map"></property> <property name="pros" ref="props"></property> </bean> </beans>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.setter.Message; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_collection.xml"); 13 //直接注入 14 Message msg = context.getBean("message",Message.class); 15 System.out.println("直接注入:"+msg); 16 //间接注入 17 Message msg1 = context.getBean("message1",Message.class); 18 System.out.println("间接注入:"+msg1); 19 } 20 }
从结果看出两种注入方式的效果是一样的。
2.4表达式注入
2.4.1 ${}表达式
参考手册中的事例。
①准备一个properties文件。
jdbc_driverClass=com.mysql.jdbc.Driver jdbc_url=jdbc:mysql://localhost:3306/tmpdb jdbc_userName=root jdbc_userPassword=root
②存放数据相关类
1 package com.hdu.util; 2 3 public class JDBCUtil { 4 private String driverClass; 5 private String url; 6 private String userName; 7 private String password; 8 public String getDriverClass() { 9 return driverClass; 10 } 11 public void setDriverClass(String driverClass) { 12 this.driverClass = driverClass; 13 } 14 public String getUrl() { 15 return url; 16 } 17 public void setUrl(String url) { 18 this.url = url; 19 } 20 public String getUserName() { 21 return userName; 22 } 23 public void setUserName(String userName) { 24 this.userName = userName; 25 } 26 public String getPassword() { 27 return password; 28 } 29 public void setPassword(String password) { 30 this.password = password; 31 } 32 @Override 33 public String toString() { 34 return "JDBCUtil [driverClass=" + driverClass + ", url=" + url + ", userName=" + userName + ", password=" 35 + password + "]"; 36 } 37 }
③xml中beans需要引入context命名空间。
<?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" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 优先加载 先把属性文件加载到spring容器中 多个文件用逗号间隔 --> <context:property-placeholder location="classpath:resources/mysql.properties,resources/page.properties"/> <!-- 表达式注入 ${} --> <bean id="jdbcUtil" class="com.hdu.util.JDBCUtil"> <property name="driverClass" value="${jdbc_driverClass}"></property> <property name="url" value="${jdbc_url}"></property> <property name="userName" value="${jdbc_userName}"></property> <property name="password" value="${jdbc_userPassword}"></property> </bean> </beans>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.util.JDBCUtil; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_expression1.xml"); 13 //从容器中取出对象 14 JDBCUtil jdbcUtil = context.getBean("jdbcUtil", JDBCUtil.class); 15 System.out.println(jdbcUtil); 16 } 17 }
结果:
2.4.1 #{}表达式
③xml中beans需要引入util命名空间。
<?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" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 优先加载 先把属性文件加载到spring容器中 多个文件用逗号间隔 --> <util:properties id="manyProperties" location="classpath:resources/mysql.properties,resources/page.properties"></util:properties> <!-- 表达式注入 #{} --> <bean id="jdbcUtil" class="com.hdu.util.JDBCUtil"> <property name="driverClass" value="#{manyProperties.jdbc_driverClass}"></property> <property name="url" value="#{manyProperties.jdbc_url}"></property> <property name="userName" value="#{manyProperties.jdbc_userName}"></property> <property name="password" value="#{manyProperties.jdbc_userPassword}"></property> </bean> </beans>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.util.JDBCUtil; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_expression2.xml"); 13 JDBCUtil jdbcUtil = context.getBean("jdbcUtil", JDBCUtil.class); 14 System.out.println(jdbcUtil); 15 } 16 }
结果:
2.5空值注入
其中str2注入的是空值,而str1注入的只是空字符串。在测试方法中str1= str2=null的结果可以证明。
1 package com.hdu.util; 2 3 public class Kong { 4 private String str1; 5 private String str2; 6 public String getStr1() { 7 return str1; 8 } 9 public void setStr1(String str1) { 10 this.str1 = str1; 11 } 12 public String getStr2() { 13 return str2; 14 } 15 public void setStr2(String str2) { 16 this.str2 = str2; 17 } 18 @Override 19 public String toString() { 20 return "Kong [str1=" + str1 + ", str2=" + str2 + "]"; 21 } 22 }
str2才是注入空值。
<bean id="kong" class="com.hdu.util.Kong"> <property name="str1" value=""></property> <property name="str2"> <null></null> </property> </bean>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.util.Kong; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_setter_kong.xml"); 13 Kong kong = context.getBean("kong", Kong.class); 14 System.out.println(kong); 15 } 16 }
结果:
其中str2注入的是空值,而str1注入的只是空字符串。在测试方法中str1= str2=null的结果可以证明。
三.构造方法注入
1 package com.hdu.constructor; 2 3 import com.hdu.setter.Cat; 4 5 public class ConstructorDI { 6 private int age; 7 private Cat cat; 8 private String name; 9 public ConstructorDI() { 10 11 } 12 13 public ConstructorDI(int age, Cat cat, String name) { 14 super(); 15 this.age = age; 16 this.cat = cat; 17 this.name = name; 18 } 19 20 @Override 21 public String toString() { 22 return "ConstructorDI [age=" + age + ", cat=" + cat + ", name=" + name + "]"; 23 } 24 }
<!-- 实例化Cat对象 --> <bean id="cat" class="com.hdu.setter.Cat"> <property name="type" value="smallCat"></property> <property name="age" value="3"></property> </bean> <!-- index:从0开始,代表参数的位置 --> <bean id="constructor" class="com.hdu.constructor.ConstructorDI"> <constructor-arg index="0" value="20"></constructor-arg> <constructor-arg index="1" ref="cat"></constructor-arg> <constructor-arg index="2" value="张三"></constructor-arg> </bean>
测试
1 package com.hdu.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.hdu.constructor.ConstructorDI; 8 9 public class TestIOCDI { 10 @Test 11 public void testMethod() { 12 ApplicationContext context = new ClassPathXmlApplicationContext("resources/spring_constructor.xml"); 13 ConstructorDI constructor = context.getBean("constructor", ConstructorDI.class); 14 System.out.println(constructor); 15 } 16 }