大家好,我是Leo!最近很久没有更新文章了,今天特地来和大家分享一下从源码层面来理解Spring的生命周期,其中也会涉及到三级缓存的问题,希望可以给大家带来一点帮助。
之前也发过一篇关于bean生命周期的文章
说明
我的源码环境是拉取Spring5.3.x版本的代码,源码依赖管理采用的是Gradle,下面我将带大家一点点去跟源码,从而加深对Spring生命周期的理解。
Spring Bean 的生命周期
在开始前,先带大家找到Spring代码的核心入口,org.springframework.context.support.AbstractApplicationContext#refresh,即在refresh方法中,可以看到Spring加载的整个过程,其中在这个过程中,会涉及到很多函数的调用,下面是这个函数里面调用的函数全部列举。
-
prepareRefresh()该方法主要是记录IOC容器启动时间,加载一些环境变量和系统属性。
-
obtainFreshBeanFactory()方法主要是创建beanFactory,其中还解析并加载BeanDefinition并放在DefaultListableBeanFactory#beanDefinitionMap中。
-
prepareBeanFactory(beanFactory)是向beanFactory添加一些重要的处理器,比如ApplicationContextAwareProcessor等。
-
postProcessBeanFactory(beanFactory)主要是在beanFactory初始化后,但是bean还未实例化前提供的扩展点。
-
invokeBeanFactoryPostProcessors(beanFactory)主要是提供BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor扩展点
-
registerBeanPostProcessors(beanFactory)注册注册所有BeanPostProcessor的后置处理器
-
initMessageSource()提供国际化消息支持
-
initApplicationEventMulticaster()主要是初始化事件广播器以及注册监听器
-
registerListeners()注册事件监听器
-
finishBeanFactoryInitialization这个方法是重点,里面会涉及到我们常见bean生命周期中的很多扩展点。
obtainFreshBeanFactory加载BeanDefinition详解
首先我们先来看代码,跟进去后会发现会先创建beanFactory,然后再调用loadBeanDefinitions方法。
@Override
protected final void refreshBeanFactory() throws BeansException {
// ....
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
// ....
// 加载的核心代码
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
然后里面会创建一个XmlBeanDefinitionReader,然后把刚刚DefaultListableBeanFactory 设置成里面中的一个成员变量,方便后续register BeanDefinition到DefaultListableBeanFactory#beanDefinitionMap,然后在XmlBeanDefinitionReader#doLoadBeanDefinitions中,然后继续跟到doRegisterBeanDefinitions方法,
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
// .......
preProcessXml(root);
// 主要在这里加载进入到beanFactory中的
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
然后就可以在下面这个方法中找到文件的NameSpace,然后就可以查看它的加载逻辑了。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean 就是在这里加载的
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
这个BeanDefinitionHolder其实就是beanName、BeanDefinition和aliases的合体,主要是用来装解析结果的,最后通过registerBeanDefinition添加到beanDefinitionMap和beanDefinitionNames中。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 将最终解析出来的bean注册到BeanFactory中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
finishBeanFactoryInitialization(beanFactory)重点解析
跟进去后,核心逻辑在preInstantiateSingletons这个方法中,我们先看到了FactoryBean扩展点,如果是的话,就通过加一个&前缀获取Bean,跟进getBean方法,再到我们常见的doGetBean方法,我们跟进到getSingleton方法,这里可以看到我们常说的三级缓存,就是singletonObjects、earlySingletonObjects和singletonFactories,这里我先带大家看一下这个结构(不要只顾背八股文)
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
可以看到一级和二级缓存都采用了ConcurrentHashMap,而三级缓存采用了HashMap,下面我们继续来看getSingleton代码,也是可以看到它是怎么解决循环依赖问题的。
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 从二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 采用双重校验机制
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 从三级缓存中获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 然后再放入二级缓存,然后将该对象从三级缓存中移除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
我们只看单例情况下的代码,创建实例部分,点进createBean
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been pu
// eagerly by the creation process, to allow for circular reference resol
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
找到resolveBeforeInstantiation方法,跟进去,然后就可以看到InstantiationAwareBeanPostProcessor,实例化前和实例化的扩展点
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 调用后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
跟进applyBeanPostProcessorsBeforeInstation方法,就可以看到实例化前置处理器的回调
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 调用InstantiationAwareBeanPostProcessor中的回调方法
Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
return null;
}
然后继续跟进doCreateBean方法,然后在createBeanInstance看到创建Bean实例的过程,然后跟进到下面这个方法在populateBean中进行属性的填充,并调用postProcessAfterInstantiation方法。
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
然后在initializeBean方法中进行初始化的逻辑,在下面可以看到它们的执行顺序是BeanNameAware、BeanClassLoaderAware和BeanFactoryAware三种Aware。
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
在调用BeanPostProcessors的初始前置处理器,postProcessBeforeInitialization方法
@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;
}
然后再调用invokeInitMethods方法,这个方法是InitializingBean这个扩展点的方法,然后再调用自定义的init-method方法
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
然后再调用BeanPostProcessors的后置处理器方法postProcessAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
销毁时,我们也可以通过实现DisposableBean来编写销毁方法,当我们容器关闭时,调用的是doClose方法,然后跟进去最后在这个方法中DefaultSingletonBeanRegistry#destroyBean调用了destroy方法。
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
然后再调用自定义的关闭方式invokeCustomDestroyMethod。
生命周期图
从上面看来,我们可以看到Bean的生命周期全部过程,其实就可以简要概括为加载,实例化,初始化,销毁四个大的过程,其中又提供了多个扩展点,我对之前的图又进行了完善,可以看到下面的这幅图。
今天的分享就到这里了,通过跟着源码确实对生命周期这一过程有了更加深刻的认识和理解,可能我写的也没有那么好,希望各位大佬多指正。