Spring5源码 - 07 Spring Bean 生命周期流程 源码解读02

简介: Spring5源码 - 07 Spring Bean 生命周期流程 源码解读02

20200914143739548.png

Pre


Spring5源码 - 06 Spring Bean 生命周期流程 概述 01

接上文


通俗流程

下面说个比较常见的主干流程


实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够使用,因为连最基本的属性都没有设置,可以理解为

连Autowired注解都是没有解析的;

填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;

如果Bean实现了BeanNameAware接口,则调用setBeanName方法;

如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;

如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;

调用BeanPostProcessor的postProcessBeforeInitialization方法;

如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;

如果Bean定义了init-method方法,则调用Bean的init-method方法;

调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的

上下文中,直到被销毁;

如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method

声明了销毁方法也会被调用。


finishBeanFactoryInitialization

完成Bean的初始化

/**
   * Finish the initialization of this context's bean factory,
   * initializing all remaining singleton beans.
   */
  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // bean工厂创建类型转化器  Convert
    /**
     * public class String2DateConversionService implements Converter<String,Date> {
      public Date convert(String source) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          try {
            return sdf.parse(source);
          } catch (ParseException e) {
          return null;
        }
      }
     }
     @Bean
     public ConversionServiceFactoryBean conversionService() {
      ConversionServiceFactoryBean factoryBean = new ConversionServiceFactoryBean();
      Set<Converter> converterSet = new HashSet<Converter>();
      converterSet.add(new String2DateConversionService());
      factoryBean.setConverters(converterSet);
      return factoryBean;
     }
     ConversionServiceFactoryBean conversionServiceFactoryBean = (ConversionServiceFactoryBean) ctx.getBean(ConversionServiceFactoryBean.class);
     conversionServiceFactoryBean.getObject().convert("2019-06-03 12:00:00",Date.class)
     */
    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));
    }
    /**
     * public class MainConfig implements EmbeddedValueResolverAware{
     *
     *     public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.jdbcUrl = resolver.resolveStringValue("${ds.jdbcUrl}");
        this.classDriver = resolver.resolveStringValue("${ds.classDriver}");
          }
     }
     */
    if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // 处理aspectj
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    //冻结所有的 bean 定义 , 说明注册的 bean 定义将不被修改或任何进一步的处理
    beanFactory.freezeConfiguration();
    //实例化剩余的单实例bean
    beanFactory.preInstantiateSingletons();
  }


继续

beanFactory.preInstantiateSingletons();
@Override
  public void preInstantiateSingletons() throws BeansException {
    if (logger.isDebugEnabled()) {
      logger.debug("Pre-instantiating singletons in " + this);
    }
    //获取我们容器中所有bean定义的名称
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    //循环我们所有的bean定义名称
    for (String beanName : beanNames) {
      //合并我们的bean定义
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      /**
       * 根据bean定义判断是不是抽象的&& 不是单例的 &&不是懒加载的
       */
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        //是不是工厂bean
        if (isFactoryBean(beanName)) {
          //是的话 给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());
            }
            //调用真正的getBean的流程
            if (isEagerInit) {
              getBean(beanName);
            }
          }
        }
        else {//非工厂Bean 就是普通的bean
          getBean(beanName);
        }
      }
    }
    //或有的bean的名称 ...........到这里所有的单实例的bean已经记载到单实例bean到缓存中
    for (String beanName : beanNames) {
      //从单例缓存池中获取所有的对象
      Object singletonInstance = getSingleton(beanName);
      //判断当前的bean是否实现了SmartInitializingSingleton接口
      if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            smartSingleton.afterSingletonsInstantiated();
            return null;
          }, getAccessControlContext());
        }
        else {
          //触发实例化之后的方法afterSingletonsInstantiated
          smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
  }

重点方法肯定是 getBean(beanName);


20200924113823114.png


20200924232522364.png


相关文章
|
2天前
|
Java Spring 容器
深入理解Spring Boot启动流程及其实战应用
【5月更文挑战第9天】本文详细解析了Spring Boot启动流程的概念和关键步骤,并结合实战示例,展示了如何在实际开发中运用这些知识。
11 2
|
3天前
|
存储 前端开发 Java
Spring Boot自动装配的源码学习
【4月更文挑战第8天】Spring Boot自动装配是其核心机制之一,其设计目标是在应用程序启动时,自动配置所需的各种组件,使得应用程序的开发和部署变得更加简单和高效。下面是关于Spring Boot自动装配的源码学习知识点及实战。
12 1
|
4天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
45 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
11天前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
19 1
|
11天前
|
设计模式 安全 Java
【初学者慎入】Spring源码中的16种设计模式实现
以上是威哥给大家整理了16种常见的设计模式在 Spring 源码中的运用,学习 Spring 源码成为了 Java 程序员的标配,你还知道Spring 中哪些源码中运用了设计模式,欢迎留言与威哥交流。
|
13天前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
31 2
|
16天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
53 0
|
2月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
137 0
|
1月前
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
43 2