3

引言

Bean是Spring框架及其核心概念之一。 Bean 是由 Spring IoC 容器实例化、组装和管理的对象。

它和普通的 Java 对象的区别在于:它不是由开发人员自己 new 出来的,而是由容器负责创建的。IOC 容器管理Bean的对象的以下内容:1.管理Bean对象的生命周期,2.依赖注入(容器在启动时自动注入),3.作用域管理,4.生命周期回调。

生命周期是一个对象从创建到被销毁经历的整个过程,普通Java对象的生命周期是JVM分配内存,调用构造函数实例化对象,当该对象没有被引用后再由GC(Garbage Collection,垃圾收集)负责销毁并释放内存。而 Spring Bean 是由IOC容器负责创建和管理的对象,它的生命周期相比普通Java对象会更加复杂。

Spring Bean是什么?

我们来看下 Spring Framework 的官方文档:

Here’s a definition of beans in the Spring Framework documentation:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.

简而言之,bean 是由 Spring IoC 容器实例化、组装和管理的对象。

Spring Bean的生命周期

Spring Bean 的生命周期简单来说可以划分为五大阶段:实例化 -> 属性赋值 -> 初始化 -> 使用 -> 销毁。
image.png
由上图可出有参构造和无参构成的区别只在于有参构造不需要给属性赋值。
以下是一个简单的demo,用于演示Spring Bean的生命周期

package com.example.demo;

public class UserBean {
    private String name;
    private String sno;

    public UserBean() {
        System.out.println("无参构造实例化UserBean");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("UserBean-->设置属性name");
    }

    public void setSno(String sno) {
        this.sno = sno;
        System.out.println("UserBean-->设置属性sno");
    }

    void init() {
        System.out.println("UserBean执行初始化方法");
    }

    void destroy() {
        System.out.println("UserBean执行销毁方法");
    }
}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="userBean" class="com.example.demo.UserBean" init-method="init" destroy-method="destroy">
       <property name="name" value="zhangsan"></property>
        <property name="sno" value="000722"></property>
    </bean>
</beans>
package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserBeanTest {
    @Test
    void Test( ) {
        /*ClassPathXmlApplicationContext类根据userBean.xml的配置,当容器启动时
        实例化userBean
        设置属性值
        初始化*/
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
        System.out.println("获取userBean" + context.getBean("userBean"));

        /*获取到userBean后可根据业务逻辑使用*/
        System.out.println("使用userBean");

        /*销毁bean*/
        context.close();
    }
}

测试结果:
image.png

Spring Bean 生命周期扩展

image.png

BeanPostProcessor接口

BeanPostProcessor接口有两个方法分别是after和before, 他们可用于Bean初始化方法的前后。
image.png
image.png

Aware接口

Spring提供的一系列Aware接口实现类,用于让Bean获取到Spring容器中的其他对象。
image.png
实现类:

  • BeanFactoryAware:允许Bean获取到当前的BeanFactory,即Spring容器本身。
  • ApplicationContextAware:是BeanFactoryAware的扩展,允许Bean获取到ApplicationContext,从而能够访问Spring应用上下文的信息,比如环境属性、配置文件中的Bean等。
  • ResourceLoaderAware、MessageSourceAware等:提供了类似的功能,允许Bean获取到资源加载器、消息源等资源。

Aware接口的主要作用是提供了一种解耦的方式,让Bean能够访问到Spring容器的资源,而无需将这些资源作为Bean的依赖注入进来。

InitializingBean接口

InitializingBean接口定义了一个afterPropertiesSet方法,当Bean的所有属性被Spring容器设置之后,并且Bean被初始化之后(例如,通过XML配置中的<bean>标签的init-method属性指定的方法,或者通过@PostConstruct注解标记的方法),Spring容器会调用这个方法。
image.png
这提供了一种机制,允许开发者在Bean的初始化过程中执行自定义的代码,比如:

  • 检验属性值:确保Bean的配置正确,检验必要的属性已经设置等。
  • 初始化内部状态:比如创建资源,例如打开文件,建立数据库连接等
  • 执行自定义的启动逻辑:比如内部的定时器或线程。

DisposableBean接口

DisposableBean接口定义了一个destroy方法,当容器关闭时,Spring容器会调用这个方法。这提供了一种机制,允许开发者在Bean被销毁之前执行清理工作,比如释放资源、关闭文件等。与InitializingBean类似,虽然可以通过@PreDestroy注解来标记销毁方法,但DisposableBean接口提供了一种更为传统的、基于接口的方式来实现相同的功能。
image.png
并非所有的资源都会在对象不在使用时释放,比如关闭数据库连接或停止后台线程,仅靠GC(Garbage Collection,垃圾收集)是不够的。

扩展代码演示

BeanPostProcessor接口

package com.example.demo;

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

public class AllBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor实现类-->postProcessBeforeInitialization方法");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor实现类-->postProcessAfterInitialization方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

将该BeanPostProcessor的实现类AllBeanPostProcessor加入bean中。
image.png
运行结果:
image.png

Aware接口

UserBean实现ApplicationContextAware,重写其setApplicationContext方法后,UserBean变可以从容器中获取其他的Bean对象。
image.png
运行结果:
image.png

InitializingBean接口, DisposableBean接口demo 与上述类似。

总结

通过上述对Spring Bean的生命周期的了解,最后我们看一下spring容器启动后的全局生命周期:
image.png
通过这张图,我们可用了解到Bean 是如何由 Spring IoC 容器创建,实例化、组装和管理的对象了。
希望这篇文章能对您有所帮助!

参考文献

一文读懂Spring Boot 生命周期


吴季分
390 声望13 粉丝