Spring Bean的生命周期指的是从一个普通的Java类变成Bean的过程:
以注解类变成Spring Bean为例,Spring会扫描指定包下面的Java类,然后将其变成beanDefinition对象,然后Spring会根据beanDefinition来创建bean。特别要记住一点,Spring是根据beanDefinition来创建Spring bean的,关于beanDefinition下文会进行分析。
上图就是beanDefinition所包含的内容,看到这些属性如果对Spring有所了解都应该知道几个,如lazyInit懒加载,在Spring中有一个@Lazy注解,用来标识其这个bean是否为懒加载的,scope属性,相应的也有@scope注解来标识这个bean其作用域,是单例还是多例,beanClass属性,在对象实例化时,会根据beanClass来创建对象、又比如autowireMode注入模型这个属性,这个属性用于记录使用怎样的注入模型,注入模型常用的有根据名称和根据类型、不注入三种注入模型。
autowireMode虽然看似我们没有使用到过,但是知道这个对于查看Spring和其他框架整合的时候很有帮助,如果我们在beanDefinition指定其根据类型进行属性注入,那么在创建这个bean时,会将其beanClass中的所有属性都拿到,然后排出掉基本属性(如类型String、Double、Boolean、Object),然后对于剩下的进行属性注入,记住一点,在beanDefinition指定其根据类型进行属性注入,即使不在属性上面使用@Autowired注解也会对其进行属性注入。在我们写注解类的时候为什么不使用@Autowired时,其属性就注入不进来呢?那是因为注解类在变成beanDefinition时,其注入类型是不注入,所以此时只有使用@Autowired注解进行标记的属性,才会完成依赖注入。
Spring会根据beanDefinition来完成bean的创建,为什么不直接使用对象的class对象来创建bean呢?因为在class对象仅仅能描述一个对象的创建,它不足以用来描述一个Spring bean,而对于是否为懒加载、是否是首要的、初始化方法是哪个、销毁方法是哪个,这个Spring中特有的属性在class对象中并没有,所有Spring就定义了beanDefinition来完成bean的创建。
java类 -> beanDefinition对象
Java类是在哪一步变成beanDefinition的,我们先来看一下Spring中AbstractApplicationContext类中的refresh方法:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
step1:prepareRefresh 上下文刷新前准备工作:设置ConfigurableWebApplicationContext上下文实例对象wac的启动日期和活动标志、加载属性源配置以及判断必填项是否都完整。
step2:obtainFreshBeanFactory 通知子类刷新内部bean工厂工作:创建BeanFactory,如果已有就销毁,没有就创建;核心工作就是解析XML 以及扫描注解,将扫描到的Bean配置属性封装到BeanDefinition 对象中,并对它beanName(key) , BeanDefinition(v) 保存到一个Map 中。
step3:prepareBeanFactory 对bean factory进行一些上下文标准化配置:设置factory的类加载器、bean 表达式解释器、资源编辑注册器、应用上下文自动注入后处理器、配置在自动装配(通过beans标签default-autowire属性来依赖注入)的时候的需要忽略的类(如ApplicationContextAwareProcessor、EnvironmentAware、ResourceLoaderAware、 EmbeddedValueResolverAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware)、注册可以自动装配的 Bean(如BeanFactory)以及注册默认系统变量配置等。
step4:postProcessBeanFactory 修改BeanFactory的后处理器配置:在标准初始化之后修改应用程序上下文的内部bean工厂初始化配置,允许注册特殊BeanPostProcessors->即ServletContextAwareProcessor 后处理器以及设置自动装配忽略接口类(ServletContextAware、ServletConfigAware)以及注册应用上下文的request/session 范围。 这一阶段所有bean定义都已加载,但没有bean将被实例化。
step5:invokeBeanFactoryPostProcessors 工作:通过显示顺序方式调用手动注册的BeanFactory后处理器,先实例化spring框架涉及到的后处理器,在调用。
(1)先执行 BeanDefinitionRegistryPostProcessor 的方法
(2)对配置/组件类中声明的嵌套@component类或configuration类者进行自动注册成bean定义,并对这些候选bean定义按照优先级进行排序。
(3)执行beanFactoryPostProcessors,对配置文件bean进行扫描实例化:如propertyConfigurer。
step6:registerBeanPostProcessors 注册拦截bean创建的bean处理器-实例化:
(1):通过beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);方法获取beanFactory里继承了BeanPostProcessor接口的name的集合;
(2):把后置器beans分为PriorityOrdered、Ordered、nonOrdered三大类,前两类是增加了排序条件的后置器;
(3):前两类后置器执行sortPostProcessors和registerBeanPostProcessors方法,也就是先执行排序方法,后执行注册方法。
(4):最后一步用到了上面提到的BeanPostProcessor和BeanFactoryPostProcessor的入参不同的AbstractApplicationContext,在addBeanPostProcessor方法里把BeanPostProcessor注册进了AbstractBeanFactory,这也就是为什么BeanFactoryPostProcessor执行了后置接口实现类,而BeanPostProcessor仅仅执行了注册和实例化,而没有执行的原因。
step7:initMessageSource 初始化消息源:MessageSource接口类用于支持信息的国际化和包含参数的信息的替换。
ApplicationContext接口继承了MessageSource接口,应用可通过ApplicationContext来调用MessageSource接口方法以实现信息的国际化和替换信息中包含的参数。所有对MessageSource接口的实现都是在AbstractApplicationContext中实现。
step8: initApplicationEventMulticaster 初始化事件广播器:如果上下文中没有定义则使用默认广播器:SimpleApplicationEventMulticaster。
step9: onRefresh 初始化其他特定的bean,由具体子类实现。
step10:registerListeners 注册监听事件:在容器中将所有项目里面的ApplicationListener注册进来,大体过程如下:获取所有的事件,并添加到事件派发器中 -> 监听事件进行派发广播。
step11:finishBeanFactoryInitialization 初始化所有剩下的单实例 Bean(没有配置赖加载的 lazy!=true)。大体过程如下:
-> 获取bean的定义信息
-> 判断bean 是否是抽象的、是单例的、非懒加载的
-> 是否为 FactoryBean ,是则调用 FactoryBean 的创建方法,否则执行 getBean() 方法
-> 调用 getBean() 方法
-> getBean方法内部再调用 doGetBean() 方法
step12:finishRefresh 完成BeanFactory的初始化创建工作:
// 初始化生命周期处理器组件
initLifecycleProcessor();
// 首先将刷新状态传播到生命周期组件中.
getLifecycleProcessor().onRefresh();
// 发布上下文已刷新完毕的事件.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active:
LiveBeansView活动beans的查看适配器,构建当前bean的快照 和来自本地{@code ApplicationContext}的依赖关系(带有本地{@code LiveBeansView} bean定义)或所有已注册的ApplicationContexts由{@value #MBEAN_DOMAIN_PROPERTY_NAME}环境属性驱动)
LiveBeansView.registerApplicationContext(this);
doGetBean方法处理过程
1)获取bean所对应clazz的构造函数
(2)构造函数先执行静态字段的初始化,然后按照属性字段声明顺序执行初始化
(3)调用各个MergedBeanDefinitionPostProcessor后处理器的postProcessMergedBeanDefinition
进行信息合并处理。
(4)在容器中为bean 添加一个单指定的单例工厂
(5)调用各个InstantiationAwareBeanPostProcessor后处理器的postProcessAfterInstantiation
(6)调用autowireByName方法处理通过autowire设置为byName的属性字段: xml 中bean的autowire指定
(7)调用autowireByType方法处理通过autowire设置为byType的属性字段 :xml 中bean的autowire指定
(8)若有实例化感知后处理器InstantiationAwareBeanPostProcessor,则调用postProcessPropertyValues
进行处理:更新beanFactory的设置
(9)若有bean属性值依赖检查,则进行检查:依赖性检查属性可以是协作对象bean,简单类型或全部
(10)调用applyPropertyValues方法对MutablePropertyValues可变属性-复杂对象进行设值,涉及到属性值
依赖注入,主要是xml中的bean配置, 例如PropertyPlaceholderConfigurer::propertyConfigurer配置,
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="properties" ref="propertiesFactoryBean"/>
</bean>
<bean id="propertiesFactoryBean"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath*:production.properties</value>
</list>
</property>
</bean>
在这一阶段会解析property配置文件。
(11)调用bean初始化之前的后处理器的postProcessBeforeInitialization方法对初始化(@postContruct、@preDestroy标注方法)方法进行处理调用
(12)调用初始化方法afterPropertiesSet():bean是实现了InitializingBean
(13)调用bean初始化之后的后处理器,一般是没有操作,直接返回。