暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring的Bean的生命周期_面试系列之Spring

Java Miraculous 2021-09-18
818

有一天,小P去某大厂面试,其中一段面试对话如下:

面试官:“看过Spring源码吗?”
小P:“看......看过一点”
面试官:“那你说下Spring中Bean的生命周期吧”
小P:“bean的创建-->bean的使用-->bean的销毁”
面试官:“可以详细说下吗?”
小P:“这个......我不大能想起来了”
......
相信在座的各位在面试时都遇到过这个问题,而大部分人的回答和小P一样,为什么会这样?因为这些人都是背的答案,结果在面试的时候一紧张给忘了,所以死记硬背是不可取的,那怎么办?自己去啃源码,并且理解大概的流程,只有这样才能做到真正的理解记忆,下面我们通过跟踪Spring的启动源码来捋捋Bean的生命周期。
  • 一、自定义bean及配置文件

  • 1、定义一个Bean

    package com.example.demo.spring;


    /**
    * 自定义一个Bean
    */
    public class XiaoPBean {


    private String name = "xiaoP";


    public String getName() {
    return name;
    }


    public void setName(String name) {
    this.name = name;
    }
    }


    • 2、自定义spring配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.1.xsd">


      <bean id="xiaoPBean" class="com.example.demo.spring.XiaoPBean"/>
      </beans>
      bean一般是在spring容器启动时创建的,当然也有可能是延迟加载,如果配置lazy-init属性为true,是不会在容器启动时创建的,而是用到的时候才创建

      由于我们要跟踪Spring的启动过程,所以这里我们不采用延时加载的方式。
      • 3、new一个容器

        package com.example.demo.spring;


        import org.junit.Test;
        import org.springframework.context.support.ClassPathXmlApplicationContext;


        public class BeanFactoryTest {


        @Test
        public void testSimpleLoad(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/bean.xml");
        XiaoPBean xiaoPBean = (XiaoPBean) applicationContext.getBean("xiaoPBean");
        System.out.println(xiaoPBean.getName());
        }
        }


        • 4、运行下看是否正常

        • 二、调试

        因为Bean是在Spring容器启动时创建的,所以我们要从Spring容器启动时开始调试,步骤一的方式叫做原始方式,就是自己选择容器,这里选择的是ClassPathXmlApplicationContext,当然Spring中还有很多其它的容器,都可以用的,比如XmlBeanFactory、FileSystemXmlApplicationContext等,在创建容器时会调用容器的启动方法

        其实除了原始的方式,还可以通过SpringBoot的入口类中的run方法进行调试

        SpringBoot的牛逼之处就在于这个run方法了,什么加载配置文件,环境信息,监听等都是在这加载的,反观原始方式,需要指定配置文件的位置,另外需要监听什么的都得手动配置。
        不管使用哪种方式,最终都得调用容器启动的核心方法

        注意:这里使用原始的方式,因为SpringBoot加载的是项目中全部的Bean,而我只是想加载自定义的Bean,所以用原始方法较为灵活点

        经过ClassPathXmlApplicationContext的两个构造方法,最终会调用到org.springframework.context.support.AbstractApplicationContext#refresh方法,这个方法就是Spring容器启动的核心方法

        先贴下refresh的源码,将注释翻译成国语如下:
          @Override
          public void refresh() throws BeansException, IllegalStateException {
          synchronized (this.startupShutdownMonitor) {
          StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");


          // 1、刷新前的准备
          prepareRefresh();


          // 2、告诉子类刷新内部 bean 工厂
          ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


          // 3、准备在此上下文中使用的 bean 工厂
          prepareBeanFactory(beanFactory);


          try {
          // 4、允许在上下文子类中对 bean 工厂进行后处理
          postProcessBeanFactory(beanFactory);


          StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
          // 5、调用在上下文中注册为 bean 的工厂处理器
          invokeBeanFactoryPostProcessors(beanFactory);


          // 6、注册拦截 bean 创建的 bean 处理器
          registerBeanPostProcessors(beanFactory);
          beanPostProcess.end();


          // 7、初始化此上下文的消息源
          initMessageSource();


          // 8、为此上下文初始化事件多播器
          initApplicationEventMulticaster();


          // 9、初始化特定上下文子类中的其他特殊 bean。
          onRefresh();


          // 10、检查监听器 bean 并注册它们
          registerListeners();


          // 11、实例化所有剩余的(非延迟初始化)单例
          finishBeanFactoryInitialization(beanFactory);


          // 12、最后一步:发布相应的事件
          finishRefresh();
          }


          catch (BeansException ex) {
          if (logger.isWarnEnabled()) {
          logger.warn("Exception encountered during context initialization - " +
          "cancelling refresh attempt: " + ex);
          }


          // 13、销毁已经创建的单例以避免悬空资源
          destroyBeans();


          // 14、重置“活动”标志
          cancelRefresh(ex);


          // 15、将异常传播给调用者
          throw ex;
          }


          finally {
          // 16、重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据......
          resetCommonCaches();
          contextRefresh.end();
          }
          }
          }
          通过注释可以看到,Spring容器的启动大概包括15个步骤,下面看看每一步都做了什么
          • 1、prepareRefresh():刷新前的准备

            protected void prepareRefresh() {
            // 设置当前时间为容器的启动时间
            this.startupDate = System.currentTimeMillis();
            // 将关闭状态设置为false,因为要开始启动嘛
            this.closed.set(false);
            // 将激活状态设置为true
            this.active.set(true);


            //打印日志
            if (logger.isDebugEnabled()) {
            if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
            }
            else {
            logger.debug("Refreshing " + getDisplayName());
            }
            }


            // 1.1、初始化Environment的propertySources属性
            initPropertySources();


            // 1.2、验证所有标记为必需的属性都是可解析的:请参阅 ConfigurablePropertyResolver#setRequiredProperties
            getEnvironment().validateRequiredProperties();


            // 1.3、存储预刷新应用程序监听器...
            if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
            }
            else {
            // 1.4、将本地应用程序监听器重置为刷新前状态
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
            }


            // 1.5、允许收集早期的 ApplicationEvents,一旦多播器可用就发布......
            this.earlyApplicationEvents = new LinkedHashSet<>();
            }
            • 1.1、初始化Environment的propertySources属性

            点进去你会发现它是个空方法,但是有一行注释:

            这是什么意思呢?就是说子类可以覆盖这个方法,去初始化一些自定义的属性信息。
            这个initPropertySources方法是抽象类AbstractApplicationContext中的方法,我们demo中用的容器类ClassPathXmlApplicationContext是AbstractApplicationContext的子类

            那我们看下ClassPathXmlApplicationContext中有没有覆盖initPropertySources方法

            可以看到,ClassPathXmlApplicationContext并没有覆盖initPropertySources方法,所以要想看到效果,我们得自己动手了
            自定义一个容器继承ClassPathXmlApplicationContext,然后重写initPropertySources方法,这里往environment中的systemProperties中添加了一个girl属性

            将测试类中的容器改为我们自定义的容器MyClassPathXmlApplicationContext,debug走一波

            到initPropertySources这里先停下,可以看到environment中的systemProperties的属性信息一共有55个,然后在刚才自定义的容器MyClassPathXmlApplicationContext中的initPropertySources打上断点,继续你会发现它进去了,而且systemProperties中的属性信息变为56个,查看source可以发现girl属性被成功的添加进去了

            所以从这可以看出,spring牛逼之处不仅在于给开发人员提供便利,还支持扩展,简直强的一批
            • 1.2、验证所有标记为必需的属性都是可解析的

            其实就是检查被标记为必须的属性是否存在

            这又是啥意思?在刚覆盖的initPropertySources方法中再加一行

            重新debug

            然后继续走到validateRequiredProperties这一步

            点进去validateRequiredProperties,可以看到是个接口方法,看下实现类

            进入AbstractPropertyResolver,打上断点

            其实到这里,你应该就差不多明白了

            就是校验当前加载的属性中有没有boy这个属性,如果没有,是要抛异常的,因为我们前面并没有添加boy属性,所以这里就抛异常了

            • 1.3、存储预刷新应用程序监听器

            • 1.4、将本地应用程序监听器重置为刷新前状态

            • 1.5、允许收集早期的 ApplicationEvents,一旦多播器可用就发布

            初始化有关监听器的集合

            • 2、obtainFreshBeanFactory():告诉子类刷新内部 bean 工厂

            看下obtainFreshBeanFactory方法内部
              /**
              * Tell the subclass to refresh the internal bean factory.
              * @return the fresh BeanFactory instance
              * @see #refreshBeanFactory()
              * @see #getBeanFactory()
              */
              protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
                  // 1、刷新Bean工厂
              refreshBeanFactory();
                  // 2、返回Bean工厂
              return getBeanFactory();
                }
              • 2.1、refreshBeanFactory():刷新Bean工厂

                @Override
                protected final void refreshBeanFactory() throws BeansException {
                // 1、当前Bean工厂是否存在
                if (hasBeanFactory()) {
                // 如果存在,就销毁工厂里的单例bean
                destroyBeans();
                // 关闭Bean工厂
                closeBeanFactory();
                }
                try {
                // 2、新创建一个Bean工厂
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                // 3、给Bean工厂设置序列化id
                beanFactory.setSerializationId(getId());
                // 4、给Bean工厂做定制
                customizeBeanFactory(beanFactory);
                // 5、加载Bean定义信息
                loadBeanDefinitions(beanFactory);
                // 6、将新创建的Bean工厂设置为当前Bean工厂
                this.beanFactory = beanFactory;
                }
                catch (IOException ex) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
                }
                }
                这个方法有两个实现,选择第一个,也就是AbstractRefreshableApplicationContext,基于xml配置的会走这个,进去打上断点

                2.1.1-2.1.2、当前Bean工厂是否存在,不存在就创建

                2.1.3、给Bean工厂设置序列化id
                设置序列化id
                2.1.4、给Bean工厂做定制
                其实就是初始化两个属性
                allowBeanDefinitionOverriding:是否允许覆盖Bean的定义信息
                allowCircularReferences:是否允许循环引用,就是循环依赖的意思
                可以看到,缺省值都是true,也就是说默认是允许修改Bean的定义信息,而且也可以循环依赖的

                2.1.5、加载Bean定义信息
                就是将你配置的Bean进行加载,通过解析,最终封装成BeanDefinition,在Spring容器中,不论是Spring自带的Bean,还是引用的第三方的Bean,还是你自定义的Bean,最终都会封装成BeanDefinition,它就是Bean在Spring容器中的表现形式。
                可以看到loadBeanDefinitions方法是一个抽象方法,它有好几个实现

                这里其实就是从xml配置文件中解析配置的bean标签,所以我们看AbstractXmlApplicationContext即可

                这个方法做的主要工作是初始化了一个XmlBeanDefinitionReader去解析xml配置了,有兴趣的可以探讨下,这里不再赘述,最终解析完后如下

                可以看到,最终配置的xiaoPBean被解析到了一个叫做beanDefinitionMap的concurrentHashMap中,这个concurrentHashMap用的妙啊
                2.1.6、将新创建的Bean工厂设置为当前Bean工厂

                • 2.2、返回Bean工厂

                其实返回的就是当前的Bean工厂

                • 3、prepareBeanFactory(beanFactory):准备在此上下文中使用的 bean 工厂

                这个方法主要是为BeanFactory设置各种功能,主要是注册一些容器中需要的系统Bean,例如classloader,beanfactoryPostProcessor等
                  protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                  // 告诉内部bean工厂使用容器的类加载器
                  beanFactory.setBeanClassLoader(getClassLoader());
                  if (!shouldIgnoreSpel) {
                  // 设置beanFactory的表达式语言处理器,Spring3开始增加了对语言表达式的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值
                  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
                  }
                  // 为beanFactory增加一个默认的propertyEditor
                  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));


                  // 添加该处理器的作用:当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象
                  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));


                  // 如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,Spring 会通过其他方式来处理这些依赖
                  beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
                  beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
                  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
                  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
                  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
                  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
                  beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);


                  // 修正依赖,这里是注册一些自动装配的特殊规则,比如是BeanFactory class接口的实现类,则在运行时修指定为当前BeanFactory
                  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
                  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
                  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
                  beanFactory.registerResolvableDependency(ApplicationContext.class, this);


                  // 如果是,加入到事件监听者队列
                  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));


                  // 如果找到一个LoadTimeWeaver,那么就准备将后置处理器“织入”bean工厂
                  if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
                  beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                  // 为类型匹配设置临时类加载器.
                  beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
                  }


                  // 注册默认environment环境bean
                  if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
                  // 环境信息ConfigurableEnvironment
                  beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
                  }
                  if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
                  //系统属性,systemProperties
                  beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
                  }
                  if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
                  // 系统环境变量systemEnvironment
                  beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
                  }
                  if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
                  // 应用启动变量,5.3版本时增加
                  beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
                  }
                  }
                  • 4、postProcessBeanFactory(beanFactory):允许在上下文子类中对 bean 工厂进行后处理

                  点进去你会发现,这是一个空方法

                  看下实现类

                  同样AbstractRefreshableWebApplicationContext是针对xml的
                    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                    // 添加ServletContextAwareProcessor处理器
                    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
                    // 在自动注入时忽略指定的依赖接口,通常被应用上下文用来注册以其他方式解析的依赖项
                    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
                    beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
                    // 注册web应用的scopes
                    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
                    // 注册和环境有关的beans
                    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
                    }
                    • 5、invokeBeanFactoryPostProcessors(beanFactory):调用在上下文中注册为 bean 的工厂处理器

                    在第2步中已经将xml或者注解修饰的bean解析成了beanDefinition,那假如说我发现某个bean定义的属性有点问题,想修改怎么办,BeanFactoryPostProcessor满足你,它就用来修改Spring容器中的beanDefinition的,下面演示下
                    • 5.1、自定义一个XiaoPBeanFactoryPostProcessor

                    • 5.2、在MyClassPathXmlApplicationContext中覆盖customizeBeanFactory方法

                    • 5.3、debug运行到invokeBeanFactoryPostProcessors观察

                    接着就会调用XiaoPBeanFactoryPostProcessor中的postProcessBeanFactory方法


                    初始化的name是xiaoP,但是最后打印出来的是daP,说明成功修改属性的值。
                    • 6、注册拦截bean创建的bean处理器

                    从Spring容器中找出实现BeanPostProcessor接口的bean,并设置到BeanFactory中
                    • 6.1、自定义一个BeanPostProcessor

                    • 6.2、将自定义的BeanPostProcessor添加到BeanFactory中

                    • 6.3、debug走一波

                    你会发现registerBeanPostProcessors方法执行完后并没有打印XiaoPBeanPostProcessor中的打印,说明这一步只是将所有的BeanPostProcessor注册到BeanFactory中,那什么时候执行呢?当bean被初始化的时候会调用这个BeanPostProcessor中的postProcessBeforeInitialization和postProcessAfterInitialization方法后面会说到。
                    • 7、初始化此上下文的消息源

                    初始化MessageSource组件,做国际化功能、消息绑定、消息解析等。
                    • 8、为此上下文初始化事件多播器

                    事件多播器用于事件的发布
                    • 9、初始化特定上下文子类中的其他特殊bean

                    一个模板方法,预留给 AbstractApplicationContext的子类用于初始化其他特殊的 bean

                    • 10、检查监听器 bean并注册它们

                    注册实现了ApplicationListener接口的监听器bean

                    • 11、实例化所有剩余的(非延迟初始化)单例

                      protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
                      // 初始化此容器的转换器,转换器的职责是处理通过配置给Bean实例成员变量赋值的时候的类型转换工作
                      if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                      beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
                      beanFactory.setConversionService(
                      beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
                      }


                      // 如果没有注册过bean后置处理器post-processor,则注册默认的解析器,(例如主要用于解析properties文件的PropertyPlaceholderConfigurer
                      // ),@value注解或在xml中使用${}的方式进行环境相关的配置
                      if (!beanFactory.hasEmbeddedValueResolver()) {
                      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
                      }


                      // AOP分为三种方式:编译期织入、类加载期织入和运行期织入,LoadTimeWeaving属于第二种,主要通过JVM进行织入,先初始化LoadTimeWeaverAware
                      // bean,以便尽早注册它们的transformers
                      String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
                      for (String weaverAwareName : weaverAwareNames) {
                      getBean(weaverAwareName);
                      }


                      // 停止使用临时类加载器进行类型匹配
                      beanFactory.setTempClassLoader(null);


                      // 允许缓存所有bean定义元数据,不希望有进一步的更改
                      beanFactory.freezeConfiguration();


                      // 实例化所有剩余的(non-lazy-init非延时加载的)单例
                      beanFactory.preInstantiateSingletons();
                      }
                      这个方法的核心在最后一个方法preInstantiateSingletons,其实就是去创建相应的Bean

                      通过getBean方法最终会调到doCreateBean,流程如下org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

                      -->

                      org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

                      -->org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

                      -->org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

                      对于这个doCreateBean方法,由于之前文章分析过(传送门:Spring的doCreateBean方法解析),所以这里就说主要的逻辑了
                        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                        throws BeanCreationException {


                        1、实例化bean
                        BeanWrapper instanceWrapper = null;
                        if (mbd.isSingleton()) {
                        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
                        }
                        if (instanceWrapper == null) {
                        instanceWrapper = 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 {
                        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                        }
                        catch (Throwable ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
                        }
                        mbd.postProcessed = true;
                        }
                        }
                         
                        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));
                        }


                        Object exposedObject = bean;
                        try {
                              // 2、对bean的属性进行填充,属性注入
                        populateBean(beanName, mbd, instanceWrapper);
                              ///3、初始化bean
                        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);
                        }
                        }


                        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 " +
                        "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                        }
                        }
                        }


                        try {
                        registerDisposableBeanIfNecessary(beanName, bean, mbd);
                        }
                        catch (BeanDefinitionValidationException ex) {
                        throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
                        }


                        return exposedObject;
                        }
                        • 11.1、实例化bean

                        跟源码你最终会发现是调用的反射创建实例,调用栈如下:

                        org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

                        -->

                        org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean

                        -->

                        org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate

                        -->

                        org.springframework.beans.BeanUtils#instantiateClass

                        -->

                        java.lang.reflect.Constructor#newInstance

                        • 11.2、对bean的属性进行填充,属性注入

                        解析参考Spring的doCreateBean方法解析
                        • 11.3、初始化bean

                          protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
                          if (System.getSecurityManager() != null) {
                          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                          invokeAwareMethods(beanName, bean);
                          return null;
                          }, getAccessControlContext());
                          }
                          else {
                                // 1、执行实现了Aware接口中的方法
                          invokeAwareMethods(beanName, bean);
                          }


                          Object wrappedBean = bean;
                          if (mbd == null || !mbd.isSynthetic()) {
                                // 2、调用BeanPostProcessor的postProcessorsBeforeInitialization方法
                          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
                          }


                          try {
                          // 3、调用初始化方法(自定义的初始化方法或者实现InitialzingBean接口)
                          invokeInitMethods(beanName, wrappedBean, mbd);
                          }
                          catch (Throwable ex) {
                          throw new BeanCreationException(
                          (mbd != null ? mbd.getResourceDescription() : null),
                          beanName, "Invocation of init method failed", ex);
                          }
                          if (mbd == null || !mbd.isSynthetic()) {
                          // 4、调用BeanPostProcessor的postProcessorsAfterInitialization方法
                          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
                          }


                          return wrappedBean;
                          }
                          11.3.1、执行实现了Aware接口中的方法
                            private void invokeAwareMethods(String beanName, Object bean) {
                            // 如果Bean是Aware类型的
                            if (bean instanceof Aware) {
                            // 如果Bean是BeanNameAware类型的
                            if (bean instanceof BeanNameAware) {
                            // BeanNameAware设置beanName
                            ((BeanNameAware) bean).setBeanName(beanName);
                            }
                            // 如果Bean是BeanClassLoaderAware类型的
                            if (bean instanceof BeanClassLoaderAware) {
                            ClassLoader bcl = getBeanClassLoader();
                            if (bcl != null) {
                            // BeanClassLoaderAware设置beanClassloader
                            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                            }
                            }
                            // 如果Bean是BeanFactoryAware类型的
                            if (bean instanceof BeanFactoryAware) {
                            // BeanFactoryAware设置beanFactory
                            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
                            }
                            }
                            }
                            11.3.2、调用BeanPostProcessor的postProcessorsBeforeInitialization方法
                            在上买6.3的时候说到了,在初始化bean的时候会执行BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,现在看到了吧
                            11.3.3、调用初始化方法(自定义的初始化方法或者实现InitialzingBean接口)
                              protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
                              throws Throwable {
                              当前bean是否实现了InitializingBean接口
                              boolean isInitializingBean = (bean instanceof InitializingBean);
                              如果实现了 InitializingBean 接口,则只调用bean的 afterPropertiesSet()
                              if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
                              if (logger.isTraceEnabled()) {
                              logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
                              }
                              if (System.getSecurityManager() != null) {
                              try {
                              AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                              ((InitializingBean) bean).afterPropertiesSet();
                              return null;
                              }, getAccessControlContext());
                              }
                              catch (PrivilegedActionException pae) {
                              throw pae.getException();
                              }
                              }
                              else {
                              直接调用 afterPropertiesSet()
                              ((InitializingBean) bean).afterPropertiesSet();
                              }
                              }


                              if (mbd != null && bean.getClass() != NullBean.class) {
                              判断是否自定义了 init-method(),是的话再调用自定义的的init-method
                              String initMethodName = mbd.getInitMethodName();
                              if (StringUtils.hasLength(initMethodName) &&
                              !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                              !mbd.isExternallyManagedInitMethod(initMethodName)) {
                              利用反射执行
                              invokeCustomInitMethod(beanName, bean, mbd);
                              }
                              }
                              }
                              什么意思呢,比如XiaoPBean实现了InitializingBean接口,那么当初始化XiaoPBean的时候就会执行afterPropertiesSet方法

                              当然也可以配置自定义的初始化方法

                              注意:如果同时使用了init-method和InitializingBean,会先执行afterPropertiesSet,再执行init-method指定的方法, 如果指定的是同一个方法,则只会执行一次
                              11.3.4、调用BeanPostProcessor的postProcessorsAfterInitialization方法
                              可以看到BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法分别是在初始化方法的前后执行的。
                              • 12、最后一步:发布相应的事件

                              • 13、销毁已经创建的单例以避免悬空资源

                              如果启动异常,就销毁已经创建的bean,用于释放资源
                              • 14、重置“活动”标志

                              • 15、将异常传播给调用者

                              将启动失败的原因抛往上层
                              至此,Spring容器的启动流程大概是捋完了,可能你们已经懵了,这还是在略过创建Bean的过程的情况下(里面包含循环依赖什么的,当然之前也有文章分析过Spring的doCreateBean方法解析Spring容器的循环依赖)。
                              其实Bean的生命周期就包含在容器的启动流程中,但是容器的启动流程还包括其他和Bean的生命周期不相干的步骤,我们要把Bean的生命周期的步骤提炼出来,那么怎么提炼呢?我们就以自定义的Bean为中心,凡是操作了或者可能操作这个Bean的步骤都挑出来,最后连在一起,是不是就是Bean的生命周期了?
                              回看下我们上面分析的步骤,可以挑出的和Bean有关的步骤如下:

                              修改Bean的BeanDefinition

                              5、invokeBeanFactoryPostProcessors(beanFactory):用来修改Spring容器中的beanDefinition

                              实例化Bean

                              11.1、实例化bean  org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

                              初始化Bean

                              11.2、对bean的属性进行填充,属性注入org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

                              11.3.1、执行实现了Aware接口中的方法

                              如果Bean实现了BeanNameAware接口,就执行setBeanName方法

                              如果Bean实现了BeanClassLoaderAware接口,就执行setBeanClassLoader方法

                              如果Bean实现了BeanFactoryAware接口,就执行setBeanFactory方法

                              11.3.2、调用BeanPostProcessor的postProcessorsBeforeInitialization方法

                              11.3.3、调用初始化方法(自定义的初始化方法或者实现InitialzingBean接口)

                              11.3.4、调用BeanPostProcessor的postProcessorsAfterInitialization方法

                              咦?这好像只是创建Bean的过程,那Bean在什么时候销毁呢?其实是在容器关闭的时候

                              跟踪代码可以发现最终调用的是DisposableBean的destroy方法

                              org.springframework.context.support.AbstractApplicationContext#close

                              -->

                              org.springframework.context.support.AbstractApplicationContext#doClose

                              -->

                              org.springframework.context.support.AbstractApplicationContext#destroyBeans

                              -->

                              org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons

                              -->

                              org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingletons

                              -->

                              org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton

                              -->

                              org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroyBean

                              -->

                              org.springframework.beans.factory.DisposableBean#destroy

                              如果我们想在Bean销毁时做一些操作,可以让Bean实现DisposableBean接口,然后重写destroy方法即可,下面来张图直观的看下

                              附完成代码:
                              XiaoPBean:
                                package com.example.demo.spring;




                                import org.springframework.beans.BeansException;
                                import org.springframework.beans.factory.*;


                                /**
                                * 自定义一个Bean
                                */
                                public class XiaoPBean implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {


                                private String name = "xiaoP";


                                public String getName() {
                                return name;
                                }


                                public void setName(String name) {
                                this.name = name;
                                }


                                @Override
                                public void afterPropertiesSet() throws Exception {
                                System.out.println("执行了afterPropertiesSet方法......");
                                }


                                public void init(){
                                System.out.println("执行自定义的init-method......");
                                }


                                @Override
                                public void destroy() throws Exception {
                                System.out.println("执行destroy方法销毁......");
                                }


                                @Override
                                public void setBeanClassLoader(ClassLoader classLoader) {
                                System.out.println("设置classLoader");
                                }


                                @Override
                                public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
                                System.out.println("设置beanFactory");
                                }


                                @Override
                                public void setBeanName(String name) {
                                System.out.println("设置bean的name");
                                }
                                }


                                MyClassPathXmlApplicationContext:
                                  package com.example.demo.spring;


                                  import org.springframework.beans.factory.support.DefaultListableBeanFactory;
                                  import org.springframework.context.support.ClassPathXmlApplicationContext;


                                  public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {




                                  public MyClassPathXmlApplicationContext(String configLocations) {
                                  super(configLocations);
                                  }


                                  @Override
                                  protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
                                  beanFactory.addBeanPostProcessor(new XiaoPBeanPostProcessor());
                                  super.addBeanFactoryPostProcessor(new XiaoPBeanFactoryPostProcessor());
                                  }
                                  }


                                  XiaoPBeanFactoryPostProcessor:
                                    package com.example.demo.spring;


                                    import org.springframework.beans.BeansException;
                                    import org.springframework.beans.factory.config.BeanDefinition;
                                    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
                                    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;


                                    public class XiaoPBeanFactoryPostProcessor implements BeanFactoryPostProcessor {


                                    @Override
                                    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                                    System.out.println("XiaoPBeanFactoryPostProcessor调用了...");
                                    BeanDefinition xiaoPBean = beanFactory.getBeanDefinition("xiaoPBean");
                                    xiaoPBean.getPropertyValues().add("name", "daP");
                                    }
                                    }


                                    XiaoPBeanPostProcessor:
                                      package com.example.demo.spring;


                                      import org.springframework.beans.BeansException;
                                      import org.springframework.beans.factory.config.BeanPostProcessor;
                                      import org.springframework.lang.Nullable;


                                      public class XiaoPBeanPostProcessor implements BeanPostProcessor {


                                      @Nullable
                                      @Override
                                      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                                      System.out.println("XiaoPBeanPostProcessor的postProcessBeforeInitialization方法执行了");
                                      return bean;
                                      }


                                      @Nullable
                                      @Override
                                      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                                      System.out.println("XiaoPBeanPostProcessor的postProcessAfterInitialization方法执行了");
                                      return bean;
                                      }
                                      }


                                      BeanFactoryTest:
                                        package com.example.demo.spring;


                                        import org.junit.Test;


                                        public class BeanFactoryTest {


                                        @Test
                                        public void testSimpleLoad(){
                                        MyClassPathXmlApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring/bean.xml");
                                        XiaoPBean xiaoPBean = (XiaoPBean) applicationContext.getBean("xiaoPBean");
                                        System.out.println("使用xiaoPBean:" + xiaoPBean.getName());
                                        applicationContext.close();
                                        }
                                        }
                                        bean.xml
                                          <?xml version="1.0" encoding="UTF-8"?>
                                          <beans xmlns="http://www.springframework.org/schema/beans"
                                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                          xmlns:context="http://www.springframework.org/schema/context"
                                          xsi:schemaLocation="http://www.springframework.org/schema/beans
                                          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                                          http://www.springframework.org/schema/context
                                          http://www.springframework.org/schema/context/spring-context-3.1.xsd">




                                          <bean id="xiaoPBean" class="com.example.demo.spring.XiaoPBean" init-method="init"/>


                                          </beans>
                                          运行下BeanFactoryTest的testSimpleLoad方法,可以清晰的观察到Bean的生命周期

                                          最后,再回答下面试官的问题,Spring的Bean的生命周期:r()
                                          1、调用BeanFactoryPostProcessor的postProcessBeanFactory()方法修改Bean的定义信息(如果有)
                                          2、调用AbstractAutowireCapableBeanFactory.createBeanInstance()方法实例化Bean
                                          3、调用AbstractAutowireCapableBeanFactory.populateBean()方法进行Bean的属性注入
                                          4、如果实现了各种aware接口,就调用响应的方法,比如BeanNameAware的setBeanName()方法,BeanClassLoaderAware的setBeanClassLoader()方法,BeanFactoryAware的setBeanFactory()方法等
                                          5、执行BeanPostProcessor的postProcessorsBeforeInitialization()方法,前处理
                                          6、执行InitialzingBean.afterPropertiesSet()或者自定义的初始化方法
                                          7、执行BeanPostProcessor的postProcessorsAfterInitializatio()方法,后处理
                                          8、使用Bean
                                          9、关闭或停止容器,销毁Bean,如果实现了DisposableBean,就调用destroy()方法进行销毁时的处理
                                          可算是完了,睡觉!!



                                          ocep()(stProcessBeanFactoryssBeanFactory()

                                          文章转载自Java Miraculous,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                          评论