spring中的DI----依赖注入

所谓的依赖注入,其实可以简单的理解为给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()这种方式就不再是调用无参构造器了,而是去调用相应有参的构造器。

猜你喜欢

转载自blog.csdn.net/dimples_qian/article/details/81301189