一、介绍:Dependency Injection,组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
二、三种依赖注入的方式
(1)setter方法注入:使用属性的setter方法注入 ,这是最常用的方式。Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。前提是Bean提供一个默认的构造函数;
(2)构造方法注入:是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。?前提是Bean必须提供带参的构造函数;
(3)接口注入:由于在灵活性和易用性比较差,从Spring4开始已被废弃。
构造函数注入 | setter?注入 |
---|---|
没有部分注入 | 有部分注入 |
不会覆盖 setter 属性 | 会覆盖 setter 属性 |
任意修改都会创建一个新实例 | 任意修改不会创建一个新实例 |
适用于设置很多属性 | 适用于设置少量属性 |
具体来看下:
1、setter属性注入:
(1)语法:
<bean id=”……” class=”……”>
<property name=”属性1” value=”……”/>
<property name=”属性2” value=”……”/>
……
</bean>
(2)demo:?
1、bean
package com.demo.model;
public class Car {
private int maxSpeed;
private String brand;
private double price;
public int getMaxSpeed() {
return maxSpeed;
}
//一定要写被注入对象的set方法
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public void run(){
System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
}
}
2、
<!-- 属性注入 -->
<bean id="car" class="com.demo.model.Car">
<property name="maxSpeed" value="200"></property>
<property name="brand" value="红旗CA72"></property>
<property name="price" value="200000.00"></property>
</bean>
3、测试:
public void test(){
//读取配置文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean的实例
Car car=(Car) ctx.getBean("car");
car.run();
}
2、构造函数注入:
(1)语法:
? ? ① 在类中,不用为属性设置setter方法,但是需要生成该类带参的构造方法;
? ? ② 在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了<constructor-arg>节点,该节点有四个属性: · index是索引,指定注入的属性,从0开始; · type是指该属性所对应的类型; · ref 是指引用的依赖对象; · value 当注入的不是依赖对象,而是基本数据类型时,就用value;?
(2)方式:有三种:
? ?① 按类型匹配入参:在<constructor-arg>的元素中有一个type属性,它表示构造函数中参数的类型,为spring提供了判断配置项和构造函数入参对应关系的“信息”。
package com.demo.model;
public class Car {
private int maxSpeed;
private String brand;
private double price;
//带参构造方法
public Car(int maxSpeed,String brand, double price){
this.maxSpeed=maxSpeed;
this.brand=brand;
this.price=price;
}
public void run(){
System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
}
}
<!-- 构造函数注入(按类型匹配) -->
<bean id="car1" class="com.demo.model.Car">
<constructor-arg type="int" value="300"></constructor-arg>
<constructor-arg type="java.lang.String" value="宝马"></constructor-arg>
<constructor-arg type="double" value="300000.00"></constructor-arg>
</bean>
②?按索引匹配入参:
public Car(String brand, String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
<!-- 构造函数注入(按索引匹配) -->
<bean id="car2" class="com.demo.model.Car">
<!-- 注意索引从0开始 -->
<constructor-arg index="0" value="宝马"></constructor-arg>
<constructor-arg index="1" value="中国一汽"></constructor-arg>
<constructor-arg index="2" value="300000.00"></constructor-arg>
</bean>
?③?联合使用类型和索引匹配入参:
public Car(String brand, String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
public Car(String brand, String corp,int maxSpeed){
this.brand=brand;
this.corp=corp;
this.maxSpeed=maxSpeed;
}
<!-- 构造函数注入(通过入参类型和位置索引确定对应关系) -->
<!-- 对应public Car(String brand, String corp,int maxSpeed)构造函数 -->
<bean id="car3" class="com.demo.model.Car">
<constructor-arg index="0" type="java.lang.String" value="奔驰"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="中国一汽"></constructor-arg>
<constructor-arg index="2" type="int" value="200"></constructor-arg>
</bean>