spring bean 生命周期

bean 的创建过程

  1. 读取配置文件,解析配置文件,得到 bean 定义集合

    1. 每个 bean 的配置都对应一个 BeanDefinition 对象,统一放在容器的 beanFactory.beanDefinitionMap 中,是一个 map
  2. bean 工厂后置处理器 BeanFactoryPostProcessor

    1. 与其说 bean 工厂后置处理器还不如说是 bean定义 后置处理器,因为这时可以修改 BeanDefinition
    2. 作用是可以修改 BeanDefinition 从而达到修改 bean 的目的
    3. 也可以往 beanDefinitionMap 增加一个 BeanDefinition ,可以达到不用显示配置 bean 的目的,动态配置 bean
    4. 如果单纯只是想增加一个 BeanDefinition,可以使用子接口 BeanDefinitionRegistryPostProcessor 来完成
    5. spring bean 的扩展点之一
  3. 创建对象

    1. 根据 BeanDefinition 反射创建 java 对象,此时还不是 bean,或者说还不是完整的 bean

    2. 创建方式有无参构造、有参构造、工厂方式。都是利用反射来创建对象

    3. 这个对象会先放入三级缓存,这里只是提一下,后面说 spring 怎么利用三级缓存来处理循环依赖

  4. 属性赋值

    1. 创建了对象,就该为属性赋值了,分为普通属性和引用了别的 bean 的属性
    2. 普通属性用 @Value。引用其他 bean 用 @Autowired 或 @Resource 完成赋值,DI 的体现
    3. 引用其他 bean 的时候,先到一级缓存中找,如果没有再到二级缓存中找,然后是三级缓存,如果都没有,先创建其他 bean
    4. 如果三级找到了其他 bean,把其他 bean 放入二级缓存,移除三级缓存
    5. 这个流程先假设没有循环依赖,不然就要先说循环依赖了
  5. Aware 回调方法

    1. bean 通过实现一些 Aware 接口,复写接口方法,创建 bean 的时候 spring 会执行这些方法,可以再次完善 bean 的配置
    2. BeanFactoryAware 能让当前 bean 拿到 BeanFactory 对象,这个对象包罗万象
    3. ApplicationContextAware 能让 当前 bean 拿到 ApplicationContext 应用上下文对象,比 BeanFactory 的信息更多
  6. bean 后置处理器的 before

    1. bean 实现 BeanPostProcessor 接口,复写 postProcessBeforeInitialization 方法,创建 bean 的时候 spring 会执行这个方法,再次完善 bean 的配置
    2. BeanFactoryPostProcessor 是修改 BeanDefinition ,BeanPostProcessor 可以修改 bean
    3. spring bean 的总要扩展点之一
  7. initializingBean 接口的方法

    1. bean 实现 initializingBean 接口,复写 afterPropertiesSet 方法,创建 bean 的时候 spring 会执行这个方法,再次完善 bean 的配置
  8. 自定义的 init 方法

    1. 创建 bean 的时候 spring 会自动执行指定的 init 方法,再次完善 bean 的配置
  9. bean后置处理器的 after 方法

    1. BeanPostProcessor 有两个方法,一个是后置,一个是前置
    2. 这里是最后节点所以这个方法在扩展时用的最多
  10. 配置自定义的销毁方法

  11. 此时 bean 就完整了,放到 单例池,并删除二三级缓存

简言之就是先创建 bean 定义对象,然后根据定义创建 java 对象,属性赋值,然后根据各种回调或接口完善对象,使其成为完整的 bean,最后放入单例池

@Component(value = "testBean") // bean 定义:id = testBean,class = com.yunxi.dg.base.center.trade.demand.engine.statemachine.Test
@Scope(value = "singleton") // bean 定义:scope = singleton
@Lazy(value = false) // bean 定义:不延迟加载
public class Test implements ApplicationContextAware, BeanNameAware, InitializingBean, BeanFactoryPostProcessor, BeanPostProcessor {

    private String username;
    private int age;
    private String sex;
    private String addr;

    /**
     * 虽然类上定义的作用域是单例,但是这里通过修改 beanDefinition 使作用域变为了原型
     * 这个方法触发的时机是所有 BeanDefinition 都已经收集完成,将要进行 bean 初始化的时候
     * @param configurableListableBeanFactory 这是 BeanFactory 的子接口,为了安全不能拿到全部的 BeanDefinition,只能通过条件获取指定的 BeanDefinition
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor,兵工厂后置处理器");
        // 这里不止能获取当前 bean 的 BeanDefinition,可以修改任意 BeanDefinitio
        configurableListableBeanFactory.getBeanDefinition("testBean").setScope("property");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware回调");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("BeanNameAware回调");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 修改 bean 的 username
        if(bean instanceof Test){
            System.out.println("BeanPostProcessor.before");
            Test testBean = (Test) bean;
        	testBean.username = "张三";
            return testBean;
        }
        return bean;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean");
        this.sex = "男";
    }

    @PostConstruct
    private void init(){
        System.out.println("自定义init方法");
        this.addr = "四川成都成华区东丽街";
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Test){
             System.out.println("BeanPostProcessor.after");
            // 修改 bean 的 age
           	Test testBean = (Test) bean;
            testBean.age = 18;
            return testBean;
        }
        return bean;
    }

}

bean 的生命周期

  1. 实例化(Instantiation)
    • 当 Spring 容器接收到对 Bean 的请求时,首先会进行 Bean 的实例化。这个阶段的实质是通过构造函数或者工厂方法创建 Bean 的实例。
  2. 依赖注入(Dependency Injection)
    • 在实例化后,Spring 开始进行依赖注入。这包括设置 Bean 的属性值、调用 Bean 的 setters 方法来传递依赖,以及通过构造函数注入或者字段注入来完成 Bean 的配置。
  3. 初始化前回调(Initialization Callbacks)
    • 在依赖注入完成后,Spring 会调用 Bean 实现的 InitializingBean 接口的 afterPropertiesSet() 方法,或者使用 @PostConstruct 注解标注的方法,来执行一些初始化操作。
  4. 自定义初始化方法(Custom Init Method)
    • 如果 Bean 配置中指定了自定义的初始化方法(通过 XML 配置或者 @Bean(initMethod="customInit")),Spring 会调用这个方法来执行额外的初始化逻辑。
  5. Bean 可用(Bean is ready for use)
    • 此时,Bean 已经被完全初始化,可以被应用程序使用。
  6. 销毁前回调(Destruction Callbacks)
    • 当容器关闭时,Spring 会调用实现 DisposableBean 接口的 destroy() 方法,或者使用 @PreDestroy 注解标注的方法,来执行 Bean 的清理工作和资源释放。
  7. 自定义销毁方法(Custom Destroy Method)
    • 如果 Bean 配置中指定了自定义的销毁方法(通过 XML 配置或者 @Bean(destroyMethod="customDestroy")),Spring 会在容器关闭时调用这个方法来执行额外的清理逻辑。
  8. 销毁(Destruction)
    • 最后,Spring 容器销毁 Bean 的实例,释放它占用的资源。
posted @ 2024-06-29 18:05  CyrusHuang  阅读(2)  评论(0编辑  收藏  举报