2 IoC 容器与 Bean

Wu Jun 2020-01-13 15:33:57
06 Spring > 01 Core

1 容器

容器(container)是 Spring 框架的核心,它管理着 Spring 应用中 bean 的创建、 配置和管理,负责对象的整个生命周期。

1.1 容器实现

Spring 自带两种不同类型容器实现,主要使用 ApplicationContext

1)BeanFactory

最简单的容器,提供基本的 DI 支持。使用控制反转将应用的配置和依赖与实际的应用代码分离开来。

第一次访问某一 Bean 时才实例化它。

2)ApplicationContext

基于 BeanFactory 构建, 并提供应用框架级别的服务。

初始化容器时就实例化所有单例的 Bean。

有多种 ApplicationContext 的实现, 每一种都提供了配置 Spring 的不同方式。

3)Bean Factory 和 ApplicationContext 的区别

ApplicationContext 提供了一种解决文档信息的方法,一种加载文件资源的方式(如图片),他们可以向监听他们的beans发送消息。

另外,容器或者容器中 beans 的操作,这些必须以 Bean Factory 的编程方式处理的操作可以在 ApplicationContext 中以声明的方式处理。

ApplicationContext 实现了 MessageSource,该接口用于获取本地消息,实际的实现是可选的。

1.2 getBean()

通过容器 getBean() 方法从容器获取指定 bean。

@Autowired
ApplicationContext applicationContext;

healthAPI =applicationContext.getBean(AdminServiceAPI.HealthAPI.class);

2 Spring Bean

2.1 Spring Bean 定义

在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 Bean。这些对象由 Spring IOC 容器实例化、组装、管理。

Spring Bean 中定义了所有的配置元数据,这些配置信息告知容器如何创建它,它的生命周期是什么以及它的依赖关系。

2.2 定义 bean 的作用域

在 Spring 中创建一个 bean 的时候,我们可以通过“scope”属性声明它的作用域。

Spring 中的 bean 默认都是单例(singleton)的,这对可变类型是非线程安全的。

Spring 定义了几种 bean 的作用域:

3 Bean 的生命周期

对于普通的 Java 对象,当 new 的时候创建对象,当它没有任何引用的时候被垃圾回收机制回收。而由 Spring IoC 容器托管的对象,它们的生命周期完全由容器控制。

Spring 只管理单例模式 Bean 的完整生命周期,对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期。

bean的生命周期

BeanFactory 负责 bean 创建的最初四步,然后移交给 ApplicationContext 做后续创建过程

3.1 实例化

Spring 容器(从 XML 文件、注解、Java 配置文件)读取 bean 的定义并实例化 bean。

容器通过获取 BeanDefinition 对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。

实例化对象被包装在 BeanWrapper 对象中,BeanWrapper 提供了设置对象属性的接口,从而避免了使用反射机制设置属性。

3.2 属性填充(依赖注入)

实例化后的对象被封装在 BeanWrapper 对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。

紧接着,Spring 根据 BeanDefinition 中的信息进行依赖注入。

并且通过 BeanWrapper 提供的设置属性的接口完成依赖注入。

3.3 注入 Aware 接口

紧接着,Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入给 bean。

xxxAware 接口可以用于在初始化 bean 时获得 Spring 中的一些对象,如获取 Spring 上下文等。

3.4 BeanPostProcessor

当经过上述几个步骤后,bean 对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过 BeanPostProcessor 接口实现。

该接口提供了两个函数:

3.5 自定义初始化

当 BeanPostProcessor 的“前置处理”完成后就会进入本阶段。

1)InitializingBean 接口

InitializingBean 接口只有一个函数:afterPropertiesSet()

这一阶段也可以在 bean 正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前 bean 对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。

若要使用它,我们需要让 bean 实现该接口,并把要增加的逻辑写在该函数中。

Spring 会在前置处理完成后检测当前 bean 是否实现了 InitializingBean 接口,并执行 afterPropertiesSet 函数。

2)init-method 属性

Spring 为了降低对客户代码的侵入性,给 bean 的配置提供了 init-method 属性,该属性指定了在这一阶段需要执行的函数名。

Spring 便会在初始化阶段执行我们设置的函数。init-method 本质上仍然使用了 InitializingBean 接口。

3)@PostConstruct 注解

对象构建之后调用

3.6 自定义销毁

当 BeanPostProcessor 的“后置处理”完成后就会进入本阶段。

1)DisposableBean 接口

如果该 bean 实现了 DisposableBean,调用 destroy() 方法。

2)destroy-method 属性

和 init-method 一样,通过给 destroy-method 指定函数,就可以在 bean 销毁前执行指定的逻辑。

3)@PreDestroy 注解

对象移除之前调用