文章目录
背景
- 在《Spring完整揭秘(一):IoC》文章中描述了IoC Service Provider 的基本职责:
- 对象的构建管理;
- 对象间的依赖绑定;
本文将针对Spring的 IoC容器中的IoC Service Provider功能进行深入剖析。
Spring 的 IoC容器
Spring的IoC容器除了基本的IoC支持,还提供了相应的AOP框架支持、企业级服务集成等功能。
Spring的IoC容器之BeanFactory
- BeanFactory是基础类型IoC容器,Spring BeanFactory相关UML结构图如下:
- BeanFactory 的定义
用 BeanFactory 的XML配置方式实现业务对象间的依赖管理
格式
- XML格式的容器信息管理方式是Spring提供的最为强大、支持最为全面的方式。
<!-- 基于XSD的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="" class="">
...
</bean>
</beans>
beans
- “beans” 是XML配置文件中最顶层的元素 包括如下属性:
- default-lazy-init 。其值可以指定为 true 或者 false ,默认值为 false 。用来标志是否对所有的 bean 进行延迟初始化。
- default-autowire 。可以取值为 no 、 byName 、 byType 、 constructor 以及autodetect 。默认值为 no ,如果使用自动绑定的话,用来标志全体bean使用哪一种默认绑定方式。
- default-dependency-check 。可以取值 none 、 objects 、 simple 以及 all ,默认值为 none ,即不做依赖检查。
- default-init-method 。如果所管辖的 bean 按照某种规则,都有同样名称的初始化方法的话,可以在这里统一指定这个初始化方法名,而不用在每一个 bean 上都重复单独指定。
- default-destroy-method 。与 default-init-method 相对应,如果所管辖的bean有按照某种规则使用了相同名称的对象销毁方法,可以通过这个属性统一指定。
bean
- Bean是指每个业务对象个体
<!--食物对象-->
<bean id="food1" class="Food">
<property name="foodType" value="面食"></property>
<property name="foodName" value="馄饨面"></property>
<property name="foodNum" value="1"></property>
</bean>
<bean id="food2" class="Food">
<property name="foodType" value="面食"></property>
<property name="foodName" value="重庆小面"></property>
<property name="foodNum" value="1"></property>
</bean>
<!--人物对象-->
<bean id="person1" class="Person" scope="prototype">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="food" ref="food1"></constructor-arg>
</bean>
<bean id="person2" class="Person" scope="prototype">
<constructor-arg name="name" value="李四"></constructor-arg>
<constructor-arg name="food" ref="food2"></constructor-arg>
</bean>
- id 属性:指定 bean 在容器中的标志
- class 属性: 每个注册到容器的对象都需要通过 bean>元素的 class 属性指定其类型
- constructor-arg:通过构造方法注入方式,为当前业务对象注入其所依赖的对象
- name 构造方法传入的参数名称
- value 构造方法传入的参数值
- ref:引用的Bean实例
- 使用 list 进行依赖注入的对象定义以及相关配置内容
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<description>SpringIoc</description>
<bean id="food1" class="Food">
<property name="foodType" value="面食"/>
<property name="foodName" value="馄饨面"/>
<property name="foodNum" value="1"/>
</bean>
<bean id="food2" class="Food">
<property name="foodType" value="面食"/>
<property name="foodName" value="重庆小面"/>
<property name="foodNum" value="1"/>
</bean>
<!-- 通过setter注入list 对象-->
<bean id="person1" class="Person" scope="prototype">
<property name="name" value="张三"/>
<property name="foods" >
<list>
<ref bean="food1"/>
<ref bean="food2"/>
</list>
</property>
</bean>
</beans>
bean 的 scope
- scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,目前存在singleton和prototype,request、session和global session类型
- singleton :在Spring的IoC容器中只存在一个对象实例
- prototype:容器在接到该类型对象的请求的时候,会每次都重新生成一个新的对象实例给请求方
- request:XmlWebApplicationContext 会为每个HTTP请求创建一个全新的 Request-Processor 对象供当前请求使用,当请求结束后,该对象实例的生命周期即告结束
- session:Spring容器会为每个独立的session创建属于它们自己的全新的对象实例
BeanFactory的完整例子
- Food.Class
/**
* 食物类
*
* @author zhuhuix
* @date 2020-0730
*/
public class Food {
// 类型
private String foodType;
// 名称
private String foodName;
// 数量
private int foodNum;
public Food(){}
public Food(String foodType, String foodName, int foodNum) {
this.foodType = foodType;
this.foodName = foodName;
this.foodNum = foodNum;
}
public String getFoodType() {
return foodType;
}
public void setFoodType(String foodType) {
this.foodType = foodType;
}
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public int getFoodNum() {
return foodNum;
}
public void setFoodNum(int foodNum) {
this.foodNum = foodNum;
}
@Override
public String toString() {
return "Food{" +
"foodType='" + foodType + '\'' +
", foodName='" + foodName + '\'' +
", foodNum=" + foodNum +
'}';
}
}
- Person.Class
/**
* 人物类
*
* @author zhuhuix
* @date 2020-0730
* /
*/
public class Person {
// 姓名
private String name;
// 食物
private Food food;
public Person(String name, Food food) {
this.name = name;
this.food = food;
}
public void havaLunch() {
System.out.println(getName() + "进食午餐:" + this.food.toString());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Food getFood() {
return food;
}
public void setFood(Food food) {
this.food = food;
}
}
- bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="food1" class="Food">
<property name="foodType" value="面食"></property>
<property name="foodName" value="馄饨面"></property>
<property name="foodNum" value="1"></property>
</bean>
<bean id="food2" class="Food">
<property name="foodType" value="面食"></property>
<property name="foodName" value="重庆小面"></property>
<property name="foodNum" value="1"></property>
</bean>
<bean id="person1" class="Person" scope="prototype">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="food" ref="food1"></constructor-arg>
</bean>
<bean id="person2" class="Person" scope="prototype">
<constructor-arg name="name" value="李四"></constructor-arg>
<constructor-arg name="food" ref="food2"></constructor-arg>
</bean>
</beans>
- Application.java
/**
* beanFactory加载
*
* @author zhuhuix
* @date 2020-07-30
*/
public class Application {
public static void main(String[] args) {
DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();
// XmlBeanDefinitionReader 负责读取Spring指定格式的XML配置文件并解析\
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanRegistry);
xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("bean.xml"));
BeanFactory beanFactory = beanRegistry;
Food food1 = (Food) beanFactory.getBean("food1");
System.out.println(food1.toString());
Food food2 = (Food) beanFactory.getBean("food2");
System.out.println(food2.toString());
Person person1 = (Person) beanFactory.getBean("person1");
person1.havaLunch();
Person person2 = (Person) beanFactory.getBean("person2");
person2.havaLunch();
}
}
- 运行结果