赞
踩
Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点。
Bean的实例化阶段
Bean的设置属性阶段
Bean的 初始化阶段
Bean的销毁阶段
阶段1:Bean元信息配置阶段
阶段2:Bean元信息解析阶段
阶段3:将Bean注册到容器中
阶段4:BeanDefinition合并阶段
阶段5:Bean Class加载阶段
阶段6:Bean实例化阶段(2个小阶段)
1.Bean实例化前阶段
2.Bean实例化阶段
阶段7:合并后的BeanDefinition处理
阶段8:属性赋值阶段(3个小阶段)
1.Bean实例化后阶段
2.Bean属性赋值前阶段
3.Bean属性赋值阶段
阶段9:Bean初始化阶段(5个小阶段)
1.Bean Aware接口回调阶段
2.Bean初始化前阶段
3.Bean初始化阶段
4.Bean初始化后阶段
5.Bean初始化完成
阶段10:所有单例bean初始化完成后阶段
阶段11:Bean的使用阶段
阶段12:Bean销毁前阶段
阶段13:Bean销毁阶段
这个阶段主要是bean信息的定义阶段
Bean信息定义4种方式
不管是是通过xml配置文件的标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。
你可以把BeanDefinition丢给Bean工厂或者其子类,然后Bean工厂就会根据这个信息帮你生产一个Bean实例
一般用的是beanFactory的子类applicationcontext, applicationcontext比一般的beanFactory要多很多功能,比如aop、事件等。
通过t加载配置文件,或者利用注解的方式扫描将bean的配置信息加载到spring容器里面。
BeanDefinition接口:bean定义信息接口
AttributeAccessor接口:属性访问接口
BeanMetadataElement接口:返回BeanDefinition定义的来源
RootBeanDefinition类:表示根bean定义信息
ChildBeanDefinition类:表示子bean定义信息
GenericBeanDefinition类:通用的bean定义信息
ConfigurationClassBeanDefinition类:表示通过配置类中@Bean方法定义bean信息
AnnotatedBeanDefinition接口:表示通过注解的方式定义的bean信息
BeanDefinitionBuilder:构建BeanDefinition的工具类,可以非常方便的组装BeanDefinition对象
Spring帮助我们管理Bean分为两个部分,一个是注册Bean,一个装配Bean。
完成这两个动作有三种方式,一种是使用自动配置的方式、一种是使用JavaConfig的方式,一种就是使用XML配置的方式。
@Compent 作用就相当于 XML配置
@Component
public class Student {
private String name = "lkm";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Bean 需要在配置类中使用,即类上需要加上@Configuration注解
@Configuration
public class WebSocketConfig {
@Bean
public Student student(){
return new Student();
}
}
两者都可以通过@Autowired装配
@Autowired Student student;
那为什么有了@Compent,还需要@Bean呢?
如果你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component注解的,因此就不能使用自动化装配的方案了,但是我们可以使用@Bean,当然也可以使用XML配置。
Bean元信息的解析主要有3种方式
bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry
别名注册接口:AliasRegistry
BeanDefinitionRegistry接口继承了AliasRegistry接口,这个接口中定义了操作bean别名的一些方法。
BeanDefinitionRegistry唯一实现:DefaultListableBeanFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory
例如 AnnotationConfigApplicationContext 类就实现了 BeanDefinitionRegistry接口
Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。
getBean这个方法的源码
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition
bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition.
合并之前是GenericBeanDefinition类型的,合并之后得到的是RootBeanDefinition类型的。
后面的阶段将使用合并产生的RootBeanDefinition
这个阶段就是将bean的class名称转换为Class类型的对象。
此时会对阶段4中合并产生的RootBeanDefinition中的beanClass进行解析,将bean的类名转换为Class对象,然后赋值给RootBeanDefinition#setBeanClassName字段
上面得到了Bean Class对象以及合并之后的BeanDefinition,下面就开始进入实例化这个对象的阶段了。
Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段;
Bean实例化前操作
看一下 DefaultListableBeanFactory
在 父类 AbstractBeanFactory 中
private final List beanPostProcessors = new CopyOnWriteArrayList<>();
是一个BeanPostProcessor类型的集合
spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的
Bean实例化之前会调用一段代码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
上面代码中轮询beanPostProcessors列表,如果类型是InstantiationAwareBeanPostProcessor, 尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了.
这个地方给开发者提供了一个扩展点,允许开发者在这个方法中直接返回bean的一个实例
Bean实例化操作
这个过程可以干什么?
这个过程会通过反射来调用bean的构造器来创建bean的实例。
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
这个方法会返回候选的构造器列表,也可以返回空.
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName) throws BeansException { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; }
具体需要使用哪个构造器,spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
重要的实现类 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
可以将@Autowired标注的方法作为候选构造器返回
到目前为止bean实例化阶段结束了
这块的源码如下
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
会调用MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法
第一个参数为beanDefinition,表示合并之后的RootBeanDefinition,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理
实现类
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存
(1)调用 InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法,判断控制程序是否继续进行属性填充
(2)根据注入类型(byType/byName),提取依赖的,统一存入 PropertyValues 中
(3)判断是否需要进行 BeanPostProcessor 和 依赖检查:
如果有后置处理器,将会应用 InstantiationAwareBeanPostProcessor 处理器的postProcessProperties 方法,对属性获取完毕填充前,对属性进行再次处理。 使用 checkDependencies方法来进行依赖检查
(4)将所有解析到的 PropertyValues 中的属性填充至 BeanWrapper 中
实例化后阶段
会调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation这个方法,调用逻辑如下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
postProcessAfterInstantiation方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过
Bean属性赋值前阶段
这个阶段会调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法,调用逻辑
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } }
如果InstantiationAwareBeanPostProcessor中的postProcessPropertyValues返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段
PropertyValues 保存了bean实例对象中所有属性值的设置,所以我们可以在postProcessPropertyValues 这个方法中对PropertyValues值进行修改。
这个方法有2个比较重要的实现类
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues在这个方法中对@Autowired、@Value标注的字段、方法注入值。
CommonAnnotationBeanPostProcessor#postProcessPropertyValues在这个方法中对@Resource标注的字段和方法注入值。
Bean属性赋值阶段
这个过程比较简单了,循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。
PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。
这个阶段分为5个小的阶段
Bean Aware接口回调
Bean初始化前操作
Bean初始化操作
Bean初始化后操作
Bean初始化完成操作
Bean Aware接口回调
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用,
BeanNameAware:将bean的名称注入进去
BeanClassLoaderAware:将BeanClassLoader注入进去
BeanFactoryAware:将BeanFactory注入进去
Bean初始化前操作
这个阶段的源码
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
会调用BeanPostProcessor的postProcessBeforeInitialization方法,若返回null,当前方法将结束。
通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。
这个接口有2个实现类,比较重要:
org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
ApplicationContextAwareProcessor注入6个Aware接口对象
如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。
EnvironmentAware:注入Environment对象 EmbeddedValueResolverAware:注入EmbeddedValueResolver对象 ResourceLoaderAware:注入ResourceLoader对象 ApplicationEventPublisherAware:注入ApplicationEventPublisher对象 MessageSourceAware:注入MessageSource对象 ApplicationContextAware:注入ApplicationContext对象
CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法
CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization中会调用bean中所有标注@PostConstruct注解的方法
ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { if (initAnnotationType != null) { if (method.getAnnotation(initAnnotationType) != null) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (debug) { logger.debug("Found init method on class [" + clazz.getName() + "]: " + method); } } } if (destroyAnnotationType != null) { if (method.getAnnotation(destroyAnnotationType) != null) { currDestroyMethods.add(new LifecycleElement(method)); if (debug) { logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method); } } } } })
调用@PostConstruct标注的方法
Bean初始化阶段
2个步骤
调用InitializingBean接口的afterPropertiesSet方法
调用定义bean的时候指定的初始化方法。
见:com.dn.spring.beandefinition.BeanDefinition5Test#test7
Bean初始化后阶段
这块的源码:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
调用BeanPostProcessor接口的postProcessAfterInitialization方法,返回null的时候,会中断上面的操作。
通常称 postProcessAfterInitialization 这个方法为:bean初始化后置操作。
所有单例bean实例化完成之后,spring会回调下面这个接口:
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
调用逻辑在下面这个方法中
//确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。 //如果需要,通常在工厂设置结束时调用。 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton的bean,调用他们的afterSingletonsInstantiated方法。
调用getBean方法得到了bean之后
触发bean销毁的几种方式
调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
调用ApplicationContext中的close方法
Bean销毁阶段会依次执行
轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法
如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
调用bean自定义的销毁方法
DestructionAwareBeanPostProcessor接口
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
* bean销毁前调用的方法
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* 用来判断bean是否需要触发postProcessBeforeDestruction方法
*/
default boolean requiresDestruction(Object bean) {
return true;
}
}
配置元信息(bean定义配置)-BeanDefinationReader(解析)-BeanDefinationRegistry(注册);
配置元信息(bean定义配置):API的方式,Xml文件方式,注解的方式,properties文件
BeanDefinationRegistry:;键值对方式,通过特定的Bean定义的id,映射到相应的BeanDefination
BeanFactoryPostProcessor:是容器启动阶段Spring提供的一个扩展点,主要对注册的BeanDefination进行一定程度上的修改与替换。
例如类名、scope、属性、构造函数参数列表、依赖的bean、是否是单例类、是否是懒加载等,
容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination了,这就是Spring为Bean实例化所做的预热的工作。
spring bean实例化之后,就开始注入属性,
首先注入自定义的属性,比如标注@autowrite的这些属性,
再调用各种Aware接口扩展方法,注入属性(spring特有的属性),
比如BeanNameAware.setBeanName,设置Bean的ID或者Name;
a.实例化Bean
容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。
对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。
实例化对象被包装在BeanWrapper对象中(可以认为是Bean的原生态),BeanWrapper提供了设置对象属性的接口,避免了使用反射机制设置属性。
这里提到了4个组件:BeanFacotry\ApplicationContext\BeanDefinition\BeanWrapper
b.设置对象属性(依赖注入)
实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。
紧接着,Spring根据BeanDefinition中的信息进行依赖注入。
并且通过BeanWrapper提供的设置属性的接口完成依赖注入。
c.注入Aware接口(给bean增加某种能力,申明是某种特殊的bean)
Aware接口用于增强Bean能力容器需检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。
常见的Aware接口有:BeanNameAware\BeanFactoryAware\ApplicationContextAware至此,一个对象已经被正确构造。
d.1.BeanPostProcessor(自定义处理,满足用户需求)
经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。 该接口提供了两个函数:
postProcessBeforeInitialzation( Object bean, String beanName )
当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。所有Aware接口的注入就是在这一步完成的。
postProcessAfterInitialzation( Object bean, String beanName )
当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。
组件:BeanPostProcessor
d.2.InitializingBean与init-method
当BeanPostProcessor的前置处理完成后就会进入本阶段。 InitializingBean接口只有一个函数:afterPropertiesSet()这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。
若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。
当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。
e.DisposableBean和destroy-method
和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。
在设置属性阶段后,postProcessBeforeInitialization方法执行前,会执行很多Aware类型的接口,这种类型接口作用是加载资源到Spring容器中,Aware前面的名字就对应哪种资源,依次加载的是:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
EnvironmentAware
ResourceLoaderAware
ApplicationEventPublisherAware
ApplicationContextAware
看到这里应该明白BeanFactory和ApplicationContext的区别了:
BeanFactoryAware之前加载的资源都是公共的。BeanFactoryAware后面加载的资源都是ApplicationContext独有的。
BeanFactoryPostProcessor接口:
在循环初始化springbean之前,对BeanDefinition元数据做扩展处理
InstantiationAwareBeanPostProcessor接口: 在对象实例化前后扩展,作用于所有bean
BeanPostProcessor接口: 在对象初始化化前后扩展,作用于所有bean(2)、Bean扩展点(作用于单个bean):
Aware接口: springBean实例化并且注入自定义属性之后 InitializingBean接口:
springBean初始化时,执行构造方法结束,并且属性赋初始化值结束之后执行 DiposableBean接口:
springBean销毁之前执行。(3)、Bean自身的方法
包括了Bean本身调用的方法
通过配置文件中的init-method和destroy-method指定的方法(或者用注解的方式)
(4)、包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor,
CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。
工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。