Spring学习6(2)依赖注入

Spring学习6(2)

 Spring支持三种依赖注入方式,分别是属性注入和构造函数注入,工厂方法注入,这里将了解不同依赖注入函数的具体配置方法。

属性注入

 所谓的属性注入就是通过setXXX()方法来注入Bean的属性值或依赖对象,其灵活读高,是实际应用中最长采用的方式。

属性注入实例

 属性注入要求Bean提供一个默认的构造函数,并为注入的属性提供对应的Setter方法。过程是先实例化对象,而后用反射的方式调用Setter方法注入属性值。
 这里就用car的例子来看:

	public void setBrand(String brand) {
		this.brand = brand;
		System.out.println("调用setBrand()设置属性。");
	}
	
	public void setPrice(double price) {
		this.price = price;
		System.out.println("调用setPrice()设置属性。");
	}
	
	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
		System.out.println("调用setMaxSpeed()设置属性。");
	}

 这里的三个setXXX就是所谓的Setter方法,在beans中的代码如下:

	<bean id="car1" class="com.smart.Car"
	init-method="myInit"
	destroy-method="myDestroy">
	<property name="maxSpeed"><value>200</value></property>
	<property name="brand"><value>红旗CA72</value></property>
	<property name="price"><value>20000.00</value></property>
	</bean>
	</beans>

 上述代码配置了一个Bean并为该Bean的3个属性提供了一个属性值,Bean的每一个属性对应一个<property>标签,name为属性的名称,并且要求在Bean的实现类有其setter方法。
 特别注意的是,spring只会查看是否有setter方法,并不会关注有无这个变量的存在,如下面这种情况:

public class Car{
	private int maxSpeed;
	private double price;
	
	public void setBrand(String brand){
		System.out.println("设置Brand属性");
		}

javaBean关于属性命名的特殊规范

 Spring配置文件中<property>元素所指定的属性名和Bean实现类的Setter方法满足属性命名规范:xxx属性对应setXxx()方法。
 一般情况下,java的属性变量都用小写字母开头,但是也允许以大写字母开头的属性变量名,不过必须满足变量的前两个字母要么都大写,要么都小写,如brand,IDCode,IC等属性变量名是合法的,而iCcard,iDCode这些是非法的。
 下面是一个“违反”了JavaBean属性命名规范的类:

public class Foo{
	//非法的属性变量名,不过Java语言本身不会报错,因为它将iDCode看车普通的变量
	private String iDCode;
	//该方法对应IDCode属性而非iDCode属性
	pubic void setIDCode(String iDcode){
	this.iDcode = iDcode;
	}
}

 在配置文件中,我们或许会使用如下的配置,但是这是错误的:

<bean id="foo" class="com.smart.attr.Foo">
	<property name="iDCode" value="0000"/>
</bean>

 系统报错的原因也是没找到setter方法而不是我们的命名错误,我们需要将配置改成:

<bean id="foo" class="com.smart.attr.Foo">
	<property name="IDCode" value="0000"/>
</bean>

 所以我们需要尽量的避免这种成员变量的出现。

构造函数注入

 构造函数注入是另一种常用的注入方式,它保证在一些必要的属性在Bean实例化时就得到设置,确保Bean在实例化后就可以使用。

按类型匹配入参

 如果任何可用对象都必须提供特定成员变量的值,那么只使用属性注入方式则只能人为的在配置时提供保证,而无法提供语法级的保证,所以必须要有构造函数注入。
 我们假设有如下这个构造函数的存在

	public Car(String brand, double price) {
		this.brand = brand;
		this.price = price;
	}
	

 那么我们在配置文件中使用如下代码进行配置:

	<bean id="car2" class="com.smart.Car">
		<constructor-arg type="java.lang.String">
			<value>红旗CA72</value>
		</constructor-arg>
		<constructor-arg type="double">
			<value>20000</value>
		</constructor-arg>
	</bean>

 在<constructor-arg>元素中有一个type属性,它为Spring提供了判断配置项和构造函数入参对应关系的“信息”,来避免多个具有相同入参的构造函数所造成的问题。

按索引匹配入参

 java语言通过入参的类型及顺序区分不同的重载方法。如果car构造函数有两个类型相同的入参那么仅仅通过type就无法对应关系了,这时候就需要通过入参索引的方式进行确定。

 下面我们对构造函数进行调整如下:

	public Car(String color, double price,String brand) {
		this.brand = brand;
		this.price = price;
		this.color = color;
	}

 那么我们可以指定索引来避免混淆,索引从0开始。

	</bean>
		<bean id="car2" class="com.smart.Car">
		<constructor-arg index="0" value="black"/>
		<constructor-arg index="1" value="20000"/>
		<constructor-arg index="2" value="红旗CA72"/>
	</bean>

联合使用类型和索引匹配入参

 如果有下列两个构造函数就需要联合使用上述两种方法进行配置。

	public Car(String brand, String color, double price) {
		this.brand=brand;
		this.color=color;
		this.price=price;
	}
	
	public Car(String brand, String color, int maxSpeed) {
		this.brand=brand;
		this.color=color;
		this.maxSpeed=maxSpeed;
	}

 例如我们要使用第二个构造函数来实例化Bean,则代码如下:

	<bean id="car4", class="com.smart.Car">
	<construuctor-arg index="0">
		<value>红旗XXX</value>
	</construuctor-arg>
	<constructor-arg index="1">
		<value>白色</value>
	</constructor-arg>
	<constructor-arg index="2" type="int">
		<value>200</value>
	</constructor-arg>
	</bean>

通过自身类型反射匹配入参

 如果Bean的构造函数入参的类型非基础数据类型且入参类型各异,那么即使步提供index和type也可以完成注入工作。

循环依赖

 Spring容器能对构造函数配置的Bean进行实例化有一个前提即是Bean构造函数入参应用的对象都已经准备就绪。如果两个Bean都采用构造函数并且互为入参,那么就会发生死循环,这时候就需要修改构造函数为setter函数。

工厂方法注入

 工厂方法已经成为底层的一部分,不过有些时候仍然需要,所以这里做一个介绍。

非静态工厂方法

 对于这类方法必须实例化工厂类后才能调用工厂方法,下面是一个非静态的工厂类方法。

package com.smart.ditype;
public class CarFactory{
	public Car createHongQiCar(){
		Car car=new Car();
		car.setBrand("红旗");
		return car;
		}
	}

 工厂类负责创建一个或多个目标实例,一般以接口或抽象类变量的形式放回目标类实例。它对外屏蔽目标类的实例化步骤,调用者甚至不知道目标类。下面的配置就提供了工厂化的注入。

<bean id="carFactory" class="com.smart.ditype.CarFactory"/>
	<bean id="car6" factory-bean="carFactory"
					factory-method="createHongQiCar"/>

 它首先需要定义一个工厂类的Bean,而后通过factory-bean应用工厂类实例,最后通过factory-method指定对应的工厂类方法。

静态工厂方法

 相当多的工厂类方法都是静态的,意味着无需实例化就可以使用:

public static Car createHongQiCar(){
...
}

 配置如下

<bean id="car7" class="com.smart.ditype.CarFactory" factory-method="createHongQiCar"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值