1.spring bean的生命周期
1.1简介
有很多关于SPRING BEAN生命周期介绍的文章,有个比较通用的总结。那就是
实例化 -> 属性赋值 -> 初始化 -> 销毁
我觉得按照这个来理解要方便很多,下面将结合代码来理解这个流程。
下面是类图,结合类图来理解
我用了AnnotationConfigApplicationContext(估计现在用这个的比较多,本人没细看过springboot的代码,但理论上用的应该也是注解方式)。
入口其实就是AbstractApplicationContext的refresh方法,里面内容很多,不一一赘述,核心直接到{BANNED}{BANNED}{BANNED}最佳佳佳终的bean生产的地方AbstractAutowireCapableBeanFacotry.doCreateBean,代码如下
-
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
throws BeanCreationException {
-
-
// Instantiate the bean.
-
BeanWrapper instanceWrapper = null;
-
if (mbd.isSingleton()) {
-
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
-
}
-
if (instanceWrapper == null) {
-
instanceWrapper = createBeanInstance(beanName, mbd, args); //bean的实例化
-
}
-
Object bean = instanceWrapper.getWrappedInstance();
-
Class<?> beanType = instanceWrapper.getWrappedClass();
-
if (beanType != NullBean.class) {
-
mbd.resolvedTargetType = beanType;
-
}
-
-
// Allow post-processors to modify the merged bean definition.
-
synchronized (mbd.postProcessingLock) {
-
if (!mbd.postProcessed) {
-
try {
-
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
-
}
-
catch (Throwable ex) {
-
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
-
"Post-processing of merged bean definition failed", ex);
-
}
-
mbd.postProcessed = true;
-
}
-
}
-
-
// Eagerly cache singletons to be able to resolve circular references
-
// even when triggered by lifecycle interfaces like BeanFactoryAware.
-
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
-
isSingletonCurrentlyInCreation(beanName));
-
if (earlySingletonExposure) {
-
if (logger.isTraceEnabled()) {
-
logger.trace("Eagerly caching bean '" + beanName +
-
"' to allow for resolving potential circular references");
-
}
-
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
-
}
-
-
// Initialize the bean instance.
-
Object exposedObject = bean;
-
try {
-
populateBean(beanName, mbd, instanceWrapper); //bean的属性赋值
-
exposedObject = initializeBean(beanName, exposedObject, mbd); //bean的初始化
-
}
-
catch (Throwable ex) {
-
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
-
throw (BeanCreationException) ex;
-
}
-
else {
-
throw new BeanCreationException(
-
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
-
}
-
}
-
-
if (earlySingletonExposure) {
-
Object earlySingletonReference = getSingleton(beanName, false);
-
if (earlySingletonReference != null) {
-
if (exposedObject == bean) {
-
exposedObject = earlySingletonReference;
-
}
-
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
-
String[] dependentBeans = getDependentBeans(beanName);
-
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
-
for (String dependentBean : dependentBeans) {
-
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
-
actualDependentBeans.add(dependentBean);
-
}
-
}
-
if (!actualDependentBeans.isEmpty()) {
-
throw new BeanCurrentlyInCreationException(beanName,
-
"Bean with name '" + beanName + "' has been injected into other beans [" +
-
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
-
"] in its raw version as part of a circular reference, but has eventually been " +
-
"wrapped. This means that said other beans do not use the final version of the " +
-
"bean. This is often the result of over-eager type matching - consider using " +
-
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
-
}
-
}
-
}
-
}
-
-
// Register bean as disposable.
-
try {
-
registerDisposableBeanIfNecessary(beanName, bean, mbd);
-
}
-
catch (BeanDefinitionValidationException ex) {
-
throw new BeanCreationException(
-
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
-
}
-
-
return exposedObject;
-
}
1.2 实例化
没什么特别的貌似,回头再看看,只是找到合适的构造函数来进行实例化。
1.3 属性赋值
构造器注入
setter注入
autowire方式
1.4 初始化
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)这个代码很多,就不贴出来了,这里面大概做了几个重要的事情
1.执行aware接口,如果你实现了的话。
2.执行了BeanPostProcessor,这是一个容器级别的扩展,也就是你如果实现了这个接口,你会发现所有的bean初始化都会执行此接口。以下是我写的一个样例,那么下面2个方法有什么区别么。一个是init-method之前被调用,一个是在init-method后被调用。 这里聊下PostContruct这个标签,其实用的就是CommonAnnotationBeanPostProcessor这个来实现的
3.执行了init-method,这个就不多谈了。
由此我们引入了一个重要的东西,spring bean的扩展点。详细见后面
2.SPRING BEAN生命周期扩展点
2.1简介
大部分在前面bean生命周期都已经介绍了,主要集中在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
2.1bean自身方法
比如setter/getter等,你可以用settler来注入,不过这个是发生在属性注入的时候。
比如init-method或者destory等。
2.2容器级接口BeanPostProcessor接口
容器级也就是你实现了这个接口,所有的bean在生命周期时候都会调用到此接口的实现
2.3Bean级生命周期方法
BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean等,这个就是每个bean自己独立去实现。
3.三级缓存
-
singletonObjects, 一级缓存:存放已经完整生成好的bean,也就是初始化做完的bean.在获取bean时候优先从一级缓存中去找。
-
earlySingletonObjects, 二级缓存:存放已经实例化的bean,但还没有初始化
-
singletonFactories 三级缓存:存储singleFactory,其实是bean工厂,此时其实bean工厂里面的bean已经被实例化了
关于存在的意义(或者设计成这样的目的)。
一级缓存:{BANNED}{BANNED}最佳佳好理解,完整BEAN总要有个地方放吧。
二级缓存和三级缓存:都是为了解决循环依赖的,想想bean生命周期 实例化 -> 属性赋值 -> 初始化。 循环依赖是发生在属性赋值的时候,那要解决这个问题,那就必需在实例化完之后,就能让其它的bean可以找到他,也就是要找一个地方放不完整的bean,此时就再需要一个缓存了,这就是三级缓存的作用。那为什么还有一个二级缓存呢?和AOP有关,一开始实例化创建好了一个不完整的bean放在三级缓存中了。后来这个不完整的bean 就被别人给用了。这个时候又发生了AOP,后面这个被人给应用的bean其实就废了。所以AOP需要提前,这个时候就要找个地方放这个已经被增强过的BEAN。