手撕spring04源码(A依赖B)

概述

本章节优化上一章节通过构造方法实例化对象属性填充问题的痛点,并解决A bean依赖B bean的问题

整体设计

知识点补充

spring生命周期

在Spring中,Bean的生命周期包括实例化、初始化和销毁三个阶段。下面是对每个阶段的解释:

  1. 实例化(Instantiation):在这个阶段,Spring容器会根据配置信息或注解创建Bean的实例。实例化可以通过构造函数实现,也可以通过工厂方法或者工厂Bean来实现。
  2. 初始化(Initialization):在实例化后,Spring会对Bean进行初始化。这个阶段包括以下几个步骤:
    a.属性注入:Spring会将配置的属性值或引用注入到Bean的对应属性中。
    b.实现Aware接口:如果Bean实现了Aware接口,Spring会调用相应的方法,将容器相关的信息注入到Bean中。
    c.自定义初始化方法:如果Bean定义了自定义的初始化方法(通过配置或注解),Spring会在这个阶段调用该方法。
  3. 销毁(Destruction):当容器关闭或者销毁Bean时,会触发销毁阶段。这个阶段包括以下几个步骤:
    a. 实现DisposableBean接口:如果Bean实现了DisposableBean接口,Spring会调用其destroy()方法进行销毁操作。
    b. 自定义销毁方法:如果Bean定义了自定义的销毁方法(通过配置或注解),Spring会在这个阶段调用该方法。

类图

时序图

手撕spring04源码(A依赖B)_第1张图片

  1. 初始化 BeanFactory(DefaultListableBeanFactory)
  2. 注册userDao bean(相关类信息),将注册的类信息放入DefaultListableBeanFactory的map中
  3. 注册userService bean,将注册的类信息(类对象,属性:依赖B)放入DefaultListableBeanFactory的map中
  4. 通过bean工厂获取类的对象
    调用继承了抽象类AbstractAutowireCapableBeanFactory继承的AbstractBeanFactory的getBean方法
    从抽象类AbstractBeanFactory继承的DefaultSingletonBeanRegistry类的getSingleton方法获取类信息
  5. 存在的话返回
  6. 不存在的话从AbstractBeanFactory的子类beanFactory(DefaultListableBeanFactory)中获取bean定义
  7. 从子类BeanFactory(AbstractAutowireCapableBeanFactory)中创建对象
    获取Class类信息(传入无参的构造方法)
    指定Cglib的子类CglibSubclassingInstantiationStrategy通过cglib实例化并返回Object
    将实例化后的对象放到继承的抽象类AbstractBeanFactory继承的DefaultSingletonBeanRegistry类中的map中
    返回实例化后的bean
  8. 返回初始化的bean对象,实例化填充属性
    /**
     * Bean 属性填充
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {

                String name = propertyValue.getName();
                Object value = propertyValue.getValue();

                if (value instanceof BeanReference) {
                    // A 依赖 B,获取 B 的实例化
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getBeanName());
                }
                // 通过反射属性填充
                BeanUtil.setFieldValue(bean, name, value);
            }
        } catch (Exception e) {
            throw new BeansException("Error setting property values:" + beanName);
        }
    }
	从beanDefinition中获取属性信息并遍历,对值为BeanReference对象的,去spring容器中获取对象,过程如上述
	对获取的属性名和值通过cn.hutool.core.bean的beanUtil进行反射设置
  1. 继承的抽象类AbstractBeanFactory继承的DefaultSingletonBeanRegistry类中的map将实例化后的对象放入。统一维护bean对象
  2. 返回bean

小结

A 依赖 B问题:通过继续在DefaultSingletonBeanRegistry中map中获取,不存在的话beanFactory去初始化、实例化该对象并返回给依赖的对象。

问题

A 依赖 B,B 依赖 A这种循环依赖怎么解决?
个人想法:
bean注册的时候,就创建对应的代理Bean,当需要依赖的时候放入代理bean,并去初始化、实例化代理bean

你可能感兴趣的:(Spring源码,spring,java)