Spring——IOC容器启动及Bean生成流程

news2024/9/22 19:36:34

IOC容器启动及Bean生成流程

  • 一、容器启动
    • IOC启动流程
    • 重点
  • 二、扫描并注册BeanDefination
    • 加载并过滤资源
    • 注册BeanDefination
  • 三、BeanFactory后置处理
  • 四、注册Bean后置处理器
  • 五、遍历BeanDefination,实例化单例Bean
    • preInstantiateSingletons
    • doGetBean(我们只关注单例)
    • createBean
      • 实例化前执行
    • doCreateBean
      • 实例化
      • 属性赋值
      • 初始化
    • getSingleton
  • 六、总结

基于 5.3.9版本

没有很详细了解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相关的内容,我们下面一个个看(注册代表放入工厂):

  1. 扫描并注册BeanDefination
  2. BeanFactory后置处理(invokeBeanFactoryPostProcessors)
  3. 实例化并注册Bean后置处理器(registerBeanPostProcessors)
  4. 遍历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(我们只关注单例)

  1. 首先会先判断Bean是否已经生成了
  2. 没生成就走getSingleton方法(对于单例而已)
  3. getSingleton执行的时候就会调用那个lambda表达式,也就是会执行createBean方法
  4. 生成的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);
            }

        }
    }

初始化

  1. 先会执行一个拓展点BeanFactoryAware
  2. 然后初始化前执行(BeanPostProcessors.postProcessBeforeInitialization)
  3. 初始化(利用反射执行init()方法、InitializingBean拓展点)
  4. 然后初始化后执行 (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

正常会先执行这个,只不过这里面内部会执行那个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的流程就结束啦

六、总结

  1. 整体上看Bean流程为:BeanDefination→实例化→属性赋值→初始化

  2. 后置处理器可以对上述流程各阶段前后做出相应的修改和调整

  3. 再细数一下过程中的拓展接口:

    BeanDefinitionRegistryPostProcessor:对BeanDefination后置处理

    BeanFactoryPostProcessor:对BeanFactory后置处理

    BeanPostProcessor:初始化前后处理

    InstantiationAwareBeanPostProcessor:实例化前后、属性赋值、初始化前后

    InitializingBean:初始化执行

    BeanFactoryAware:获取容器中的工厂

    ApplicationContextAware:获取容器上下文

    SmartInitializingSingleton:Bean全生成完了后执行

  4. 源码很多,但是我们挑自己感兴趣的那部分重点来看,就能形成一个结构化思维,最后再看一下图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32867.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea配置tomcat,解决控制台乱码问题

问题描述&#xff1a; 配置tomcat&#xff0c;解决idea运行tomcat8.5.27版本控制台输出乱码。 版本&#xff1a; jdk1.8.0_172 IntelliJ IDEA 2019.3 3 (Ultimate Edition) apache-tomcat-8.5.27 解决步骤&#xff1a; 1、打开目录 apache-tomcat-8.5.27\conf\ 目录下 logging…

编译原理—运行环境、局部存储分配、活动记录、全局栈式存储分配、非局部名字的访问、参数传递

编译原理—运行环境、局部存储分配、全局栈式存储分配、非局部名字的访问、参数传递#pic_center 65%x55%1. 运行环境1.1存储组织与分配1.2运行时内存划分2.活动记录2.1活动记录的内容2.2活动记录内容的存取3.静态存储分配3.1FORTRAN静态存储分配4. 动态存储分配4.1 栈式分配下的…

Java反射(Reflex)机制

反射概述 Reflection(反射)是Java被视为动态语言的关键&#xff0c;反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息&#xff0c;并能直接操作任意对象的内部属性及方法。 加载完类之后&#xff0c;在堆内存的方法区中就产生了一个Class类型的对象&#x…

【linux】linux实操篇之软件包管理

前言 关于这一快软件包管理知识点不多&#xff0c;我们主要认识一下rpm和yum这两个软件包管理工具&#xff0c;主要还是yum的使用&#xff01; rpm 包的管理 一种用于互联网下载包的打包及安装工具&#xff0c;它包含在某些 Linux 分发版中。它生成具有 .rpm 扩展名的文件。…

QQ plot 的解读

QQ plot全称是Quantile-Quantile Plot&#xff0c;分位数-分位数图是通过比较两个概率分布的分位数对这两个概率分布进行比较的概率图方法。 这个图形的形式非常简单&#xff0c;有点类似RNA-seq中评价两个样本相关性的散点图&#xff08;图1&#xff09;。这类图形为什么那么…

Java小技能:多级菜单排序并返回树结构菜单列表

文章目录 引言I 生成树形结构菜单列表1.1 获取全部菜单1.2 获取一级菜单,递归获取子节点。1.3 实体1.4 DtoII 常见问题2.1 no instance(s) of type variable(s) R exist so that void conforms to R,2.2 集合filter过滤Integer数值为空问题解决方案引言 需求: 服务商角色配置…

面试官:说说你了解的分布式 ID 生成方案

为什么需要分布式 ID 对于单体系统来说&#xff0c;主键 ID 常用主键自动的方式进行设置。这种 ID 生成方法在单体项目是可行的&#xff0c;但是对于分布式系统&#xff0c;分库分表之后就不适应了。比如订单表数据量太大了&#xff0c;分成了多个库&#xff0c;如果还采用数据…

创业可以做什么项目,六个轻资产创业项目推荐

​2022年已经接近尾声了&#xff0c;你有为下一年做好计划嘛&#xff0c;今年并不是平静的一年&#xff0c;口罩总是反反复复的出现&#xff0c;很多人萌生了创业的想法&#xff0c;那有没有不怕口罩的创业项目呢&#xff1f;虽然创业并不容易&#xff0c;但当你有了正确的方向…

【优化充电】粒子群算法电动汽车充电动态优化策略【含Matlab源码 2163期】

⛄一、粒子群算法电动汽车充电优化 1 电动汽车充电负荷估算 电动汽车的充电负荷主要与电动汽车起始充电时刻和充电时长相关,而起始充电时刻是由电动汽车用户的到家时间决定的,充电时长主要与电动汽车的行驶里程和充电倍率相关。 目前电动汽车还没有大规模运营, 只能通过统计燃…

笔试强训day1

一、选择题 第一题&#xff1a; 题解&#xff1a;y123返回值为123&#xff0c;是非零数&#xff0c;所以y123总是正确&#xff0c;因此循环条件由x<4控制&#xff0c;答案 为C 第二题&#xff1a; %5表示输出总共占据了五列&#xff0c;%.3表示只取字符串左边三个字符并且…

傻白入门芯片设计,wafer/die/chip/cell(一)

1.wafer&#xff1a; 晶圆&#xff0c;指一整个圆形的晶圆硅片。如果问及CPU的原料是什么&#xff0c;大家都会轻而易举的给出答案—是硅。这是不假&#xff0c;但硅又来自哪里呢&#xff1f;其实就是那些最不起眼的沙子。不过不是随便抓一把沙子就可以做原料的&#xff0c;一定…

HTTP 协议

1 HTTP 协议的介绍 HTTP&#xff08;Hyper Transfer Protocol&#xff09;&#xff1a;超文本传输协议HTTP 协议是基于 TCP/IP 协议的超文本&#xff1a;比普通文本更加强大传输协议&#xff1a;客户端和服务器的通信规则&#xff08;握手规则&#xff09; 注意&#xff1a; J…

【计算机毕业设计】21.二手拍卖系统maven源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 引言 近年来&#xff0c;电子商务发展的愈趋成熟使得人们的消费方式以及消费观念发生巨大改变&#xff0c;网上竞拍的拍卖模式随之发展起来。大学拍卖网旨在为湘大学生提供一个线上拍卖的交易平台。平台展示的商品大…

STM32CubeMX时钟树(72MHZ主频配置)

目录 一些基础概念 时钟树配置图 第一步 第二步 这里我只是配置常用的72MHZ主频&#xff0c;很多时候新手都在时钟树这里被劝退了。其实不知道没关系&#xff0c;我用STM32这么久了&#xff0c;也只知道大概。我们绝大多数时候不需要配置这个时钟&#xff0c;记住72MHZ主频…

LeetCode-795-区间子数组个数

1、双指针 根据题意&#xff0c;我们可以将数组中的数分为这三类&#xff1a;1、小于leftleftleft的数&#xff1b;2、大于等于leftleftleft且小于等于rightrightright的数&#xff1b;3、大于rightrightright的数。因此若我们使用双指针来维护区间[last2,last1][last2,last1]…

Nacos与Eureka中的高性能读写并发架构设计

Nacos、Eureka都是微服务领域内熟知、常用的注册中心组件。只不过呢&#xff0c;Nacos还多了个功能身份就是配置中心。从目前流行与随着Spring Cloud Alibaba发展来看&#xff0c;Nacos使用得更加多&#xff0c;也是趋势所在。 注册中心原理 注册中心原理其实很简单&#xff…

【18】Java常见的面试题汇总(Spring/Spring MVC)

目录 1. 为什么要使用 spring&#xff1f; 2. 解释一下什么是 aop&#xff1f; 3. 解释一下什么是 ioc&#xff1f; 4. spring 有哪些主要模块&#xff1f; 5. spring 常用的注入方式有哪些&#xff1f; 6. spring 中的 bean 是线程安全的吗&#xff1f; 7. spring 支持…

【Java八股文总结】之外卖平台项目整理

文章目录一、项目介绍1.1 项目整体介绍1.2 主要模块介绍二、项目开发2.1 后台管理系统开发2.1.1 员工管理employee1、员工后台登录2、员工退出3、过滤器4、新增员工5、员工信息分页查询↑&#xff08;参加上面&#xff09;6、修改员工信息7、根据id查询员工信息&#xff0c;回显…

后台开发的学习日记

后台开发的学习日记 Java后台开发的日记&#xff1a;Push一下自己每天都要学习后台 后台开发学习日志-Day1后台开发的学习日记Day1: 路线及资料的汇总一、应该选择什么语言&#xff1f;二、学习路线的规划及资料的汇总整理Day1: 路线及资料的汇总 第一天主要是路线的准备及资料…

Pytorch学习笔记(二)官方60min入门教程之自动微分

目录 一.相关包及函数介绍 二.雅各比向量积 三.练习代码 一.相关包及函数介绍 autograd 包是 PyTorch 中所有神经网络的核心。首先让我们简要地介绍它&#xff0c;然后我们将会去训练我们的第一个神经网络。该 autograd 软件包为 Tensors 上的所有操作提供自动微分。它是一…