本章目标
- 了解Spring的历史和发胀概况
- 掌握Spring IoC容器的大致设计
- 掌握Spring IoC的实现过程
- 掌握Spring Bean的生命周期
Spring 的概述
一些历史可以自行百度
这里做个小总结,Spring提供以下策略:
- 对于POJO的潜力开发,提供了轻量级和低侵入的编程,可以通过配置XML或者注解等来扩展POJO的功能,通过依赖注入的理念去扩展功能,建议通过接口编程,强调OOD的开发模式理念,降低耦合度,提高系统可读性和扩展性
- 提供切面编程,使得开发人员能够集中于业务开发而不是技术本身,也避免了try…catch…finally语句的滥用
- 为了整合各个框架和技术的应用,Spring提供了模版类,通过模版类可以整合各个框架和技术,比如支持Hibernate开发的HibernateTemplate、支持MyBatis开发的SplSessionTemplate、支持Redis开发的RedisTemplate等,这样就把各种技术框架整合到Spring中,提供了统一的模版。
Spring IoC 概述
主要理解两个概念:
1. 控制反转
2. 依赖注入
场景:A类中包含B类的对象b
控制反转:以前对象b需要程序员自己创建,主动权在程序员,现在这个对象不需要程序员自己创建,由容器来创建。
依赖注入:上面IoC容器负责对象的创建和管理,但是需要通过依赖注入的方式注入到类A中。
Spring实现控制反转的是IoC容器,实现方法是依赖注入。
Spring IoC 容器
Spring IoC 容器可以容纳我们开发的各种Bean,并且我们可以从中获取各种发布在Spring IoC 容器里的Bean,并且通过描述可以得到它。
Spring IoC 容器的设计
Spring IoC 容器的设计主要是基于BeanFactory和ApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,ApplicationContext是高级接口之一。下图是Spring IoC 容器接口的设计:
Spring IoC 容器的初始化和依赖注入
Bean的定义和初始化在Spring IoC容器中是两大步骤:
- 先定义
- 然后初始化和依赖注入
Bean的定义分3步:
1. Resource定位,这步是Spring IoC 容器根据开发者的配置进行资源定位。
2. BeanDefinition的载入,将Resource定位到的信息保存到Bean定义中,此时并不会创建Bean的实例
3. BeanDefinition的注册,将BeanDefinition的信息发布到Spring IoC容器中,注意此时仍然没有创建Bean实例
上面三部后,Bean在Spring IoC 容器中被定义,但是没有被初始化,更没有完成依赖注入。
Spring Bean 还有一个配置:lazy-init,默认值为:false,Spring IoC 默认会自动初始化Bean。如果将其设置为true,只有当我们使用Spring IoC容器的getBean方法获取它,它才会进行Bean的初始化,完成依赖注入。
Spring Bean 的生命周期
Spring IoC 容器的本质目的就是为了管理Bean。在容器中Bean的初始化以及销毁有一个过程,存在一个生命周期。
下图是Bean的生命周期:
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
- Bean自身的方法 : 这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法
- Bean级生命周期接口方法 : 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
- 容器级生命周期接口方法 : 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
- 工厂后处理器接口方法 : 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
其中BeanPostProcessor接口则是针对所有Bean而言的。
示例
BeanPostProcessorImpl类,实现了BeanPostProcessor,是针对所有Bean而言的。
package com.ssm.chapter9.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class BeanPostProcessorImpl implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[" + bean.getClass().getSimpleName() + "] 对象" + beanName + "开始实例化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[" + bean.getClass().getSimpleName() + "] 对象" + beanName + "完成实例化");
return bean;
}
}
DisposableBeanImpl类
package com.ssm.chapter9.bean;
import org.springframework.beans.factory.DisposableBean;
public class DisposableBeanImpl implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("调用接口DisposableBean的destroy方法。");
}
}
Blender类
package com.ssm.chapter9.pojo;
public class Blender {
/**
* 搅拌
*
* @param water
* 水描述
* @param fruit
* 水果描述
* @param sugar
* 糖描述
* @return 果汁
*/
public String mix(String water, String fruit, String sugar) {
String juice = "这是一杯由液体:" + water + "\n水果:" + fruit + "\n糖量:" + sugar + "\n组成的果汁";
return juice;
}
}
JuiceMaker类
package com.ssm.chapter9.pojo;
public class JuiceMaker {
private Blender blender = null;// 搅拌机
private String water;// 水描述
private String fruit;// 水果
private String sugar;// 糖分描述
public Blender getBlender() {
return blender;
}
public void setBlender(Blender blender) {
this.blender = blender;
}
public String getWater() {
return water;
}
public void setWater(String water) {
this.water = water;
}
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public String getSugar() {
return sugar;
}
public void setSugar(String sugar) {
this.sugar = sugar;
}
/**
* 果汁生成
*/
public String makeJuice() {
blender = new Blender();
return blender.mix(water, fruit, sugar);
}
}
JuiceMaker2 类
package com.ssm.chapter9.pojo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class JuiceMaker2 implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean{
private String beverageShop = null;
private Source source = null;
public String getBeverageShop() {
return beverageShop;
}
public void setBeverageShop(String beverageShop) {
this.beverageShop = beverageShop;
}
public Source getSource() {
return source;
}
public void setSource(Source source) {
this.source = source;
}
public String makeJuice() {
String juice = "这是一杯由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();
return juice;
}
public void init() {
System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义初始化方法");
}
public void destroy() {
System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义销毁方法");
}
@Override
public void setBeanName(String s) {
System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanNameAware接口的setBeanName方法");
}
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanFactoryAware接口的setBeanFactory方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(
"【" + this.getClass().getSimpleName() + "】调用ApplicationContextAware接口的setApplicationContext方法");
}
}
Source 类
package com.ssm.chapter9.pojo;
public class Source {
private String fruit;// 类型
private String sugar;// 糖分描述
private String size;// 大小杯
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public String getSugar() {
return sugar;
}
public void setSugar(String sugar) {
this.sugar = sugar;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
配置文件 spring-cfg.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-4.0.xsd">
<!--BeanPostProcessor定义 -->
<bean id="beanPostProcessor" class="com.ssm.chapter9.bean.BeanPostProcessorImpl" />
<!--DisposableBean定义 -->
<bean id="disposableBean" class="com.ssm.chapter9.bean.DisposableBeanImpl" />
<bean id="source" class="com.ssm.chapter9.pojo.Source">
<property name="fruit" value="橙汁" />
<property name="sugar" value="少糖" />
<property name="size" value="大杯" />
</bean>
<bean id="juiceMaker2" class="com.ssm.chapter9.pojo.JuiceMaker2"
destroy-method="destroy" init-method="init">
<property name="beverageShop" value="贡茶" />
<property name="source" ref="source" />
</bean>
</beans>
测试主函数,Chapter9Main 类
package com.ssm.chapter9.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ssm.chapter9.pojo.JuiceMaker;
import com.ssm.chapter9.pojo.JuiceMaker2;
public class Chapter9Main {
public static void main(String[] args) {
testIoC();
}
public static void testCommon() {
JuiceMaker juiceMaker = new JuiceMaker();
juiceMaker.setWater("矿泉水");
juiceMaker.setFruit("橙子");
juiceMaker.setSugar("少糖");
System.out.println(juiceMaker.makeJuice());
}
public static void testIoC() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cfg.xml");
JuiceMaker2 juiceMaker2 = (JuiceMaker2) ctx.getBean("juiceMaker2");
System.out.println(juiceMaker2.makeJuice());
ctx.close();
}
}
运行结果:
1. [DisposableBeanImpl] 对象disposableBean开始实例化
2. [DisposableBeanImpl] 对象disposableBean完成实例化
3. [Source] 对象source开始实例化
4. [Source] 对象source完成实例化
5.【JuiceMaker2】调用BeanNameAware接口的setBeanName方法
6.【JuiceMaker2】调用BeanFactoryAware接口的setBeanFactory方法
7.【JuiceMaker2】调用ApplicationContextAware接口的setApplicationContext方法
8. [JuiceMaker2] 对象juiceMaker2开始实例化
9.【JuiceMaker2】调用InitializingBean接口的afterPropertiesSet方法
10.【JuiceMaker2】执行自定义初始化方法
11. [JuiceMaker2] 对象juiceMaker2完成实例化
这是一杯由贡茶饮品店,提供的大杯少糖橙汁
12.【JuiceMaker2】执行自定义销毁方法
13. 调用接口DisposableBean的destroy方法。
说明
- BeanPostProcessor针对所有Bean的,所以不管哪个Bean实例化的时候都会调用实现的两个接口,所以后面所有包含开始实例化和完成实例化的打印都是Bean实例化的时候调用下面两个接口:
- postProcessBeforeInitialization
- postProcessAfterInitialization
- 上面前4个打印是对应xml中BeanPostProcessor以及DisposableBean两个对象的实例化的打印
- 第5行是对应BeanNameAware的setBeanName接口
- 第6行是对应BeanFactoryAware的setBeanFactory接口
- 第7行是对应ApplicationContext的setApplicationContext方法,并且Spring IoC 容器必须是一个ApplicationContext接口的实现类,因为ClassPathXmlApplicationContext是ApplicationContext的实现类
- 第9行时InitializingBean的afterPropertiesSet方法
- 第10行执行自己定义的init方法,这个在xml配置
- 第12行对象通过getBean方法得到,病调用相关方法打印的结果
- 第13行时执行自定义的destroy方法,在xml中配置
- 最后一行是DisposableBean的destroy方法。