Spring 支持 3 种依赖注入的方式
1 属性注入
2 构造器注入
3 工厂方法注入(很少使用,不推荐)
属性注入
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
属性注入是实际应用中最常用的注入方式
<bean id = "helloWorld" class = "HelloWorld">
<property name="name" value = "Spring"></property>
</bean>
构造器注入
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中有 name 属性
新建一个Car类
/**
*@author Danbro
*@version 创建时间:2019年6月27日上午11:05:37
*@funcition
**/
public class Car {
private String brand;
private String corp;
private int price;
private int maxSpeed;
public Car(String brand, String corp, int price) {
super();
this.brand = brand;
this.corp = corp;
this.price = price;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
}
}
<bean id = "car" class = "Car">
<constructor-arg name = "brand" value = "audi"></constructor-arg>
<constructor-arg name = "corp" value = "20"></constructor-arg>
<constructor-arg name = "price" value = "30"></constructor-arg>
</bean>
Car car = ctx.getBean(Car.class);
System.out.println(car);
Car [brand=audi, corp=20, price=30, maxSpeed=0]
字面值:
可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。
<constructor-arg name = "price">
<!-- -->
<value>230</value>
</constructor-arg>
基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式
若字面值中包含特殊字符,可以使用 <![CDATA[]]> 把字面值包裹起来。
<constructor-arg name = "corp" >
<value><![CDATA[<shanghai>]]></value>
</constructor-arg>
引用其它 Bean
组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用
在 Bean 的配置文件中, 可以通过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.
新建一个Person类
/**
*@author Danbro
*@version 创建时间:2019年6月27日上午11:30:08
*@funcition
**/
public class Person {
private String name;
private Car mycar;
public String getName() {
return name;
}
public Car getMycar() {
return mycar;
}
public void setMycar(Car mycar) {
this.mycar = mycar;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [name=" + name + ", mycar=" + mycar + "]";
}
}
<bean id = "person" class = "Person">
<property name="name" value = "dan"></property>
<!-- 用property的ref属性建立bean之间的引用关系 -->
<property name="mycar" ref = "car"></property>
</bean>
------------------------------------------------------------
或者这样
<bean id = "person" class = "Person">
<property name="name" value = "dan"></property>
<!-- 用property的ref属性建立bean之间的引用关系 -->
<property name="mycar">
<ref bean = "car"/>
</property>
</bean>
Person p = ctx.getBean(Person.class);
System.out.println(p);
打印结果
Person [name=dan, mycar=Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=0]]
也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean,不能被外部引用,只能在内部使用
当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不需要设置任何 id 或 name 属性 内部 Bean 不能使用在任何其他地方
<bean id = "person" class = "Person">
<property name="name" value = "dan"></property>
<property name="mycar">
<bean id = "car3" class = "Car">
<constructor-arg value = "benz"></constructor-arg>
<constructor-arg value = "beijing"></constructor-arg>
<constructor-arg value = "22222"></constructor-arg>
</bean>
</property>
</bean>
注入参数详解:null 值和级联属性
可以使用专用的 <null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值
和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置。
为mycar属性赋null
<constructor-arg ><null/></constructor-arg>
Person [name=shan, mycar=null]
为级联属性赋值
<bean id = "person2" class = "Person">
<constructor-arg value = "shan"></constructor-arg>
<constructor-arg name = "mycar" ref = "car"></constructor-arg>
<property name="mycar.maxSpeed" value = "234"></property>//级联属性赋值,属性需要先初始化后才能赋值 否则会有异常
</bean>
Person [name=shan, mycar=Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=234]]
集合属性
在 Spring中可以通过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性.
配置 java.util.List 类型的属性, 需要指定 <list> 标签, 在标签里包含一些元素. 这些标签可以通过 <value> 指定简单的常量值, 通过 <ref> 指定对其他 Bean 的引用. 通过<bean> 指定内置 Bean 定义. 通过 <null/> 指定空元素. 甚至可以内嵌其他集合.
数组的定义和 List 一样, 都使用 <list>
配置 java.util.Set 需要使用 <set> 标签, 定义元素的方法与 List 一样.
List
import java.util.List;
/**
*@author Danbro
*@version 创建时间:2019年6月27日上午11:30:08
*@funcition
**/
public class Person {
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public Person(String name, List<Car> cars) {
super();
this.name = name;
this.cars = cars;
}
@Override
public String toString() {
return "Person [name=" + name + ", cars=" + cars + "]";
}
private String name;
private List<Car> cars;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
// TODO Auto-generated constructor stub
}
}
<bean id = "person3" class = "Person">
<property name="name" value = "john"></property>
<property name="cars">
<!--使用list节点为list类型赋值-->
<list>
<ref bean = "car"/>
<ref bean = "car2"/>
</list>
</property>
</bean>
Person [name=john, cars=[Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=0], Car [brand=benz, corp=<london>, price=2331, maxSpeed=0]]]
Map
Java.util.Map 通过 <map> 标签定义, <map> 标签里可以使用多个 <entry> 作为子标签. 每个条目包含一个键和一个值.
必须在 <key> 标签里定义键
因为键和值的类型没有限制, 所以可以自由地为它们指定 <value>, <ref>, <bean> 或 <null> 元素.
可以将 Map 的键和值作为 <entry> 的属性定义: 简单常量使用 key 和 value 来定义; Bean 引用通过 key-ref 和 value-ref 属性定义
使用 <props> 定义 java.util.Properties, 该标签使用多个 <prop> 作为子标签. 每个 <prop> 标签必须定义 key 属性.
定义一个NewPerson类
import java.util.List;
import java.util.Map;
/**
*@author Danbro
*@version 创建时间:2019年6月27日上午11:30:08
*@funcition
**/
public class NewPerson {
private String name;
private Map<String, Car> cars;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, Car> getCars() {
return cars;
}
public void setCars(Map<String, Car> cars) {
this.cars = cars;
}
@Override
public String toString() {
return "NewPerson [name=" + name + ", cars=" + cars + "]";
}
public NewPerson(String name, Map<String, Car> cars) {
super();
this.name = name;
this.cars = cars;
}
public NewPerson() {
// TODO Auto-generated constructor stub
}
}
<!-- 为map类型赋值 -->
<bean id = "newPerson" class = "NewPerson">
<property name="name" value = "Alice"></property>
<property name="cars">
<map>
<entry key = "AA" value-ref = "car"></entry>
<entry key = "BB" value-ref = "car2"></entry>
</map>
</property>
</bean>
NewPerson [name=Alice, cars={AA=Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=0], BB=Car [brand=benz, corp=<london>, price=2331, maxSpeed=0]}]
用来配置Properties属性值
先定义一个DataSource类
import java.util.Properties;
/**
*@author Danbro
*@version 创建时间:2019年6月27日下午12:36:31
*@funcition
**/
public class DataSource {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "DataSource [properties=" + properties + "]";
}
public DataSource(Properties properties) {
super();
this.properties = properties;
}
public DataSource() {
// TODO Auto-generated constructor stub
}
}
<!-- 配置Properties属性值 -->
<bean id = "dataSource" class = "DataSource">
<property name="properties">
<!--使用props和prop子节点配置-->
<props>
<prop key = "user">root</prop>
<prop key = "password">123456</prop>
<prop key = "jdbcUrl">jdbc:mysql://test</prop>
<prop key = "driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
打印出
DataSource [properties={driverClass=com.mysql.jdbc.Driver, user=root, password=123456, jdbcUrl=jdbc:mysql://test}]
配置独立的集合bean,以供多个bean进行引用,需要导入util命名空间
<!-- 配置独立的集合bean,以供多个bean进行引用,需要导入util命名空间 -->
<util:list id = "cars">
<ref bean = "car"/>
<ref bean = "car2"/>
</util:list>
<bean id = "person5" class = "Person">
<property name="name" value = "john"></property>
<!-- 把cars赋值给之前创建的集合bean cars -->
<property name="cars" ref = "cars"></property>
</bean>
Person [name=john, cars=[Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=0], Car [brand=benz, corp=<london>, price=2331, maxSpeed=0]]]
通过p命名空间为bean的属性赋值 需要先导入p命名空间,相对传统的方式更加简洁
<!-- 通过p命名空间为bean的属性赋值 需要先导入p命名空间 -->
<bean id = "person7" class = "Person" p:name = "Ben" p:cars-ref="cars"></bean>
Person [name=Ben, cars=[Car [brand=audi, corp=<shanghai>, price=230, maxSpeed=0], Car [brand=benz, corp=<london>, price=2331, maxSpeed=0]]]