前言:
此文是从spring框架的源码进行剖析Bean加载的一个过程,请耐心一步一步阅读
目前来说,我们一般开发都是基于SpringBoot进行,所以我们就从SpringBoot项目启动类开始解析
启动入口:
先从加载bean对象的角度来看一下springboot程序启动类
@SpringBootApplication
public class YosmfaApplication {
public static void main(String[] args) {
SpringApplication.run(YosmfaApplication.class, args);
}
}
@SpringBootApplication注解加载其他starter的解读请参考springboot如何实现自动装配
这里详细的解析下springboot程序加载本地项目中的Bean信息到Ioc容器的过程 1、进入SpringApplication.run方法 找到this.refreshContext(),它会调用spring框架下org.springframework.context.support.AbstractApplicationContext#refresh()方法,该refresh()方法就是spring框架用来加载本地项目中所有的bean信息的。主要的Bean对象的加载过程都是在这个方法逻辑里调用的
这里要说一个点,通常我们一般说Bean加载,Bean加载。实际在Spring框架里,只是一个刷新容器的概念,只不过刷新容器的时候把你配置的Bean信息加载到容器当中,所以在Spring源码里是一个refresh()方法
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
上面的解析中,有两个核心逻辑点需要关注
加载BeanDefinitions
BeanFactory初始化后会扫描项目中所有的Bean配置信息加载成BeanDefinition对象
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
从this.obtainFreshBeanFactory()方法一直跟下来,发现加载Bean信息的实现有下面几种。 SpringBoot是采用AnnotationConfigWebApplicationContext的实现,也就是扫描注解的方式加载Bean信息。而现在常用的一般也都是注解方式。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
AnnotatedBeanDefinitionReader reader = this.getAnnotatedBeanDefinitionReader(beanFactory);
ClassPathBeanDefinitionScanner scanner = this.getClassPathBeanDefinitionScanner(beanFactory);
BeanNameGenerator beanNameGenerator = this.getBeanNameGenerator();
if (beanNameGenerator != null) {
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);
}
ScopeMetadataResolver scopeMetadataResolver = this.getScopeMetadataResolver();
if (scopeMetadataResolver != null) {
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
if (!this.componentClasses.isEmpty()) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Registering component classes: [" + StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
}
reader.register(ClassUtils.toClassArray(this.componentClasses));
}
if (!this.basePackages.isEmpty()) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(StringUtils.toStringArray(this.basePackages));
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
String[] var7 = configLocations;
int var8 = configLocations.length;
for(int var9 = 0; var9 < var8; ++var9) {
String configLocation = var7[var9];
try {
Class<?> clazz = ClassUtils.forName(configLocation, this.getClassLoader());
if (this.logger.isTraceEnabled()) {
this.logger.trace("Registering [" + configLocation + "]");
}
reader.register(new Class[]{clazz});
} catch (ClassNotFoundException var13) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Could not load class for config location [" + configLocation + "] - trying package scan. " + var13);
}
int count = scanner.scan(new String[]{configLocation});
if (count == 0 && this.logger.isDebugEnabled()) {
this.logger.debug("No component classes found for specified class/package [" + configLocation + "]");
}
}
}
}
}
具体的解析逻辑可以自己debug看,大概就是加载项目下所有的注解配置Bean信息。
创建Bean实例
此方法会根据上面加载的Bean信息创建Bean实例,填充字段属性,处理一些Bean的后置处理逻辑postProcess
this.finishBeanFactoryInitialization(beanFactory);
跟进去后,核心方法调用如下:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver((strVal) -> {
return this.getEnvironment().resolvePlaceholders(strVal);
});
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
String[] var3 = weaverAwareNames;
int var4 = weaverAwareNames.length;
for(int var5 = 0; var5 < var4; ++var5) {
String weaverAwareName = var3[var5];
this.getBean(weaverAwareName);
}
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
}
进入beanFactory.preInstantiateSingletons()方法,此方法是抽象方法,由DefaultListableBeanFactory类实现。 下面开始分析preInstantiateSingletons创建Bean实例的逻辑,此方法核心调用就是一个 getBean() 方法
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
while(true) {
String beanName;
Object bean;
do {
while(true) {
RootBeanDefinition bd;
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
while(var2.hasNext()) {
beanName = (String)var2.next();
Object singletonInstance = this.getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, this.getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
return;
}
beanName = (String)var2.next();
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract());
} while(!bd.isSingleton());
} while(bd.isLazyInit());
if (this.isFactoryBean(beanName)) {
bean = this.getBean("&" + beanName);
break;
}
this.getBean(beanName);
}
} while(!(bean instanceof FactoryBean));
FactoryBean<?> factory = (FactoryBean)bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
SmartFactoryBean var10000 = (SmartFactoryBean)factory;
((SmartFactoryBean)factory).getClass();
isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
}
}
继续跟进 getBean() 方法,进入到org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean()方法 调用该方法会去ioc容器中获取bean实例,如果没有则会创建Bean实例(前提是BeanFactory中有BeanDefinition信息)
Object sharedInstance = this.getSingleton(beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
如ioc容器中获取不到Bean对象,则会调用this.createBean() 方法创建 继续跟进createBean() 方法,它的核心调用是this.doCreateBean 真正创建bean实例以及属性赋值的逻辑都在这个方法里,进入doCreateBean方法查看
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);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
this.populateBean(beanName, mbd, instanceWrapper);
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);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.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.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
上面需重点关注的逻辑点有三个地方 1、创建bean实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
2、属性填充-赋值
this.populateBean(beanName, mbd, instanceWrapper);
3、一些aware扩展的处理
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
处理完方法后会返回创建的bean实例
结束
到这,整个spring加载bean对象的一个过程就完成了。 总结来讲,先是:org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory() 方法初始化BeanFactory并拿到本地项目中所有配置的BeanDefinitions信息,而后org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons() 方法根据遍历BeanDefinitions信息创建相应的Bean实例,实际的bean创建逻辑则是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean() 方法当中
纸上得来终觉浅,大家可以自己debug跟进一下整个bean的加载过程。
|