Bean的生命周期

生命周期

首先Bean是通过ConfigurationClassPostProcessor解析配置类的后置处理器,将Bean从类中注册到BeanFactory中,然后通过getBean方法加载Bean

首先调用getSingleton方法从三级缓存中获取,若获取不到,再通过函数式接口调用createBean创建Bean的流程。通过resolveBeforeInstantiation方法去第一次调用Bean的后置处理器,这里调用的是实现了InstantiationAwareBeanPostProcessor接口postProcessBeforeInstantiation方法的后置处理器,这里主要调用AbstractAutoProxyCreatorAOP切面类进行解析,并将解析后的数据缓存,即通过@EnableAspectJAutoProxy开启了AOP代理,且该类为AdvicePointcutAdvisorAopInfrastructureBean等接口的子类,或该类上有@Aspect注解且不是一个被AspectJ编译过的类;在这里还可以自定义一个后置处理器返回一个对象来阻断后续流程的执行。

接着调用doCreateBean真正去创建Bean,首先回去创建Bean的简单实例,在创建实例的过程中可能会第二次调用Bean的后置处理器,这里调用的是实现了SmartInstantiationAwareBeanPostProcessor接口determineCandidateConstructors方法的后置处理器,这里主要调用AutowiredAnnotationBeanPostProcessor指定实例化的的构造函数,通过@Bean注入的对象会跳过该后置处理器

简单实例化完成后,调用applyMergedBeanDefinitionPostProcessors从而第三次调用Bean的后置处理器,完成@Autowired、@Value、@Inject、@PostConstruct、@Resource等注解以及自定义的初始化方法等预解析。调用AutowiredAnnotationBeanPostProcessor@Autowired@Value@Inject注入信息预解析存入externallyManagedConfigMembers中,调用CommonAnnotationBeanPostProcessor解析@Resource注解,且会调用父类InitDestroyAnnotationBeanPostProcessor,解析@PostConstruct@PreDestroy@Bean(initMethod = "initMethod")是在扫描BeanDefinition时解析时就已完成且在invokeInitMethods方法最后的invokeCustomInitMethod方法中被调用,且执行的先后顺序为@PostConstruct、InitializingBean的afterPropertiesSet、@Bean(initMethod = "initMethod")

然后将早期对象通过函数式接口getEarlyBeanReference存入第三级缓存singletonFactories中,这里主要是为了解决循环依赖,若不存在循环依赖,该函数接口不会被调用,故三级缓存不会被升级为二级缓存。在该函数式接口中第四次调用了Bean的后置处理器,调用实现了SmartInstantiationAwareBeanPostProcessor接口的getEarlyBeanReference方法的后置处理器,这里是调用AbstractAutoProxyCreator后置处理器,主要作用是给有AOP代理的且产生循环依赖先被加载的对象创建AOP代理,若该Bean有AOP代理,但不存在循环依赖存在循环依赖但后被加载,则AOP代理是在第八次调用后置处理器时,给该Bean创建动态代理的。若在该处已经设置了动态代理会将beanName加入到earlyProxyReferences集合中,防止第八次调用后置处理器时重复添加动态代理

紧接着调用populateBean方法为Bean的属性进行赋值,在属性设置前第五次调用实现了InstantiationAwareBeanPostProcessor接口postProcessAfterInstantiation的后置处理器,其作用是让用户可以自定义属性,其还可以设置跳过后续的赋值操作

紧接着调用第六次后置处理器,调用实现了InstantiationAwareBeanPostProcessor接口postProcessProperties的后置处理器,主要是注入PropertyValues对属性进行赋值操作,@Autowired、@Value注解是通过AutowiredAnnotationBeanPostProcessorpostProcessProperties方法调用InjectionMetadata.inject方法,若发现@Autowired注入的Bean未被创建,最终会调用DependencyDescriptorresolveCandidate方法,通过getBean去创建该Bean。若存在循环依赖,给依赖的Bean进行属性赋值时会再次通过getBean调用当前Bean,从而通过getSingleton方法中对三级缓存中函数式接口的调用,即调用getEarlyBeanReference方法将三级缓存转换为二级缓存,返回给依赖的Bean进行赋值操作。

完成了属性的赋值,接下来就是通过initializeBean对Bean的初始化方法的调用,初始化调用前首先通过invokeAwareMethods方法对BeanNameAwareBeanClassLoaderAwareBeanFactoryAware三个Aware接口的调用。

第七次Bean的后置处理器调用,通过InitDestroyAnnotationBeanPostProcessor接口中调用LifecycleMetadata.invokeInitMethods方法来实现初始化前@PostConstruct注解的方法的调用,以及调用ApplicationContextAwareProcessor后置处理器的postProcessBeforeInitialization方法,完成EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAwareImportAware等Aware接口的调用。

接着调用invokeInitMethods方法,若Bean实现了InitializingBean接口,则调用InitializingBean接口的afterPropertiesSet方法,以及自定义的初始化方法的调用即@Bean(initMethod = "initMethod")中指定的初始化方法

applyBeanPostProcessorsAfterInitialization方法中完成了第八次后置处理器的调用,通过调用实现了BeanPostProcessor接口postProcessAfterInitialization方法的后置处理器,调用AbstractAutoProxyCreatorAbstractAdvisingBeanPostProcessorAdvisorAdapterRegistrationManager等后置处理器的调用来对初始化完成后的Bean进行AOP代理的创建,调用ApplicationListenerDetector调用来对ApplicationListener的添加。

最终Bean销毁时会调用第九次Bean的后置处理器,即调用InitDestroyAnnotationBeanPostProcessor后置处理器的postProcessBeforeDestruction方法。

Bean的后置处理器调用时机

循环依赖

所谓的循环依赖是指,A依赖B,B又依赖A,它们之间形成了循环依赖。或者A依赖B,B依赖C,C又依赖A:

循环依赖

Spring中Bean创建过程中,需要对Bean的属性进行赋值,当发现其属性B是一个Bean时,会先通过getBean(B)去获取依赖的Bean,若B未被穿件会先创建,最终将生成好的依赖的Bean赋值给当前属性。若在通过getBean(B)创建依赖Bean时,给依赖的Bean的属性A赋值时,发现其属性是前一个Bean,这是又通过getBean(A)去获取Bean,但这时A并没有创建完成,这时就会产生死循环。Spring中是通过三级缓存来解决单例Bean的循环依赖问题的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// 一级缓存,也是单例缓存池 用于保存所有的单实例bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存,缓存的key为beanName,value为早期对象,即还没进行属性赋值的对象
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存,缓存key为beanName,value为函数式接口ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 已注册的单例名称set
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
// 该集合用户缓存当前正在创建bean的名称
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 排除当前创建检查的
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
}

一级缓存singletonObjects保存所有生成完全的单实例Bean,二级缓存earlySingletonObjects保存还没进行属性赋值的Bean的早期对象,三级缓存singletonFactories中保存是封装了早期对象的函数式接口

1
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}

当Bean实例化完成即早期对象生成完成后,会将早期对象通过函数式接口getEarlyBeanReference存入第三级缓存singletonFactories中,主要就是为了解决循环依赖,若不存在循环依赖,该函数接口不会被调用,故三级缓存不会被升级为二级缓存。若存在循环引用就会在getBean(A)时调用getSingleton方法,从而将三级缓存中的函数式接口getEarlyBeanReference执行,给有AOP代理的且产生循环依赖的对象创建AOP代理,并将代理后的对象放入二级缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

B的属性赋值中就能通过getBean(A)拿到A了,然后B就能完成赋值从而完成Bean的生成,最终A的属性赋值getBean(B)就能获取到B从而A完成属性赋值。

从源码来看其实二级缓存完全可以解决循环依赖的问题,若不使用第三级缓存,那getEarlyBeanReference方法要么在Bean实例化后就立即调用,要么将getEarlyBeanReference放入getSingleton中调用,前者会导致不论是否有循环依赖的Bean创建都会被调用,从而导致大量重复的调用,后者导致getSingleton方法职责不单一,故用到第三级缓存可能主要是为了解耦方法职责单一提高阅读性便于维护

循环依赖Bean创建过程

对于循环依赖中先被加载的类A才会用到二级缓存earlySingletonObjects后被加载的类B其实跟普通Bean加载过程一样,不会调用三级缓存中的函数式接口getEarlyBeanReference。若A存在AOP代理,则B中赋值的A是经过AOP代理过后的对象,但给A属性赋值的时候依旧是赋值给未被代理的A,但是A和代理对象的中的A是同一个,故代理对象中的A属性被赋值了。若不存在AOP代理,这里的beanearlySingletonReferenceexposedObject其实是同一个对象,若存在AOP代理earlySingletonReferencebeanexposedObject不是同一个对象

1
2
3
4
5
6
7
8
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false); // 若存在AOP代理,则返回被代理后的对象
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference; // 将代理后的对象返回
}
}
}

只有单实例Bean才会放入三级缓存,对于原型模式创建的对象不会放入三级缓存中,而Spring又是通过三级缓存来解决循环依赖的,故原型Bean的循环依赖无法利用缓存,则无法解决循环依赖的问题

对于构造方法注入的Bean的循环依赖问题,源码中可以很明看到Bean是先通过构造方法实例化后,才会将其放入三级缓存中,故构造方法注入Bean无法利用三级缓存,故也无法解决循环依赖问题。