创建应用对象之间的协作关系的行为通常被称作装配,这也是依赖注入的本质。
在spring中装配bean的方式有两种,手动装配和自动装配,手动装配顾名思义就是每一个bean都是自己写到xml里面,二自动装配的方式有两种,按类型装配和按名字装配
1、手动装配的例子
有三个类,一个是Person的基类,另两个类是服务于Person类的分别是Address和Car,先看这三个类:
Person.java
package com.roger.spring.beans
public class Person {
private String name;
private Address address;
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person [name=" + name + ", address=" + address + ", car=" + car
+ "]";
}
}
Address.java
package com.roger.spring.beans
public class Address {
private String city;
private String street;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
@Override
public String toString() {
return "Address [city=" + city + ", street=" + street + "]";
}
}
Car.java
package com.roger.spring.beans
public class Car {
private String brand;
private double price;
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;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", price=" + price + "]";
}
}
基于以上3个类进行手动配置xml文件
(以下,使用了Spring的命名空间p来装配属性,-ref作为后缀告诉Spring装配的应该是一个引用而不是字面值)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 手动装配Bean -->
<bean id="address" class="com.roger.spring.beans.Address"
p:city="WhuHan" p:street="Bayi"></bean>
<bean id="car" class="com.roger.spring.beans.Car"
p:brand="Audi" p:price="300000"></bean>
<bean id="person" class="com.roger.spring.beans.Person"
p:name="Roger" p:address-ref="address" p:car-ref="car"></bean>
</beans>
测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ctx.getBean("person");
System.out.println(person);
}
}
2、xml命名空间
aop | 为声明切面以及将@AspectJ注解的类代理为Spring切面提供了配置元素 |
beans | 支持声明Bean和装配Bean,是Spring最核心也是最原始的命名空间 |
context | 为配置Spring应用上下文提供了配置元素,包括自动检测和自动装配Bean、注入非Spring直接管理的对象 |
jee | 提供了与Java EE API的集成,例如JNDI和EJB |
jms | 为声明消息驱动的POJO提供了配置元素 |
lang | 支持配置由Groovy、JRuby或BeanShell等脚本实现的Bean |
mvc | 启用Spring MVC的能力,例如面向注解的控制器、视图控制器和拦截器 |
oxm | 支持Spring的对象到XML映射配置 |
tx | 提供声明式事务配置 |
util | 提供各种各样的工具类元素,包括把集合配置为Bean、支持属性占位符元素 |
3、构造器注入
<constructor-arg>元素使用:
<bean id="address" class="com.roger.spring.beans.Address">
<constructor-arg value="WhuHan" />
<constructor-arg value="Bayi" />
</bean>
<bean id="car" class="com.roger.spring.beans.Car">
<constructor-arg value="Audi" />
<constructor-arg value="300000" />
</bean>
<bean id="person" class="com.roger.spring.beans.Person"
<constructor-arg value="Roger" />
<constructor-arg ref="address" />
<constructor-arg ref="car" />
</bean>
使用构造器注入的前提是在类中声明另一种构造方法:
Address类
public Address(String city, String street){
this.city = city;
this.street = street;
}
Person类
public Person(String name, Address address, Car car) {
this.name = name;
this.address = address;
this.car = car;
}
4、setter注入
使用<property>元素来配置Bean,是通过调用属性的setter方法来注入值的。
<bean id="address" class="com.roger.spring.beans.Address">
<property name="city" value="WhuHan" />
<property name="street" value="Bayi" />
</bean>
其中value值得类型可以是String、数值型、boolean型等,Spring将根据Bean属性的类型自动判断value值的正确类型。
引用其他Bean
<bean id="address" class="com.roger.spring.beans.Address">
<property name="city" value="WhuHan" />
<property name="street" value="Bayi" />
</bean>
<bean id="car" class="com.roger.spring.beans.Car">
<property name="brand" value="Audi" />
<property name="price" value="300000" />
</bean>
<bean id="person" class="com.roger.spring.beans.Person"
<property name="name" value="Roger" />
<property name="address" ref="address" />
<property name="car" ref="car" />
</bean>
5、Bean的作用域
利用scope属性来设置
作用域 | 定义 |
singleton | 在每一个Spring容器中,一个Bean定义只有一个对象实例(默认) |
prototype | 允许Bean的定义可以被实例化任意次(每次调用都创建一个实例) |
request | 在一次HTTP请求中,每个Bean定义对应一个实例,该作用域仅在基于Web的Spring上下文(例如Spring MVC)中才有效 |
session | 在一个HTTP Session中,每个Bean定义对应一个实例,该作用域仅在基于Web的Spring上下文(例如Spring MVC)中才有效 |
global-session | 在一个全局HTTP Session中,每个Bean定义对应一个实例,该作用域仅Portlet上下文中才有效 |
例如:
<bean id="address" class="com.roger.spring.beans.Address" scope="prototype">
<constructor-arg value="WhuHan" />
<constructor-arg value="Bayi" />
</bean>
6、初始化和销毁Bean
利用init-method和destroy-method属性来设置
<!--Address类需要编写相应的名为init()和destroy()方法-->
<bean id="address" class="com.roger.spring.beans.Address"
init-method="init" destroy-method="destroy">
<constructor-arg value="WhuHan" />
<constructor-arg value="Bayi" />
</bean>
默认的init-method和destroy-method
如果在上下文定义的很多Bean都拥有相同名字的初始化方法和销毁方法,就没有必要为每一个Bean声明init-method和destroy-method属性,可以使用<beans>元素的default-init-method和default-destroy-method属性:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-init-method="init"
default-destroy-method="destroy">
</beans>
7、内部Bean
内部Bean是定义在其他Bean内部的Bean,可以利用<property>或者<constructor-arg>元素来声明内部Bean。
<bean id="person" class="com.roger.spring.beans.Person"
<property name="name" value="Roger" />
<property name="address" ref="address" />
<property name="car" ref="car" />
<property name="profession">
<bean class="com.roger.spring.beans.Profession">
</property>
</bean>
8、装配集合
当配置集合类型的属性时,Spring提供了4种集合配置元素。
集合元素 | 用途 |
<list> | 装配类型为java.util.Collection的任意实现或数组的属性,允许重复 |
<set> | 装配类型为java.util.Collection的任意实现或数组的属性,不允许重复 |
<map> | 装配map类型的值,名称和值可以是任意类型 |
<props> | 装配properties类型的值,名称和值必须都是String型 |
下面的例子分别展示了<list>、<map>和<props>的配置使用:
前提是假设存在两个已配置id为basketball和swim的Bean
A_<list>:假设Person类包括一个集合属性interestings
private List<Interesting> interestings;
public void setInterestings(List<Interesting> interestings) {
this.interestings = interestings;
}
xml配置:
<bean id="person" class="com.roger.spring.beans.Person"
<property name="name" value="Roger" />
<property name="address" ref="address" />
<property name="car" ref="car" />
<property name="interestings">
<list>
<ref bean="basketball" />
<ref bean="swim" />
</list>
</property>
</bean>
<list>的设置元素:<ref>、<value>、<bean>、<null/>,当然<list>也可以包括另一个<list>形成多维列表。
B_<map>:假设Person类包括一个集合属性interestings
private Map<String, Interesting> interestings;
public void setInterestings(Map<String, Interesting> interestings) {
this.interestings = interestings;
}
xml配置:
<bean id="person" class="com.roger.spring.beans.Person"
<property name="name" value="Roger" />
<property name="address" ref="address" />
<property name="car" ref="car" />
<property name="interestings">
<map>
<entry key="BASKETBALL" value-ref="basketball"/>
<entry key="SWIM" value-ref="swim"/>
</map>
</property>
</bean>
<entry>元素的属性:key、key-ref、value、value-ref
C_<props>:假设Person类包括一个集合属性interestings
private Map<String, String> interestings;
public void setInterestings(Map<String, String> interestings) {
this.interestings = interestings;
}
xml配置:
<bean id="person" class="com.roger.spring.beans.Person"
<property name="name" value="Roger" />
<property name="address" ref="address" />
<property name="car" ref="car" />
<property name="interestings">
<props>
<prop key="BASKETBALL">play basketball</prop>
<prop key="SWIM">go to swim</prop>
</props>
</property>
</bean>
注意:
- <property>元素用于Bean的属性注入;
- <props>元素用于定义一个java.util.Properties类型的集合值;
- <prop>元素用于定义<props>集合的一个成员。
9、装配空值
为属性设置null值,只需要使用<null/>元素
如:
<property name="someNonNullProperty"><null/></property>