加载和实例化bean分以下几个重要步骤:

1、根据package扫描出需要被管理的类
2、将这些类封装成BeanDefinition并注册到BeanFactory容器
3、实例化所有扫描到的BeanDefinition,其中包括解决循环依赖、延迟加载问题

下面这张图根据Springboot启动调用链的顺序,画了这三个关键步骤被触发的时间点:

1、根据package扫描出需要被管理的类

springboot是通过启动类上的@ComponentScan注解所指定的包路径来进行扫描的,如果没有标注这个注解,则默认从启动类所在的包路径开始扫描,会根据类的注解来判断是否需要被容器进行管理,具体代码在ConfigurationClassParser的parse方法里,从上图能看到这个方法的调用栈是SpringApplication#run()->refreshContext(context)->invokeBeanFactoryPostProcessors(beanFactory);->ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)->ConfigurationClassParser#parse,debug图如下:

下面看parse方法的代码:

public void parse(Set<BeanDefinitionHolder> configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();try {if (bd instanceof AnnotatedBeanDefinition) {// parse方法里的逻辑看后面的解析,核心步骤1.1到1.8逻辑parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());}else {parse(bd.getBeanClassName(), holder.getBeanName());}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);}}// 核心步骤 1.9this.deferredImportSelectorHandler.process();}

parse方法会调到下面这个方法:

核心步骤如下:

  • 1.1:如果该类被@Component标注(即使被@Component标注的注解标注也算,比如@Configuration注解被@Component标注了,如果该类被@Configuration标注,那么也就被@Component标注),那么先处理这个类里定义的一些内部类,对这些内部类递归调用processConfigurationClass(ConfigurationClass configClass)方法,先解析内部类,再解析外层类

  • 1.2:判断是否有被@PropertySource标注,如果有这个注解,则将该注解的property配置文件里的key和value解析到Context的Environment对象里供后续使用

  • 1.3:判断是否被@ComponentScans标注(这个注解就是告知Spring容器遍历那些包路径来加载bean),根据配置的包路径来扫描所有的类,对需要被Spring容器管理的类(被@Component注解的类)会递归调用下面这个方法,直到这类上的@ComponentScans注解里指定的包路径下的所有类都被扫描并解析到Spring容器里(这里如果没有配置包路径,默认为该类所在的包路径),这个扫描是由ClassPathBeanDefinitionScanner类的doScan方法来实现的。debug图如下:

  • 1.4:开始解析@Import注解,这个注解可以指定某些类由Spring容器管理

  • 1.5:扫描这个类是否有被@ImportResource标注,如果有这个注解,则解析该注解,这个注解作用就是引进一xml配置,比如以前Spring项目里写了很多配置bean信息的xml文件,通过这个注解将这些bean配置文件加载进来,加载这些文件里的配置信息

  • 1.6:解析类里被@Bean标注的方法

  • 1.7:解析当前类的接口里的default方法,这里可以看出可以在接口的default方法上使用@Bean注解

  • 1.8:查看该类是否有父类和父接口,如果有的话则递归调用processConfigurationClass()方法来解析

  • 1.9:最后执行前几步中扫描出来的DeferredImportSelector类,比如我们自动加载的@EnableAutoConfiguration注解里@Import引入的用于加载自动组件的AutoConfigurationImportSelector类(原理是这个类的selectImports方法会去查看META-INF/spring.factory下找到EnableAutoConfiguration的配置里的一些自动加载的组件查找spring.factory的源码解析看这里),这个接口类放在最后执行是因为这些自动加载的类很多都用到了@Conditional相关条件注解,比如@ConditionalOnMissingBean,所以需要等到其他bean已经扫描完后再执行这个类的逻辑

1.1到1.8的代码如下:

/*** Apply processing and build a complete {@link ConfigurationClass} by reading the* annotations, members and methods from the source class. This method can be called* multiple times as relevant sources are discovered.* @param configClass the configuration class being build* @param sourceClass a source class* @return the superclass, or {@code null} if none found or previously processed*/@Nullableprotected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {// 1.1if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);}// 1.2// Process any @PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {processPropertySource(propertySource);}else {logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");}}// 1.3// Process any @ComponentScan annotationsSet<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with @ComponentScan -> perform the scan immediatelySet<BeanDefinitionHolder> scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());}}}}// 1.4// Process any @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), true);// 1.5// Process any @ImportResource annotationsAnnotationAttributes importResource =AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if (importResource != null) {String[] resources = importResource.getStringArray("locations");Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");for (String resource : resources) {String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);}}// 1.6// Process individual @Bean methodsSet<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// 1.7// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// 1.8// Process superclass, if anyif (sourceClass.getMetadata().hasSuperClass()) {String superclass = sourceClass.getMetadata().getSuperClassName();if (superclass != null && !superclass.startsWith("java") &&!this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null;}

2、将扫描到的类封装成BeanDefinition并注册到BeanFactory容器

通过ConfigurationClassBeanDefinitionReader来解析第三步中parser放到configurationClasses的Map里的ConfigurationClass,并解析成BeanDefinition注册到容器中,debug图如下:

/*** Read a particular {@link ConfigurationClass}, registering bean definitions* for the class itself and all of its {@link Bean} methods.*/private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {// 先判断是否有@Conditional注解,有的话,校验条件是否满足,不满足条件,则从容器中删除if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName = configClass.getBeanName();if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}// 将通过@Import注解引入的类封装成beanDefinition,注册到容器内if (configClass.isImported()) {registerBeanDefinitionForImportedConfigurationClass(configClass);}// 将通过@Bean标注的方法封装成BeanDefinition注册到容器内for (BeanMethod beanMethod : configClass.getBeanMethods()) {loadBeanDefinitionsForBeanMethod(beanMethod);}// 加载@ImportResource指定的配置文件里的信息,加载配置文件里的beanDefinitionloadBeanDefinitionsFromImportedResources(configClass.getImportedResources());// 执行引入的ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法,比如@EnableConfigurationProperties注解上的EnableConfigurationPropertiesRegistrar.classloadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());}

这里的TrackedConditionEvaluator类就是解析@Conditional注解的,比如@ConditionalOnClass、@ConditionalOnBean等注解,原理就是这些注解上都会指定一个Condition接口的实现类,通过这个类的matches方法来判断是否符合条件,比如@ConditionalOnClass注解如下图:

而OnClassCondition类图如下:

而这里有个逻辑就是像@ConditionalOnBean这个注解的条件是必须已经加载了某个bean,在调用这个注解的matches方法时,需要等到所有的bean都扫描后,所以这里还有个阶段的概念,指定当前的matches方法是在哪个阶段做匹配,比如OnBeanCondition就指定只在注册阶段匹配:

而这个阶段的枚举有两个:

PARSE_CONFIGURATION:指的是在上面的parser的parse阶段,即:在扫描包路径并封装成ConfigurationClass阶段
REGISTER_BEAN:指的就是当前这一步的reader的loadBeanDefinitionsForConfigurationClass阶段,即:将ConfigurationClass转成beanDefinition注册到容器阶段

3、实例化所有的BeanDefinition,其中包括解决循环依赖、延迟加载问题

而bean的真正实例化就是通过BeanFactory容器的getBean方法来实现的,先看下BeanFactory的类图:

这里提供了通过bean名字以及类型信息来获取bean的方法,根据开头的调用链的图,我们debug进finishBeanFactoryInitialization(beanFactory)方法的beanFactory.preInstantiateSingletons()方法里,代码如下:

@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}

这段代码作用就是:
1、通过getBean(beanName)方法 实例化所有非延迟加载的bean(延迟加载的bean会在给bean做注入时生成一个代理类的方法来实现)
2、遍历出所有已经实例化的SmartInitializingSingleton类,并调用这个类的afterSingletonsInstantiated()方法

getBean(beanName)源码分析:

在bean的实例化过程中,Spring将这个过程分成两个阶段:

  • 实例化阶段,Spring通过反射调用这个类的构造器得到的一个空对象,这时这个对象里的依赖都是null(除非该属性是通过构造器注入),在这个阶段完成后,就将这个空对象的引用放到一个Map中暴露出去,如果出现循环依赖时,会在这个Map中拿到引用,从而注入这个引用来解决循环依赖问题,后面会详细将这个循环依赖的解决过程,我后面称这种对象为【半实例化bean】
  • 依赖注入阶段,对空对象进行依赖注入,如果发现Spring容器内还没有所依赖的bean,则开始实例化这个所依赖的bean。我后面称这种完成注入的bean为【完全实例化bean】

核心步骤如下:

  • 检查singletonObjects这个Map(存储已经完全实例化的bean)是否存在已经存在
  • 检查earlySingletonObjects这个Map(存储提前暴露的半实例化的bean,解决循环依赖)
  • 检查singletonFactories这个Map(存储提前暴露的半实例化的bean,解决循环依赖),如果存在则将调用这个Factory的getObject方法获取bean,然后将这个bean放到earlySingletonObjects里
  • 如果上面三步中存在已经创建的bean,则检查这个bean是否是FactoryBean,是的话,则调用这个FactoryBean的getObject方法获取bean
  • 如果不存在已经创建的bean,则需要新实例化bean,首先检查是否存在非单例bean(比如scope="prototype")循环依赖问题,如果存在,则直接报错,非单例bean的循环依赖是无法解决的,因为每次都要重新new对象,每次都是一个新的引用,已经无法通过将引用提前暴露出去的方式来解决了
  • 检查是否存在父BeanFactory,如果存在,则调用父BeanFactory的getBean来进行实例化
  • 标记bean已经创建,即:在alreadyCreated这个set中加入这个bean的beanName
  • 重新合并这个beanDefinition,这个合并的意思是指如果这个bean有父bean,则需要将父bean的beanDefinition和当前这个bean的beanDefinition合并成一个BeanDefinition,比如这种定义的bean,在实例化son的时候,需要将father的beanDefinition合并到一起,因为父bean里也可能会定义一些spring的特性(比如注入一些属性等),所以需要一起实例化,否则被son继承的father里的一些注入属性会为null
  • 查看当前bean有没有被@DependsOn注解标注,该注解的意思是标注当前bean在实例化前需要依赖的其他bean,需要先实例化@DependsOn注解中指定的依赖的类
  • 检查当前bean是否是单例bean(即:只生成一个对象),单例bean走单例bean的逻辑,详见后面单例bean分析
  • 检查当前bean是否是原型bean(即:每次都生成一个新的对象),原型bean走原型bean的逻辑,详见后面分析
  • 即非单例bean也非原型bean,则走其他Scope的逻辑,详见后面分析
  • 如果最后生成的bean类型不匹配,则进行类型转换
/*** Return an instance, which may be shared or independent, of the specified bean.* @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取bean的名字,这里主要会过滤FactoryBean的&符号final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 检查是否已经创建过单例对象Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}//如果存在已经创建的bean,则检查这个bean是否是FactoryBean,是的话,则调用这个FactoryBean的getObject方法获取beanbean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 如果这个bean是多例模式,而多例模式循环依赖自己的话是无法解决的,因为需要无限new对象// 而单例模式的循环依赖是可以解决的,毕竟只有一个对象,引用只有一个,不需要无限new对象if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.// 优先使用父beanFactory实例化beanBeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}// 标记bean已经被创建if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {// 如果一个bean有父bean,比如<bean id="son" class="com.llf.bean.Son" parent="father" depends-on="father"></bean>,则将这个父子的链合并成一个beanDefinition,因为父bean里也可能会定义一些spring的特性,所以需要一起实例化,比如父bean里有依赖注入等checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 查看当前bean有没有被@DependsOn注解标注,该注解的意思是标注当前bean在实例化前依赖的其他bean,需要先实例化@DependsOn注解中指定的依赖的类String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// 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 put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 原型模式(每次new一个新对象)的实例化else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}// 其他自定义Scope的实例化,比如session、request的scope的实例化else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// 如果类型不一致则做下类型转换// Check if required type matches the type of the actual bean instance.if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}

3.1 单例bean的实例化

spring 默认是单例bean,即:scope=“single”

核心步骤如下:

  • 检查用来存储已经创建的单例bean的Map:singletonObjects中是否存在该bean,如果存在则直接返回
  • 如果容器正在销毁,则停止创建并抛出异常
  • 将beanName放到singletonsCurrentlyInCreation这个set中,标记当前bean正在创建中
  • 调用createBean方法实例化bean,详见后面源码分析
  • 实例化完成后,从singletonsCurrentlyInCreation这个set中删除该beanName,标识该bean的创建过程已经完成(但是这个bean锁依赖的属性都没有完成注入,还不能使用)
  • 将完成实例化的bean放到singletonObjects这个Map中
  • 从singletonFactories、earlySingletonObjects缓存中删除这个bean,这两个缓存是为了解决循环依赖问题,因为已经完全实例化并已加到singletonObjects中,所以从这两个缓存中删除
  • 按实例化顺序保存到registeredSingletons这个set中( registeredSingletons是个linkedSet)
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 put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}                   public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {// 检查是否该单例bean已经被创建,已经被创建就直接返回Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}// 检查singletonsCurrentlyInCreation这个set中是否存在当前类,存在的话,说明当前类本来就处于创建过程中,则抛出错误,所以在单例bean的循环依赖场景中,如果是通过构造函数来进行注入时的循环依赖就会抛出错误,因为构造器注入的循环依赖场景会导致bean的构造过程都无法完成,只能报错(通过属性来注入时的循环依赖场景并不妨碍先new出该对象,然后再注入彼此的引用就可以了)beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {// 调用调用这个方法时传入的函数,即: createBean(beanName, mbd, args)singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime ->// if yes, proceed with it since the exception indicates that state.singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}// 实例化完成后,从singletonsCurrentlyInCreation这个set中删除该beanName,标识该bean的创建过程已经完成(但是这个bean锁依赖的属性都没有完成注入,还不能使用)afterSingletonCreation(beanName);}if (newSingleton) {// 创建完成后,将bean缓存到singletonObjectsMap中,从为了解决循环依赖的几个缓存中删除提前暴露的引用(后面会详细提到)addSingleton(beanName, singletonObject);}}return singletonObject;}}

createBean()方法解析:

createBean方法核心逻辑是调用doCreateBean()方法:

核心步骤如下:

  • 检查缓存FactoryBean的factoryBeanInstanceCache的Map是否存在该bean
  • 如果没有则调用createBeanInstance()来实例化对象,详见后面的createBeanInstance源码分析
  • 指向MergedBeanDefinitionPostProcessor后置处理器逻辑,这些处理器里包括负责@Resource注解解析及注入的CommonAnnotationBeanPostProcessor和负责@AutoWired及@Value注解解析和注入的AutowiredAnnotationBeanPostProcessor后置处理器
  • 将半实例化的bean(还没有注入依赖属性的bean)放到singletonFactories这个map中提前暴露出去,来解决循环依赖问题
  • 进行依赖注入操作,详见后面你的源码分析
  • 检查该bean是否实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,如果实现了,则执行对应接口的set方法
  • 执行BeanPostProcessor后置处理器的postProcessBeforeInitialization方法,这个方法允许返回一个对象来替换当前的bean,比如返回一个代理
  • 执行bean的InitMethods方法,包括实现了InitializingBean接口的afterPropertiesSet方法,@Bean注解指定的init-method方法
  • 执行BeanPostProcessor后置处理器的postProcessAfterInitialization方法,这个方法允许返回一个对象来替换当前的bean,比如返回一个代理
  • 检查如果BeanPostProcessor后置处理器返回了一个新对象来代替原bean,那么提前暴露到singletonFactories这个Map中的引用就是失效的,需要将依赖当前这个bean的对象重新实例化
  • 注册bean被销毁时需要执行的方法,比如实现了DisposableBean接口的destroy方法,这个destroy方法是根据bean的scope来区分的,这个scope表明这个bean的声明周期,比如scope=request表示当前bean的生命周期持续到一次请求结束,那么在请求结束时就需要执行这个bean的destroy方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;// FactoryBean的缓存中是否存在if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 实例化beaninstanceWrapper = createBeanInstance(beanName, mbd, args);}//获取真正的beanfinal Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.// 执行MergedBeanDefinitionPostProcessor后置处理器,为这个bean的依赖注入做准备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.// 为了解决循环依赖,将实例化的bean的引用提前缓存到singletonFactories这个Map中,这时的bean里的依赖属性还没有被注入(通过构造器注入的属性例外),所以是不完整的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的init方法(被@PostConstruct标注的方法)// 执行BeanPostProcessor后置处理器的方法exposedObject = initializeBean(beanName, exposedObject, mbd);}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);}}// 如果提前暴露的bean已经被注入,这里还需要检测是否bean被重新实例化了,如果被重新实例化了,则原来暴露出去的引用已经过期,需要重新注入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 " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.// 注册bean被销毁时需要执行的方法,比如实现了DisposableBean接口的destroy方法try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

createBeanInstance方法源码

核心逻辑如下:

  • 通过bean名称解析出bean的Class信息
  • 查看是否配置了生成对象的Supplier,如果配置了,就是用这个Supplier来生成对象
  • 检查bean是否配置了factory-method,这个就是配置一个工厂类来生成对象,比如
  • 检查是否之前已经解析过,如果已经解析过构造器或者factory-method,则不重新解析
  • 执行SmartInstantiationAwareBeanPostProcessor后置处理器的determineCandidateConstructors方法,该后置处理器返回bean的构造器,比如AutowiredAnnotationBeanPostProcessor后置处理器会返回带参数的构造器
  • 如果存在有参构造器,则执行有参构造器,并且执行过程中会负责这个构造器里参数的注入
  • 如果不存在有参构造器就执行无参构造器
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually resolved at this point.// 通过bean名称解析出bean的Class信息Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}// 查看是否配置了生成对象的SupplierSupplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 检查bean是否配置了factory-method,比如<bean id="myBean" factory-bean="myBeanFactory" factory-method="getMyBean"></bean>if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...// 检查是否之前已经解析过,如果已经解析过构造器或者factory-method,则不重新解析boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}// 已经解析过则直接实例化if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}// Candidate constructors for autowiring?// 执行SmartInstantiationAwareBeanPostProcessor后置处理器的determineCandidateConstructors方法,该后置处理器返回bean的构造器Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {// 执行有参数的构造器return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 执行无参构造器// No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);}

populateBean源码分析

核心步骤如下:

  • 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessAfterInstantiation方法,该方法如果返回fase则表示不需要做后续的依赖注入动作,直接返回
  • 查看当前这个BeanDefinition是否配置了依赖注入的对象
  • 根据注入类型来获取对应的需要注入的对象,默认值是0,即:没有指定是通过name还是type来注入,会使用后置处理器来完成注入,这里会通过CommonAnnotationBeanPostProcessor的postProcessProperties方法完成@Resourse的注入,通过AutowiredAnnotationBeanPostProcessor的postProcessProperties来完成@AutoWired和@Value的注入,有兴趣的同学可以看着两个方法的源码
  • 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessProperties方法,这里就会执行CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor来完成相应注解的注入逻辑,同时这个方法会返回一个PropertyValues对象,如果该对象有值的话,会根据这个对象再次注入,而这两个后置处理器在处理注入时,会处理@Lazy注解标志的延迟加载逻辑,详见延迟加载源码分析 如果PropertyValues对象有值,则根据这个对象里的key找到bean里的属性,完成value的注入
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 {// Skip property population phase for null instance.return;}}// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.boolean continueWithPropertyPopulation = true;// 执行InstantiationAwareBeanPostProcessor后置处理器的postProcessAfterInstantiation方法,该方法如果返回fase则表示不需要做后续的依赖注入动作,直接返回if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}if (!continueWithPropertyPopulation) {return;}// 查看当前这个BeanDefinition是否配置了属性PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);int resolvedAutowireMode = mbd.getResolvedAutowireMode();// 根据注入类型来获取对应的需要注入的对象,默认值是0,即:没有指定是通过name还是type来注入,会使用后置处理器来完成注入if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}//  执行InstantiationAwareBeanPostProcessor后置处理器的postProcessProperties方法,这里就会执行CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor来完成相应注解的注入逻辑,同时这个方法会返回一个PropertyValues对象,如果该对象有值的话,会根据这个对象再次注入for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}// 根据pvs对象来进行注入if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}

延迟加载源码分析

我这里以CommonAnnotationBeanPostProcessor后置处理器的代码来分析下原理,代码位置在CommonAnnotationBeanPostProcessor类的内部类ResourceElement的getResourceToInject方法里的buildLazyResourceProxy方法,思路就是并不真正的实例化这个bean,而是返回一个代理类的引用,这个代理类里会生成一个TargetSource对象,在程序运行过程中,碰到这个bean的方法被真正调用时,就会首先调用这个TargetSource对象的getTarget方法来实例化这个bean,想看详细分析的点这里,代码如下:


protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) {TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return element.lookupType;}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {return getResource(element, requestingBeanName);}@Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf = new ProxyFactory();pf.setTargetSource(ts);if (element.lookupType.isInterface()) {pf.addInterface(element.lookupType);}ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);return pf.getProxy(classLoader);}

循环依赖问题分析

Spring只能解决单例bean的循环依赖问题,对于多例bean(scope=“prototype”)的是无法解决的,解决办法就是在bean半实例化出来时(这时候的bean的注入逻辑还没完成,只是刚通过反射构造器new出来的一个空对象),就将这个bean的引用提前暴露到一个Map中,而依赖这个对象的bean在创建时,会首先遍历这个Map,并将找到的引用注入到bean中,这样就解决了循环依赖问题,但是当bean循环依赖的对象是通过构造器来进行注入时,就无法解决了,因为这时候连半实例化的对象都没有(因为要通过构造器的反射来实例化对象),下面是bean在创建过程中几个缓存的get和set的时间点的分布图:

3.2 原型bean的创建(scope=“prototype”)

原型bean是每次都创建新的对象,所以每次是直接调用createBean方法,不像单例bean会将创建后的bean放到一个Map中并且每次首先查询这个Map,原型bean在创建前会调用beforePrototypeCreation()方法,将beanName放入prototypesCurrentlyInCreation这个set中,这个set存放了处于创建中的非单例bean,原型bean在创建前会遍历这个Set,如果存在则直接报错,所以对于非单例的bean的循环依赖问题,spring是没办法解决的


else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}

3.3 其他Scope的bean的创建

比如scope=“request”、scope="session"这种生命周期的bean的创建过程,逻辑是调用通过Scope的get方法来获取bean,比如request的Scope的get方法会先从一个requestAttribute对象里取bean,如果不存在则再通过beanFactory来生成bean:

  {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}

Springboot之Bean的加载过程相关推荐

  1. 面试官:讲讲Spring框架Bean的加载过程

    spring作为目前我们开发的基础框架,每天的开发工作基本和他形影不离,作为管理bean的最经典.优秀的框架,它的复杂程度往往令人望而却步. 不过作为朝夕相处的框架,我们必须得明白一个问题就是spri ...

  2. 如何正确控制springboot中bean的加载顺序总结

    1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...

  3. 面试官:讲讲Bean的加载过程

    spring作为目前我们开发的基础框架,每天的开发工作基本和他形影不离,作为管理bean的最经典.优秀的框架,它的复杂程度往往令人望而却步. 不过作为朝夕相处的框架,我们必须得明白一个问题就是spri ...

  4. 框架源码专题:springIOC的加载过程,bean的生命周期,结合spring源码分析

    文章目录 1.BeanFactory和ApplicationContext的区别? 2. IOC与 Bean的加载过程 ①:初始化容器DefaultListableBeanFactory ②:创建读取 ...

  5. bean的加载-配置文件的解析

    bean的加载-配置文件的解析 spring的启动流程部分内容比较多,因此在之前先做了以下这些源码分析,这些要简单些. spring-webmvc启动流程 spring-webmvc请求处理流程 sp ...

  6. 【Spring源码分析系列】bean的加载

    前言 以 BeanFactory bf  = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过 ...

  7. Spring component-scan类扫描加载过程

    2019独角兽企业重金招聘Python工程师标准>>> https://github.com/javahongxi 有朋友最近问到了spring加载类的过程,尤其是基于annotat ...

  8. Spring框架—SpringBean加载过程

    原文作者:RunAlgorithm 原文地址:图文并茂,揭秘 Spring 的 Bean 的加载过程 1. 概述 Spring 作为 Ioc 框架,实现了依赖注入,由一个中心化的 Bean 工厂来负责 ...

  9. Spring 源码分析(七)--bean的加载详细分析

    一:缓存中获取单例bean 前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从sing ...

最新文章

  1. 南方电网两栖机器人_探访国内最大5G智能电网应用区:5G机器人已替代人工巡检...
  2. 提示You don't have permission to access /index.php on this server.
  3. 网站互点排名掉了网站互点排名掉了网站互点_7天上百度首页排名优化技巧有哪些?...
  4. matlab循环标注,for循环
  5. python 递归 写平方_Python算法:推导、递归和规约
  6. 最近有粉丝向我请教Java泛型,于是重温了一下,希望学弟面试顺利
  7. 基于Spring Cloud微服务化开发平台-Cloud Platform后台管理系统 v3.1.0
  8. 导入php项目_商业裂变,之项目技术实战(第九节:程序框架的安装)
  9. nginx+Keeplive高可用集群部署
  10. FLV格式视频转换成MP4格式教程
  11. python图像数字识别
  12. 睿智的目标检测22——Keras搭建RFBnet目标检测平台
  13. 《天才在左 疯子在右》读书记
  14. 问题解决:consider to specify kernel configuration cache directory through OPENCV_OCL4DNN_CONFIG_PATH par
  15. Run-down Protection
  16. 通信协议学习-485通信(1)
  17. mysql快速复制数据库中所有表及数据至另一个库中
  18. 差分函数(差分运算)
  19. 俗话说:十赌九输。因为大多数赌局的背后都藏有阴谋。不过也不尽然,有些赌局背后藏有的是:“阳谋”。
  20. 下载bilibi视频 下载B站视频

热门文章

  1. 打造教育培训的“师育学大”——线上教育网站建设这件事
  2. 移远EC20 4G模块的GPS部件刷新率修改方法,附GPS数据格式说明
  3. 搜索:刘超的博客及《Lucene 原理与代码分析》
  4. parseInt深度探究
  5. LeetCode 455. 分发饼干
  6. JMH API 详解
  7. html margin属性,HTML5属性:margin属性的用法实例
  8. 支持post的web服务器搭建,搭建Web服务器
  9. Web3D工程师(three.js)北京招聘
  10. 系统重装后会重启计算机吗,重装系统后电脑重启就黑屏怎么样解决