
在之前的篇幅中已经介绍过SpringIOC的一些细节,包括IOC的启动流程以及对应的源码解析过程。今天就SpringBean生命周期的事情好好的在聊一聊。
开始之前,给大家截了一个图,是BeanFactory接口中的一段注释:
其实从上面这段注释已经表达的很清楚了,大佬们已经把bean生命周期的流程已经列出来了。所以从这里我们就能够引申出另外一副构图:
在IOC详解的篇幅已经介绍了IOC的启动流程,如果还没有对整体流程没有概念的可以先去看看那篇,这里我们就直接进入整体。
下面我们就上图所示进行代码跟踪:
AbstractAutowireCapableBeanFactory.doCreateBean方法:
2.设置属性值:
上述同类同方法:
在这里的populateBean方法主要是填充属性值的,如果是引用类型,可能会存在循环依赖问题,这个问题我会单独抽取出来作为一个篇幅来讲。
3.执行Aware方法。
我们先来了解下什么是Aware接口,他们都做了什么事情? spring中提供了很多的XXXAware接口,例如BeanNameAware、BeanFactoryAware、ApplicationContextAware等,这些接口可以让你IOC启动的过程中做一些事情,比如在实现BeanNameAware接口时,你可以获取beanName来做一些事情:
在bean生命周期中的Aware接口的执行是在2图中的initializeBean方法,进入到该方法中:
从上图中可以看出这里执行了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三个Aware接口。
4.beanPostProcessor接口的before方法。
在spring中,有一个BeanPostProcessor接口,对应的还有一个BeanFactoryPostProcessor,他们分别是bean后置处理器、bean工厂后置处理器,也叫增强器,就是对bean或者beanFactory的增强处理。这里的bean后置处理器BeanPostProcessor接口有两个方法
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
那么bean何时调用的beanPostProcessor的呢?
在3图中有一个initializeBean方法,我们把它拿出来看一下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
进入applyBeanPostProcessorsBeforeInitialization方法:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public List getBeanPostProcessors() {
return this.beanPostProcessors;
}
这里调用了getBeanPostProcessors()方法拿到了所有的beanPostProcessor然后循环调用执行。而且从getBeanPostProcessors方法内可以看出是直接返回了一个beanPostProcessors变量(它是个List集合),也就是说再此之前就已经add到list集合了,那么什么时候add到集合中的呢,在详解IOC的流程的篇幅中,在refresh()方法中已经详细的介绍了BeanPostProcessor的注册流程,这里就不过多赘述了,所这里自然而然的就从集合中拿出遍历执行了。
在上述初始化方法中在执行bean的后置处理器的before方法之后的invokeInitMethod()方法:
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这里获取bea后置处理器的方法getBeanPostProcessors原理同上述分析的before方法的时候是一样的。
上述过程就是整个bean生命周期的过程,其实也是按照首图去一步步跟踪的,只不过细节需要自己去手动过一遍,这样会多springbean生命周期有一个更好的理解。
到这里可能有些小伙伴会对首图中的一开始的好多Aware接口有一些疑问,图中介绍了好多的Aware接口,为什么在上述介绍中就只有三种Aware接口,其他接口的执行在哪?
其实它们是通过beanPostProcessor实现调用了其他的一些Aware接口,这个beanPostProcessor是ApplicationContextAwareProcessor
它会在bean初始化之前调用,也就是before方法:
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}