Spring的依赖注入
依赖注入的概念
它是spring框架核心ioc的具体实现。我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况 。ioc解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用数据访问层的方法。这种业务层和数据访问层的依赖关系,在使用spring之后,就让spring来维护了。简单的说,就是坐等框架把数据访问层对象传入业务层,而不用我们自己去获取组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中
依赖注入的目的
并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现
Spring依赖注入的两种方式
1)构造函数注入
使用类中的构造函数,给成员变量赋值,注意:赋值的操作不是我们自己做的,而是通过配置的方式,让spring框架来为我们注入
<constructor-arg>标签
属性
- 给谁赋值
・index:指定参数在构造函数参数列表的索引位置
・type:指定参数在构造函数中的数据类型
・name:指定参数在构造函数中的名称,用这个找给谁赋值 - 赋什么值
・value:它能赋的值是基本数据类型和String类型
・ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean
beans.xml文件中
//会根据class="cn.xh.Demo01.Car"创建对象,并且给这个对象的属性赋值
<bean id="car" class="cn.xh.Demo01.Car">
//Car类的构造方法第一个参数是brand,第二个参数是price,下面这两行是分别给这两个参数赋值的
<constructor-arg index="0" value="奔驰"></constructor-arg>
<constructor-arg index="1" value="180000"></constructor-arg>
//Car类里price是double类型,但这个配置文件里都要写String类型的,到时会转换
//上面那种不容易判断到底是给谁赋值了,还要去Car类里看,常用的是下面这种
<constructor-arg name="brand" value="奔驰"></constructor-arg>
<constructor-arg name="price" value="180000"></constructor-arg>
</bean>
<bean id="person" class="cn.xh.Demo01.Person">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
Car.java文件中
public class Car {
private String brand;
private Double price;
//要写带参的构造函数
public Car(String brand, Double price) {
this.brand = brand;
this.price = price;
}
public String toString() {
return "Car{" + "brand='" + brand + '\'' + ",price=" + price + '}';
}
}
}
Person.java文件中
public class Person {
private String name;
private Car car;
//要写带参的构造函数
public Person(String name, Car car) {
this.name = name;
this.car = car;
}
public String toString() {
return "Person{" + "name='" + name + '\'' + ",car=" + car + '}';
}
}
}
Test.java文件中
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Car car = (Car)context.getBean("car");
System.out.println(car.toString());
//运行结果为打印输出:Car{brand='奔驰', price=180000.0}
Person p = (Person)context.getBean("person");
System.out.println(p.toString());
//运行结果为打印输出:Person{name='张三', car=Car{brand='奔驰', price=180000.0}}
}
}
2) set方法的方式注入属性
beans.xml文件中
<bean id="car" class="cn.xh.Demo01.Car">
<property name="brand" value="奔驰"></property>
<property name="price" value="180000"></property>
</bean>
<bean id="person" class="cn.xh.Demo01.Person">
<property name="name" value="张三"></property>
<property name="car" ref="car"></property>
</bean>
Car.java文件中
public class Car {
private String brand;
private Double price;
//不能有有参数的构造函数,否则会报错
/* public Car(String brand, Double price) {
this.brand = brand;
this.price = price;
}*/
//一定要加set方法,否则注入无法实现
public void setBrand(String brand) {
this.brand = brand;
}
public void setPrice(Double price) {
this.price = price;
}
public String toString() {
return "Car{" + "brand='" + brand + '\'' + ",price=" + price + '}';
}
}
}
Person.java文件中
public class Person {
private String name;
private Car car;
//不能有有参数的构造函数,否则会报错
/*public Person(String name, Car car) {
this.name = name;
this.car = car;
}*/
public void setName(String name) {
this.name = name;
}
public void setCar(Car car) {
this.car = car;
}
public String toString() {
return "Person{" + "name='" + name + '\'' + ",car=" + car + '}';
}
}
}
Test.java文件中
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Car car = (Car)context.getBean("car");
System.out.println(car.toString());
//运行结果为打印输出:Car{brand='奔驰', price=180000.0}
Person p = (Person)context.getBean("person");
System.out.println(p.toString());
//运行结果为打印输出:Person{name='张三', car=Car{brand='奔驰', price=180000.0}}
}
}
3) 集合和数组注入(通过set注入)
beans.xml文件中
<bean id="collections" class="cn.xh.Demo01.Collections">
<property name="str">
<list>
<value>北京</value>
<value>上海</value>
</list>
</property>
<property name="list">
<list>
<value>北京</value>
<value>上海</value>
</list>
</property>
*************************************************
<property name="map">
<map>
<entry key="1" value="张三"></entry>
<entry key="2" value="李四"></entry>
</map>
</property>
<property name="prop">
<props>
<prop key="1">张三</prop>
<prop key="2">李四</prop>
</props>
*************************************************
=================================================
//上面*框起来的部分也可以像下面这样写,效果都是一样的
<property name="map">
<props>
<prop key="1">张三</prop>
<prop key="2">李四</prop>
</props>
</property>
<property name="prop">
<map>
<entry key="1" value="张三"></entry>
<entry key="2" value="李四"></entry>
</map>
</property>
=================================================
</bean>
Collections.java文件中
public class Collections {
private String[] str;
private List<String> list;
private Map<String,String> map;
private Properties prop;
public void setStr(String[] str) {
this.str = str;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String,String> map) {
this.map = map;
}
public void setProp(Properties prop) {
this.str = str;
}
public String toString() {
return "Collections {" + "str=" + Arrays.toString(str) + ", list=" + list + ", map=" + map + ",prop=" + prop +'}';
}
}
Test.java文件中
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Collections col = (Collections)context.getBean("collections");
System out. Println(col.toString());
//执行结果为打印输出:Collections{str=[北京,上海], list=[北京,上海], map={1=张三, 2=李四}, prop={2=李四, 1=张三}}
}
}