• Ioc容器加载过程-bean生命周期源码解析


    Spring IOC容器的加载过程

    1、实例化容器:AnnotationConfigApplicationContext

    首先从这里出发:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

    创建 AnnotationConfigApplicationContext对象实例化bean工厂,走的是无参构造方法,而无参构造方法又会去调用父类的无参构造方法。为什么这里要实现的是DefaultListableBeanFactory()?因为这个类继承了最多的父类,包括BeanDefinitionRegistry,功能是最丰富的,比如注册bean定义的方法。所以实现了这个DefaultListableBeanFactory()后赋值给beanFactory,得到了bean工厂

    1. //根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
    2. public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    3. //调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
    4. //父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
    5. //本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefi
    6. nitionScanner scanner
    7. //scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
    8. this();
    9. //把传入的类进行注册,这里有两个情况,
    10. //传入传统的配置类
    11. //传入bean(虽然一般没有人会这么做
    12. //看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配
    13. 置类
    14. //但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
    15. register(annotatedClasses);
    16. //刷新
    17. refresh();
    18. }
    19. //this()执行的无参构造方法
    20. public AnnotationConfigApplicationContext() {
    21. /**
    22. * 初始化注解模式下的bean定义扫描器
    23. * 调用AnnotatedBeanDefinitionReader构造方法,传入的是this(AnnotationConfigApplicationContext)对象
    24. */
    25. this.reader = new AnnotatedBeanDefinitionReader(this);
    26. /**
    27. * 初始化我们的classPath类型的bean定义扫描器
    28. */
    29. this.scanner = new ClassPathBeanDefinitionScanner(this);
    30. }
    31. //父类具体执行的构造方法
    32. public GenericApplicationContext() {
    33. /**
    34. * 调用父类的构造函数,为ApplicationContext spring上下文对象初始beanFactory
    35. * 为啥是DefaultListableBeanFactory?我们去看BeanFactory接口的时候
    36. * 发DefaultListableBeanFactory是最底层的实现,功能是最全的
    37. */
    38. this.beanFactory = new DefaultListableBeanFactory();
    39. }

    接下来会去执行new  AnnotatedBeanDefinitionReader(this)(创建用去读取配置类的工具。);在执行这一句的时候会去注册一些创世纪的类例的bean定义如ConfigurationClassPostProcessor.class(在这个类中负责解析配置类,会解析加了@Configuration\@Component\@Import等注解)、AutowiredAnnotationBeanPostProcessor.class(这个类会去解析@Autowired)等处理器,这个只是注册这些类,真正去把类解析bean定义的是由他注册的后置处理器去完成的。

    接下来会去执行this.scanner = new ClassPathBeanDefinitionScanner(this);创建扫面读取到的配置类的工具。在这个扫描工具里面有个doScan(String basePackages)方法,提供一个手动传入扫描包进行扫描的支持。传入一个包路径,通过这个路径扫描到包里面的所有类。

    在构造方法跳出来之后会执行注册配置类到bean定义里面

     接着会执行refresh()方法

     refresh()方法

    invokeBeanFactoryPostProcessors(beanFactory);

    调用我们的bean工厂的后置处理器。因为之前已经注册了创世纪类ConfigurationClassPostProcessor.class,所以这里执行getBean()就会实例化注册了的创世纪的类(实现了postprocessor接口),这里调用这些实例化了的处理器就会去解析配置类、@CompenetScan、@Import等注解注册到bean定义里面。

    registerBeanPostProcessors(beanFactory);

    注册bean的后置处理器

    finishBeanFactoryInitialization(beanFactory);

    实例化剩余的单例bean。

    在这里面会执行getBean(),判断需要实例化的这个Bean定义是否符合生产标准、是不是factorybean。符合标准了才会执行getBean()。这时候会先去判断一级缓存是否有,如果拿到了直接返回,如果没有拿到就会标记为isInCreation正在创建,去执行creatBean()

    creatBean()中会执行第一个bean后置处理器,这里可以阻止bean的创建交由用户自己创建。

    接着就来到了doCreatBean(),进行实例化、填充属性、初始化,最终把bean放入一级缓存。

    springBean生命周期

    阶段1:处理名字,检查缓存,因为spring是支持别名系统,也就是一个bean可以起一个小名,将来根据小名也能找到这个bean,所以在这一步是将这个别名翻译成真正的名字。是为了实现单例bean,检查缓存单例池中是否已经存在,如果有就直接拿不再创建。

    阶段2:检查父工厂,针对的是beanFactory有一个父子继承关系,如果子工厂没有这个Bean就会去父工厂中走getBean

    阶段3:检查bean的dependsOn,应该先创建dependon的bean,保证先后顺序

    阶段4:按Scope创建bean

    • 创建singleton
    • 创建prototype:多例bean
    • 创建其他scope

    阶段5:

    • 创建bean实例
    • 依赖注入
    • 初始化:调用各种初始化方法。
    • 登记可销毁bean

    阶段6:类型转换:根据requiredType进行类型转换。

    阶段7:销毁阶段5登记的可销毁bean

     

  • 相关阅读:
    iMazing最新版2.16.1Apple设备管理器功能介绍
    在页面中使用store中的成员
    【Python零基础入门篇 · 4】:字符串的运算符、下标和切片
    Worthington细胞色素 C 消化研究丨羧肽酶 B方案
    Java最长回文串leetcode
    机器学习-无监督学习之聚类
    Vue2 | Vant uploader实现上传文件和图片
    linux正则使用
    习题:选择结构(二)
    mysql- 数据库的备份与还原
  • 原文地址:https://blog.csdn.net/PnJgHT/article/details/127026528