详解Bean的生命周期+自编码验证

1. Bean的生命周期完整图示

Bean的生命周期包括 4 个阶段:实例化Instantiation 、属性赋值Populate 、初始化Initalization 、销毁Destruction。其中这 4 个阶段又进一步细分,下图列举了完整的Bean创建至销毁的流程:
在这里插入图片描述

2. 编码验证

2.1 Bean的实例化与属性赋值

(1)定义Person类,类中包含有参构造方法和name属性的setter方法,用于验证Bean的实例化与属性赋值。

/**
 * @author name:    silk
 * @version 1.0
 * @description: Bean
 * @date 2024/3/29 20:30
 */
public class Person {

    private String name;

    public Person() {
        System.err.println("Person's constructor is called...");
    }

    /***
     * @description: 在Bean的生命周期中,首先进行实例化,再属性赋值
     * @author name silk
     * @date: 2024/3/29 20:47
     */
    public void setName(String name) {
        System.err.println("setName method is called...");
        this.name = name;
    }
}

(2)XML配置Bean的定义

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="com.wyw.learn.beanlife.Person">
        <property name="name" value="xiaoWang"/>
    </bean>
</beans>

(3)DemoApplication启动类

package com.wyw.learn.beanlife;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author name:    silk
 * @version 1.0
 * @description: 主程序
 * @date 2024/3/29 20:34
 */
@ComponentScan("com.wyw.learn")
public class DemoApplication {
    public static void main(String[] args) {
        System.err.println("======Spring容器初始化开始======");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeApplicationContext.xml");
        System.err.println("======Spring容器初始化完成======");
        System.err.println("--------------------------------------");
        System.err.println("=======Spring容器准备关闭=======");
        context.close();
        System.err.println("========Spring容器已关闭========");
    }

}

(4)测试结果
在这里插入图片描述

2.2 Bean的初始化

Bean的初始化一般通过以下 4 种方式:

  • 实现BeanPostProcessor接口,重写postProcessBeforeInitialization()方法;
  • 使用@PostConstruct注解标识某初始化方法;
  • 实现InitializingBean接口,重写afterPropertiesSet()方法;
  • 在XML中配置了init-method属性,则会自动调用其配置的初始化方法;

接下来,我们探索一下这几种初始化方式的执行顺序:
(1)Person类

/**
 * @author name:    silk
 * @version 1.0
 * @description: Bean
 * @date 2024/3/29 20:30
 */
@Component
public class Person implements InitializingBean, DisposableBean {

    private String name;

    public Person() {
        System.err.println("Person's constructor is called...");
    }

    /***
     * @description: 在Bean的生命周期中,首先进行实例化,再属性赋值,然后执行init-method标记的方法
     * @author name silk
     * @date: 2024/3/29 20:47
     */
    public void setName(String name) {
        System.err.println("setName method is called...");
        this.name = name;
    }

    @PostConstruct
    public void postConstruct() {
        System.err.println("@PostConstruct...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.err.println("InitializingBean#afterPropertiesSet...");
    }

    /***
     * @description: init-method
     * @author name silk
     * @date: 2024/3/29 20:33
     */
    public void initMethod() {
        System.err.println("init-method...");
    }

    @Override
    public String toString() {
        return "Person{" + "name=" + name + '}';
    }
}

(2)PersonBeanPostProcessor类,实现BeanPostProcessor接口

package com.wyw.learn.beanlife;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author name:    silk
 * @version 1.0
 * @description: TODO
 * @date 2024/3/29 21:08
 */
@Component
public class PersonBeanPostProcessor implements BeanPostProcessor {

	// 常规情况这个构造器不写,这里主要为了证明前面的几条打印信息属于该PersonBeanPostProcessor
    public PersonBeanPostProcessor() {
        System.err.println("PersonBeanPostProcessor's constructor is called...");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.err.println("postProcessBeforeInitialization");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.err.println("postProcessAfterInitialization");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

(3)PersonConfig类,代替XML文件创建Person对应的Bean对象

package com.wyw.learn.beanlife;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author name:    silk
 * @version 1.0
 * @description: Person配置类
 * @date 2024/3/29 20:59
 */
@Configuration
public class PersonConfig {

    /***
     * @description: @Bean注解中有属性:initMethod和destroyMethod,这两个属性的作用与XML配置中的init-method和destroy-method相同
     * @author name silk
     * @date: 2024/3/29 21:01
     */
    @Bean(initMethod = "initMethod")
    public Person person() {
        return new Person();
    }

}

(4)DemoApplication启动类

package com.wyw.learn.beanlife;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author name:    silk
 * @version 1.0
 * @description: 主程序
 * @date 2024/3/29 20:34
 */
@ComponentScan("com.wyw.learn")
public class DemoApplication {
    public static void main(String[] args) {
        System.err.println("======Spring容器初始化开始======");
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.wyw.learn.beanlife");
        System.err.println("======Spring容器初始化完成======");
        System.err.println("--------------------------------------");
        System.err.println("=======Spring容器准备关闭=======");
        context.close();
        System.err.println("========Spring容器已关闭========");
    }

}

(5)测试结果
在这里插入图片描述

2.3 Bean的销毁

(1)Person类,新增与Bean销毁相关的方法

package com.wyw.learn.beanlife;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author name:    silk
 * @version 1.0
 * @description: Bean
 * @date 2024/3/29 20:30
 */
@Component
public class Person implements InitializingBean, DisposableBean {

    private String name;

    public Person() {
        System.err.println("Person's constructor is called...");
    }

    /***
     * @description: 在Bean的生命周期中,首先进行实例化,再属性赋值,然后执行init-method标记的方法
     * @author name silk
     * @date: 2024/3/29 20:47
     */
    public void setName(String name) {
        System.err.println("setName method is called...");
        this.name = name;
    }

    @PostConstruct
    public void postConstruct() {
        System.err.println("@PostConstruct...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.err.println("InitializingBean#afterPropertiesSet...");
    }

    /***
     * @description: init-method
     * @author name silk
     * @date: 2024/3/29 20:33
     */
    public void initMethod() {
        System.err.println("init-method...");
    }

    @PreDestroy
    public void preDestroy() {
        System.err.println("@PreDestroy...");
    }

    @Override
    public void destroy() throws Exception {
        System.err.println("DisposableBean#destroy...");
    }

    /***
     * @description: destroy-method
     * @author name silk
     * @date: 2024/3/29 20:33
     */
    public void destroyMethod() {
        System.err.println("destroy-method...");
    }

    @Override
    public String toString() {
        return "Person{" + "name=" + name + '}';
    }

}

(2)PersonConfig类,@Bean注解中配置destory-method属性

package com.wyw.learn.beanlife;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author name:    silk
 * @version 1.0
 * @description: Person配置类
 * @date 2024/3/29 20:59
 */
@Configuration
public class PersonConfig {

    /***
     * @description: @Bean注解中也有属性:initMethod和destroyMethod,这两个属性的作用与XML配置中的init-method和destroy-method相同
     * @author name silk
     * @date: 2024/3/29 21:01
     */
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Person person() {
        return new Person();
    }

}

(3)PersonBeanPostProcessor类和主启动类DemoApplication类不变

(4)测试结果(展示了完整的从Bean的创建至销毁全过程信息)
在这里插入图片描述

最后,得出结论,Bean的初始化顺序为:BeanPostProcessor → @PostConstruct → InitializingBean → init-method;销毁顺序为:@PreDestroy → DisposableBean → destroy-method。

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值