所谓的依赖注入,其实可以简单的理解为给bean设置属性值,那么给属性赋值有几种方式:
1、使用构造函数注入
2、使用set方法注入
3、使用注解注入
注入的值类型不同,写法也不同,注入的属性类型有如下几种:
1、基本类型和String类型
2、其他bean类型(必须是在bean.xml中配置过的)
3、复杂类型(集合类型:数组、List、Set、Map、Properties)
那么现在我们先试试用构造器的方式注入:
这是service类:
package com.dimples.service.impl;
import java.util.Date;
import com.dimples.service.ICustomerService;
public class CustomerServiceImpl implements ICustomerService {
private String name;
private int num;
private Date date;
public CustomerServiceImpl(String name, Integer num, Date date) {
super();
this.name = name;
this.num = num;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public CustomerServiceImpl() {
System.out.println("serviceImpl创建了");
}
@Override
public void saveCustomer(Object obj) {
System.out.println(name + num + date);
}
}
这是bean.xml的配置:
<bean id="customerService" class="com.dimples.service.impl.CustomerServiceImpl" scope="singleton">
<constructor-arg name="name" value="小明"></constructor-arg>
<constructor-arg name="num" value="1"></constructor-arg>
<constructor-arg name="date" ref="today"></constructor-arg>
</bean>
<bean id="today" class="java.util.Date"></bean>
这是测试代码:
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
/*
* 这里其实就体现了接口的好处。我们spring中采用bean工厂的模式创建bean,很大一个好处就是可以变编译依赖为运行依赖,降低程序耦合性,那么在这里,
如果我们需要用这个bean中具体的方法,就不得不将其强转为对应类型,如果转为具体的类,那么就需要导入相应的类,也就是说那个类需要提前写好,这样
的话又变成了编译依赖,那spring用工厂生成bean就毫无意义了,如果这里用接口,我们可以只导接口,并正常用其所有方法,而我们知道接口中的方法都是
未实现方法,只需要知道入参和返回值就可以了,所以写接口相对于写类来说要方便的多,这也是为什么实际开发中总是先开发接口的原因。
*/
ICustomerService cs = (ICustomerService)ac.getBean("customerService");
cs.saveCustomer("aaa");
}
结果:
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
小明1Tue Jul 31 11:27:15 CST 2018
但是值得注意的是,我们一般不用构造器的方式去注入,因为我们不确定我们需要注入哪几个参数,从而不能确定提前写好哪些构造器,比如有三个属性,可能到时候需要注入两个属性,也可能是注入三个,那么我不确定你要注入几个,我就必须把所有情况的构造器都写好,这样显然很麻烦。而用set方法注入的方式,只要给每个属性写上set方法,你想注入哪些属性直接写就好了,现在我们用set方法去注入,注意bean中配置的name需要和set方法一致,而不是和属性名一致。
这是bean.xml的配置:
<bean id="customerService" class="com.dimples.service.impl.CustomerServiceImpl" scope="singleton">
<property name="name" value="xiaohua"></property>
<property name="num" value="1"></property>
<property name="date" ref="today"></property>
<property name="list">
<list>
<value>"AAA"</value>
<value>"BBB"</value>
<value>"CCC"</value>
</list>
</property>
<!--这里可以看到数组类型属性我用set标签去注入的也可以,实际上,数组、list、set是一组,他们的标签可以互换,map、properties是一组,他们的标签也可以互用-->
<property name="strs">
<set>
<value>"AAA"</value>
<value>"BBB"</value>
<value>"CCC"</value>
</set>
</property>
<property name="set">
<array>
<value>"AAA"</value>
<value>"BBB"</value>
<value>"CCC"</value>
</array>
</property>
<property name="map">
<map>
<entry key="a" value="aaa"></entry>
<entry key="a" value="aaa"></entry>
</map>
</property>
<property name="props">
<props>
<prop key="a">"aaa"</prop>
<prop key="b">"bbb"</prop>
</props>
</property>
</bean>
-->
<bean id="today" class="java.util.Date"></bean>
这是service类:
package com.dimples.service.impl;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import com.dimples.service.ICustomerService;
public class CustomerServiceImpl implements ICustomerService {
private String name;
private int num;
private Date date;
private List<String> list;
private String[] strs;
private Set<String> set;
private Map<String,String> map;
private Properties props;
public CustomerServiceImpl(String name, Integer num, Date date) {
super();
this.name = name;
this.num = num;
this.date = date;
System.out.println("有参构造器调用了!");
}
public void setList(List<String> list) {
this.list = list;
}
public void setStrs(String[] strs) {
this.strs = strs;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public CustomerServiceImpl() {
System.out.println("serviceImpl创建了");
}
@Override
public void saveCustomer(Object obj) {
System.out.println(name + num + date);
System.out.println(list);
System.out.println(Arrays.toString(strs));
System.out.println(map);
System.out.println(set);
System.out.println(props);
}
}
最后顺带说一下:我们说bean的创建方式有三种,如上面我用构造器方式注入的情况,bean的创建方式就是Class.forName().newInstance.可我们发现这次无参构造器并没有被调用,而是那个有参数的构造器被调用了,也就是说,当我们使用构造器的方式去注入的时候,Class.forName().newInstance()这种方式就不再是调用无参构造器了,而是去调用相应有参的构造器。