IOC容器启动及Bean生成流程
目录
没有很详细了解Bean的可能只知道Bean会经历实例化,初始化,属性赋值这些所谓的Bean生命周期,再往下细聊可能就不清楚了,这次呢我们就全面的了解一下IOC容器的启动流程,然后重点看一下其中有关Bean的流程!
一、容器启动
上节我们说过了,容器启动入口就是ApplicationContext,有两个重要的实现类:
- AnnotationConfigApplicationContext: 基于注解包路径扫描的容器上下文,通过注解扫描来完成BeanDefinition的注册
- ClassPathXmlApplicationContext: 基于类路径下xml文件的Spring应用程序上下文,通过解析类路径下的xml来完成BeanDefinition的注册
这里我们就通过现在流行的注解方式来看,像下面这样一行代码就能启动一个容器了
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("com.example.spkie");
我们是扫描了一个包,直接看看这个构造方法
源代码如下:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(String... basePackages) {
// 调用上面的 初始化了两个类
this();
// 扫描包下要加载的Bean
this.scan(basePackages);
// 启动流程
this.refresh();
}
上面初始化的两个类我们上一节也提过了
- AnnotatedBeanDefinitionReader: 读取注解生成BeanDefinition并注册
- ClassPathBeanDefinitionScanner: 扫描类路径生成BeanDefinition并注册
这里是扫描的包,所以无疑是会执行ClassPathBeanDefinitionScanner.doScan方法,我们下面再说
IOC启动流程
先看一下启动的流程refresh():
synchronized(this.startupShutdownMonitor) {
// 工厂刷新前的前置准备
this.prepareRefresh();
// 获取BeanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 对BeanFactory做一些设置
this.prepareBeanFactory(beanFactory);
try {
// 空的,给子类拓展使用
this.postProcessBeanFactory(beanFactory);
// 实例化并调用BeanFactory后置处理器(BeanFactory、BeanDefination的后置处理)
this.invokeBeanFactoryPostProcessors(beanFactory);
// 实例化并注册所有Bean的后置处理器(将BeanPostProcessor添加到工厂)
this.registerBeanPostProcessors(beanFactory);
// 初始化国际化工具MessageSource
this.initMessageSource();
// 初始化事件广播器
this.initApplicationEventMulticaster();
// 空的,容器刷新的时候调用(给子类拓展)
this.onRefresh();
// 注册监听器
this.registerListeners();
// 实例化所有剩余的非懒加载的单例Bean,BeanPostProcessor也会在这过程执行
this.finishBeanFactoryInitialization(beanFactory);
// 收尾工作
this.finishRefresh();
} catch (BeansException var10) {
// 省略.....
} finally {
// 省略.....
}
}
重点
我们重点关注和Bean相关的内容,我们下面一个个看(注册代表放入工厂):
- 扫描并注册BeanDefination
- BeanFactory后置处理(invokeBeanFactoryPostProcessors)
- 实例化并注册Bean后置处理器(registerBeanPostProcessors)
- 遍历BeanDefination,实例化单例Bean(finishBeanFactoryInitialization)
refresh()流程如下:
二、扫描并注册BeanDefination
我们上面说了,我们采用的方式是包扫描,所以最终调用的是ClassPathBeanDefinitionScanner.doScan 方法,在这个方法中我们重点关注两个:
一个是加载并过滤资源** findCandidateComponents()**
一个是注册放入工厂registerBeanDefinition()
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
String[] var3 = basePackages;
int var4 = basePackages.length;
for(int var5 = 0; var5 < var4; ++var5) {
String basePackage = var3[var5];
// 扫描类并过滤 (只找我们需要注入的Bean)
Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
Iterator var8 = candidates.iterator();
while(var8.hasNext()) {
BeanDefinition candidate = (BeanDefinition)var8.next();
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
}
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册放入工厂
this.registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
加载并过滤资源
为什么要过滤资源?因为加载并不是直接加载被注解标识的类,而是加载了所有的类,然后再判断具体需要把哪些变成BeanDefination,所以需要过滤一次
ClassPathScanningCandidateComponentProvider.scanCandidateComponents:
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
LinkedHashSet candidates = new LinkedHashSet();
try {
String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 获取所有的资源
Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = this.logger.isTraceEnabled();
boolean debugEnabled = this.logger.isDebugEnabled();
Resource[] var7 = resources;
int var8 = resources.length;
for(int var9 = 0; var9 < var8; ++var9) {
Resource resource = var7[var9];
if (resource.isReadable()) {
try {
MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
// 过滤资源
if (this.isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
candidates.add(sbd);
} else if (debugEnabled) {
this.logger.debug("Ignored because not a concrete top-level class: " + resource);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not matching any filter: " + resource);
}
} catch (Throwable var13) {
throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);
}
} else if (traceEnabled) {
this.logger.trace("Ignored because not readable: " + resource);
}
}
return candidates;
} catch (IOException var14) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
}
}
this.isCandidateComponent:
该方法中就会根据过滤器,对这些资源过滤,最终获取的资源就是我们要加载的Bean(内置了一个AnnotationTypeFilter过滤器就是对 @Component注解过滤)
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
Iterator var2 = this.excludeFilters.iterator();
TypeFilter tf;
do {
if (!var2.hasNext()) {
var2 = this.includeFilters.iterator();
do {
if (!var2.hasNext()) {
return false;
}
tf = (TypeFilter)var2.next();
} while(!tf.match(metadataReader, this.getMetadataReaderFactory()));
return this.isConditionMatch(metadataReader);
}
tf = (TypeFilter)var2.next();
} while(!tf.match(metadataReader, this.getMetadataReaderFactory()));
return false;
}
注册BeanDefination
要加载的Bean对象会被解析封装成BeanDefination,里面就是Bean对象相关的所有信息,最终调用的就是工厂中的注册BeanDefination方法,信息会保存在工厂内的集合里面
DefaultListableBeanFactory.registerBeanDefinition():
三、BeanFactory后置处理
这个在上一节也说过了,对BeanDefination和BeanFactory的后置处理,其实就是对下面这三类接口做一个处理,将实现了这三类接口的实现类找出来排序,挨个执行里面的方法,总得来说就是对BeanDefination和BeanFactory做一个后置的处理
- BeanDefinitionRegistry
- BeanFactoryPostProcessor
- BeanDefinitionRegistryPostProcessor
最终会执行下面这个方法,这个方法还挺长,我就只截图部分了,重点是掌握以上这些接口,知道这些接口可以对BeanDefination和BeanFactory做一个后置的处理就可以了
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors:
四、注册Bean后置处理器
BeanDefination和BeanFactory都有后置处理器,Bean当然也有,但是这里只是把Bean的后置处理器给全找出来放到BeanFactory中去,在后面Bean实例化、初始化、属性赋值的时候才执行生效,这个后置处理器上一节也说过了就是BeanPostProcessor接口
PostProcessorRegistrationDelegate.registerBeanPostProcessors:
先找到全部的然后处理、排序,然后注册放入工厂
五、遍历BeanDefination,实例化单例Bean
这一步就是最感兴趣的Bean的生命周期了,前面的准备工作都做完了,BeanDefination和BeanPostProcessor都放入工厂了,还是老规矩只看重点,其他的一律跳过,主流程都不理解看其他的只会懵逼,我们先看一张关于Bean生成的图:
入口就是我们下面这个方法,也就是IOC容器启动最关键一步了,从图上看真正的逻辑体现在doGetBean处,我将整个过程最关键的位置分成三步,也就是实例化、属性赋值、初始化,中间插入后置处理器的一些方法处理,这中间关于三级缓存的地方我会提一下,但是不会深入介绍,之后再说
preInstantiateSingletons
DefaultListableBeanFactory.preInstantiateSingletons
这个方法需要记住几个点:
第一点:普通的Bean和实现了FactoryBean接口的Bean 生成流程是不同的
第二点:Bean都生成完成后,会判断Bean是否实现了SmartInitializingSingleton接口,实现了的Bean还会执行该接口的afterSingletonsInstantiated方法
第三点:FactoryBean和单例Bean都会执行getBean方法,getBean又会调用doGetBean方法
doGetBean(我们只关注单例)
- 首先会先判断Bean是否已经生成了
- 没生成就走getSingleton方法(对于单例而已)
- getSingleton执行的时候就会调用那个lambda表达式,也就是会执行createBean方法
- 生成的Bean对象都要判断一次是不是FactoryBean,是的话还要特殊处理一次
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
// 根据Bean名称获取Bean对象
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
// 判断Bean是否已经生成了
if (sharedInstance != null && args == null) {
// 省略部分.....
// 获取到的Bean对象 还需要判断是否是FactoryBean 是的话还要对其进行处理
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
// 统统省略........一大段
try {
// 统统省略........一大段
// 我们这里只看单例,像多例、session等类型的都不看了
if (mbd.isSingleton()) {
// 单例走这里 这里注意这个getSingleton 方法传参的时候 内置了一lambda表达式
// getSingleton内部会先执行createBean方法得到返回后 继续执行
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
// 获取到的Bean对象 还需要判断是否是FactoryBean 是的话还要对其进行处理
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 统统省略........一大段
} catch (BeansException var32) {
beanCreation.tag("exception", var32.getClass().toString());
beanCreation.tag("message", String.valueOf(var32.getMessage()));
this.cleanupAfterBeanCreationFailure(beanName);
throw var32;
} finally {
beanCreation.end();
}
}
return this.adaptBeanInstance(name, beanInstance, requiredType);
}
createBean
AbstractAutowireCapableBeanFactory.createBean
这里很简单,上一节说过了有些拓展的Bean后置处理器会在Bean实例化前执行,这里所以在一步里面手动实例化了就不需要再往下走流程了直接返回,正常的Bean都会往下走
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 省略............
Object beanInstance;
try {
// 这里就是会判断是否有处理器需要在Bean实例化前执行
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
// 如果存在某些Bean在Bean实例化前处理了,就走不到这了
// 这里就是正常的Bean实例化、属性赋值、初始化
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
实例化前执行
resolveBeforeInstantiation
这一步了解一下就好霍,毕竟少用,实例化前执行的接口上一节说过了就是InstantiationAwareBeanPostProcessor继承了BeanPostProcessor
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
// 执行后Bean不为空 说明已经实例化了
if (bean != null) {
// 所以这里会再执行BeanPostProcessor.postProcessAfterInitialization
// Bean初始化后执行的方法
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
doCreateBean
总得来说就分成了三步,实例化、属性赋值、初始化(Bean的生命周期就在这了),过程里面包含一个三级缓存的重点
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 实例化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
// 省略一大段.................
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
// 记住这个添加的lambda表达式 三级缓存重点
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// Bean的属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
// 初始化前执行、初始化、初始化后执行 BeanPostProcessor表演时刻
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
// 省略一大段.............................
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
实例化
createBeanInstance
这里就是利用反射实例化,然后将实例化对象包装成了BeanWrapper
属性赋值
populateBean
这里就是对Bean里面的属性值进行注入赋值,同时实例化后执行的方法在里面也会执行
注入需要去容器中找对应的Bean,这里有两个查找方法根据Bean name 和根据Bean type
之后后置处理器的拓展点又会生效执行,InstantiationAwareBeanPostProcessor 内的两个属性赋值的方法,不多说
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
} else {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();
while(var4.hasNext()) {
// 实例后执行
// 这里会判断实例化后执行的那个返回值true 或者 false
// false代表该实例 不需要属性注入
InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
// 属性注入 根据Bean name去容器中找然后注入
if (resolvedAutowireMode == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}
// 属性注入 根据Bean Type去容器中找然后注入
if (resolvedAutowireMode == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyValues pvsToUse;
for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
// 这里InstantiationAwareBeanPostProcessor 中给属性赋值的两个方法也会执行
// 上一节说过了 不多说了
InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
}
if (pvs != null) {
this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
初始化
- 先会执行一个拓展点BeanFactoryAware
- 然后初始化前执行(BeanPostProcessors.postProcessBeforeInitialization)
- 初始化(利用反射执行init()方法、InitializingBean拓展点)
- 然后初始化后执行 (BeanPostProcessors.postProcessAfterInitialization)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
// 这里也是一个拓展点 就是BeanFactoryAware这个接口
// 可以获取容器中的工厂对象,我们常用的Spring工具类就可以利用这个来搞
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// bean初始化前执行
// 就是BeanPostProcessors里面的postProcessBeforeInitialization方法
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
// 利用反射执行初始化方法 init()
// 这里也有一个拓展点就是InitializingBean接口
// Bean如果实现了该接口,这里还会执行接口里afterPropertiesSet方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
// bean初始化后执行
// 就是BeanPostProcessors里面的postProcessAfterInitialization方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
getSingleton
DefaultSingletonBeanRegistry.getSingleton
正常会先执行这个,只不过这里面内部会执行那个lambda表达式,还是要去执行createBean方法,所以前面就先介绍createBean方法了,这里最终就是会把Bean加入到一级缓存,同时删除掉其他缓存
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 省略一段....................
try {
// 这里就是会去执行那个表达式,也就是createBean的方法
// 我们前面已经介绍了哈
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
// 省略一段.....................
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
// 到这Bean已经生成了
if (newSingleton) {
// 所以要把bean加入到一级缓存中去,同时把二、三级缓存删除掉
// 这个在三级缓存的时候再说
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
到这Bean的流程就结束啦
六、总结
整体上看Bean流程为:BeanDefination→实例化→属性赋值→初始化
后置处理器可以对上述流程各阶段前后做出相应的修改和调整
再细数一下过程中的拓展接口:
BeanDefinitionRegistryPostProcessor:对BeanDefination后置处理
BeanFactoryPostProcessor:对BeanFactory后置处理
BeanPostProcessor:初始化前后处理
InstantiationAwareBeanPostProcessor:实例化前后、属性赋值、初始化前后
InitializingBean:初始化执行
BeanFactoryAware:获取容器中的工厂
ApplicationContextAware:获取容器上下文
SmartInitializingSingleton:Bean全生成完了后执行
源码很多,但是我们挑自己感兴趣的那部分重点来看,就能形成一个结构化思维,最后再看一下图