spring支持3中依赖注入方式:
- 属性注入
- 构造器注入
- 工厂方法注入(很少使用,不推荐使用,这里我就不再写了)
1、属性注入
属性注入即通过 setter 方法注入 Bean 的属性值或以来的对象。属性注入使用 <property> 元素,使用 name 属性指定Bean的属性名称,value属性或者 <value> 子节点指定属性的值。
创建一个HelloWord类,一个Car类,一个Person类
HelloWord.java
public class HelloWord {
private String name;
public void setName(String name) {
this.name = name;
}
public void hello(){
System.out.println("Hello: " + name);
}
}
Car.java
public class Car {
private String brand;
private String color;
private double price;
private int maxSpeed;
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;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", color='" + color + '\'' +
", price=" + price +
", maxSpeed=" + maxSpeed +
'}';
}
public void setPrice(double price) {
this.price = price;
}
}
Person.java
public class Person {
private String name;
private int age;
private Car car;
private String sex;
private List<Car> cars;
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public Person() {
}
public Person(String name, int age, List<Car> cars, String sex) {
this.name = name;
this.age = age;
this.cars = cars;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getSex() {
return sex;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
", sex='" + sex + '\'' +
", cars=" + cars +
'}';
}
public void setSex(String sex) {
this.sex = sex;
}
}
bean.xml
<!-- 按照属性注入,依赖类中的set方法,bean中的id是唯一标识-->
<bean id="hello" class="it.hu.demo.HelloWord">
<property name="name" value="Spring"> </property>
</bean>
<bean id="hello" class="it.hu.demo.HelloWord">
<!--通过<value> 子节点指定值,在这个子节点中可以指定带有特殊符号的值,通过<![CDATA[xxx]]>实现 -->
<property name="name ">
<value>小小</value>
<!--<value><![CDATA[<XXX>]]> </value>-->
</property>
</bean>
为类中有引用变量指定值,例如:为Person类中的Car属性指定值,通过 ref 属性完成,或者使用内部 bean 的方式
<!-- 因为 Car 中只有构造方法,所以只能使用构造方法的方式注入,下边再讲这种方式 -->
<bean id="car" class="it.hu.demo.Car">
<constructor-arg value="baoma" type="java.lang.String"></constructor-arg>
<constructor-arg value="black" type="java.lang.String"></constructor-arg>
<constructor-arg value="128" type="int"></constructor-arg>
</bean>
<bean id="person1" class="it.hu.demo.Person">
<property name="name" value="小华"></property>
<property name="age" value="18"></property>
<property name="sex" value="女"></property>
<property name="car" ref="car"></property> <!-- 通过ref指向外部 Car 类型对应的 bean -->
</bean>
<bean id="person2" class="it.hu.demo.Person">
<property name="name" value="张三"></property>
<property name="age" value="20"></property>
<property name="sex" value="男"></property>
<property name="car" >
<bean class="it.hu.demo.Car">
<constructor-arg value="benchi"></constructor-arg>
<constructor-arg value="blue"></constructor-arg>
<constructor-arg value="8888888" type="double"></constructor-arg>
</bean>
</property> <!--内部 bean的方式为引用类型指定值 -->
</bean>
构造器注入
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。构造器注入在 元素里声明属性, 中没有 name 属性,在构造器注入的方法中通过type属性可以指定调用的是哪个重载的构造方法,通过 index 属性指明为那个参数赋值。在构造器方法中为引用类型指定值同样使用 ref 属性。
<!-- 使用 type 属性 -->
<bean id="car" class="it.hu.demo.Car">
<constructor-arg value="aodi" type="java.lang.String"></constructor-arg>
<constructor-arg value="red" type="java.lang.String"></constructor-arg>
<constructor-arg value="866886" type="double"></constructor-arg>
</bean>
<!-- 使用 index 属性 -->
<bean id="car" class="it.hu.demo.Car">
<constructor-arg value="aodi" index="0"></constructor-arg>
<constructor-arg value="red" index="1"></constructor-arg>
<constructor-arg value="866886" index="2"></constructor-arg>
</bean>
spring中 bean 的配置也支持 级联属性赋值。
<bean id="person1" class="it.hu.demo.Person">
<property name="name" value="小华"></property>
<property name="age" value="18"></property>
<property name="sex" value="女"></property>
<property name="car">
<bean class="it.hu.demo.Car">
<constructor-arg value="benchi"></constructor-arg>
<constructor-arg value="blue"></constructor-arg>
<constructor-arg value="8888888" type="double"></constructor-arg>
</bean>
</property>
<!--级联属性赋值,如果car的实例不存在spring不会自动创建,因此如果想要使用级联赋值前提是
为car变量赋值-->
<property name="car.price" value="123456789"></property>
</bean>
集合属性
在 Spring中可以通过一组内置的 xml 标签(例如: <list>, 或 <map>) 来配置集合属性.
配置 java.util.List 类型的属性, 需要指定 <list> 标签, 在标签里包含一些元素. 这些标签可以通过 <value> 指定简单的常量值, 通过 <ref> 指定对其他 Bean 的引用. 通过<bean> 指定内置 Bean 定义. 通过 <null/> 指定空元素. 甚至可以内嵌其他集合.
数组的定义和 List 一样, 都使用 <list>
配置 java.util.Set 需要使用 <set> 标签, 定义元素的方法与 List 一样.
<bean id="person2" class="it.hu.demo.Person">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
<property name="sex" value="男"></property>
<property name="cars">
<list>
<ref bean="car"></ref> <!-- 通过 ref 节点指向外部 Bean -->
<ref bean="car2"></ref>
<ref bean="car1"></ref>
<bean class="it.hu.demo.Car"> <!-- 通过创建内部 Bean 赋值 -->
<constructor-arg value="劳斯莱斯" ></constructor-arg>
<constructor-arg value="write"></constructor-arg>
<constructor-arg value="12354678" type="double"></constructor-arg>
</bean>
</list>
</property>
</bean>
为Map属性赋值,通过 <map> 标签定义,<map> 标签里可以使用多个<entry> 作为子标签. 每个条目包含一个键和一个值. 可以通过 value-ref 属性指向外部 Bean,也可以使用内部 Bean 完成赋值
<bean id="person3" class="it.hu.demo.Humn">
<property name="name" value="不知火舞" ></property>
<property name="sex" value="女"></property>
<property name="age" value="18"></property>
<property name="carMap">
<map>
<entry key="AA" value-ref="car"></entry>
<entry key="BB" value-ref="car2"></entry>
<entry key="CC" value-ref="car1"></entry>
<entry key="DD">
<!--内部bean-->
<bean class="it.hu.demo.Car">
<constructor-arg value="baoma"></constructor-arg>
<constructor-arg value="black"></constructor-arg>
<constructor-arg value="123456" type="double"></constructor-arg>
</bean>
</entry>
</map>
</property>
</bean>
使用基本集合标签定义集合时,将集合作为某个独立的Bean定义,无法在其他 Bean 中引用,无法做到共享。使用 util schema 定义独立的集合 Bean 可以在 Bean 之间共享
<!--将bean抽取出来为list元素赋值,可以被多个bean引用-->
<util:list>
<ref bean="car1"></ref>
<ref bean="car2"></ref>
<ref bean="car"></ref>
</util:list>
<!--将bean抽取出来为map元素赋值,可以被多个bean引用-->
<util:map id="map">
<entry key="AAA" value-ref="car1"></entry>
<entry key="BBB" value-ref="car2"></entry>
<entry key="CCC" value-ref="car"></entry>
</util:map>
<bean id="person3" class="it.hu.demo.Humn">
<property name="name" value="不知火舞" ></property>
<property name="sex" value="女"></property>
<property name="age" value="18"></property>
<property name="carMap" ref="map"> <!-- 通过外部的集合bean直接引用,list也是类似的 -->
</bean>
使用 p 命名空间可以使 Bean 的配置变得更加的简洁
<bean id="ccc" class="it.hu.demo.Humn" p:age="18" p:name="小华" p:sex="男"
p:carMap-ref="map"></bean>