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


相关文章
|
18天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
72 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
1月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
176 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
16天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
27 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
12天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
24 2
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
56 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
182 2
下一篇
无影云桌面