Spring学习笔记之bean生命周期

Spring学习笔记之Bean生命周期

什么是Bean生命周期

在Spring容器中,当我们需要获取一个Bean实例时,会经历一系列的过程,包括BeanDefinition解析、Bean实例化、属性注入和初始化等操作,最终才能得到我们所需要的Bean实例。这整个过程就称之为Bean生命周期。

Bean生命周期可以分为以下几个阶段:

  1. 实例化:根据BeanDefinition创建Bean实例。
  2. 属性注入:对Bean实例进行属性注入。
  3. 初始化:执行各种初始化操作,例如Bean对象实现的InitializingBean接口、@PostConstruct注解等都可以在这阶段被执行。
  4. 使用:Bean实例被使用。
  5. 销毁:当容器被关闭时,销毁Bean实例。

Bean实例化阶段

BeanDefinition解析

在Spring容器启动时,它会读取配置文件,并将配置文件中定义的BeanDefinition解析为真正的Java对象。例如,我们在配置文件中通过<bean>标签定义了一个名为userService的Bean:

<bean id="userService" class="com.example.UserService">
    <property name="userDao" ref="userDao" />
</bean>

在解析过程中,会创建一个org.springframework.beans.factory.support.DefaultListableBeanFactory对象,然后再通过registerBeanDefinition方法将定义好的Bean注册到BeanFactory当中。

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(UserService.class)
        .addPropertyValue("userDao", userDao())
        .getBeanDefinition();
beanFactory.registerBeanDefinition("userService", beanDefinition);

Bean实例化

一旦BeanDefinition被注册成功,Spring容器就会通过反射创建出相应的Bean实例。它会调用构造函数实例化Bean对象,并在实例化时进行依赖注入。

InstantiationAwareBeanPostProcessor -> postProcessBeforeInstantiation
    -> 构造函数实例化Bean对象
InstantiationAwareBeanPostProcessor -> postProcessAfterInstantiation

在无参构造函数被调用之后,会为Bean的成员变量进行依赖注入操作。例如,我们在上面的XML中定义了userService依赖注入了userDao,则Spring容器会在实例化userService时自动注入相应的UserDao对象。

Bean实例化示例

我们通过以下的示例,来看看Spring创建Bean实例的过程:

@Component
public class MyBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("MyBean.setBeanName " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("MyBean.setBeanFactory " + beanFactory);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyBean.afterPropertiesSet");
    }

    public String hello() {
        return "Hello, " + name + "!";
    }

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

    @Override
    public void destroy() throws Exception {
        System.out.println("MyBean.destroy");
    }
}

在这个示例中,我们定义了一个名为MyBean的Bean。它实现了多个Spring生命周期接口,其中BeanNameAwareBeanFactoryAware用于获取Bean的名称和工厂,而InitializingBeanDisposableBean则用于Bean的初始化和销毁。

<bean id="myBean" class="com.example.MyBean">
    <property name="name" value="world"/>
</bean>

在XML中,我们定义了一个名为myBean的Bean,并注入了一个名为name的属性。

我们执行以下代码,来演示Spring容器创建MyBean实例的过程:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
System.out.println(myBean.hello());
context.close();

通过运行这个程序,我们会发现控制台上依次出现了以下输出:

MyBean.setBeanName myBean
MyBean.setBeanFactory org.springframework.context.annotation.AnnotationConfigApplicationContext@5a39699c: startup date [Sun Oct 20 19:39:57 CST 2019]; root of context hierarchy
MyBean.afterPropertiesSet
Hello, world!
MyBean.preDestroy
MyBean.destroy

Bean初始化阶段

Bean初始化是指Spring容器在创建完Bean实例之后,会调用org.springframework.beans.factory.config.BeanPostProcessor接口实现类的回调方法,来完成Bean对象的初始化工作。

BeanPostProcessor

在这个阶段中,Spring会调用BeanPostProcessor接口实现类的两个回调方法:

BeanPostProcessor -> postProcessBeforeInitialization
    -> 执行各种初始化工作
BeanPostProcessor -> postProcessAfterInitialization

其中的postProcessbeforeInitializationpostProcessAfterInitialization方法,分别对应Bean实例化之后的初始化操作和Bean实例化完成之后的操作。

通常我们会使用@PostConstruct注解来标注Bean的初始化方法。这样当Spring容器进行初始化时,会自动调用这个方法。

@Component
public class MyBean {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @PostConstruct
    public void init() {
        System.out.println("MyBean.init");
    }

    public String hello() {
        return "Hello, " + name + "!";
    }
}

Bean初始化示例

我们通过以下的示例,来看看Spring初始化Bean的过程:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessAfterInitialization " + beanName);
        return bean;
    }
}

在这个示例中,我们定义了一个名为MyBeanPostProcessorBeanPostProcessor实现类。在初始化前和初始化后分别输出Bean的名称,以便我们更好地理解阶段。

我们执行以下代码,来演示Spring容器初始化MyBean实例的过程:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
System.out.println(myBean.hello());
context.close();

通过运行这个程序,我们会发现控制台上依次出现了以下输出:

MyBeanPostProcessor.postProcessBeforeInitialization myBean
MyBean.init
MyBeanPostProcessor.postProcessAfterInitialization myBean
Hello, world!

Bean销毁阶段

DisposableBean

在Bean销毁的阶段时,Spring容器会依次调用DisposableBean的回调方法destroy,用于执行Bean的清理工作。

DisposableBean -> destroy

与初始化阶段类似,我们还可以使用@PreDestroy注解来标注Bean的销毁方法。这样当Spring容器收到关闭的通知,会自动调用这个方法。

@Component
public class MyBean {

    @PreDestroy
    public void destroy() {
        System.out.println("MyBean.destroy");
    }
}

Bean销毁示例

我们通过以下的示例,来看看Spring销毁Bean的过程:

@Component
public class MyBean implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        System.out.println("MyBean.destroy");
    }
}

在这个示例中,我们定义了一个名为MyBean的Bean,实现了DisposableBean接口。

我们执行以下代码,来演示Spring容器销毁MyBean实例的过程:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
context.close();

通过运行这个程序,我们会发现控制台上依次出现了以下输出:

MyBean.destroy

总结

Bean生命周期是Spring容器的核心部分之一,它决定了一个Bean实例的创建、初始化和销毁的过程。通过本文的介绍,我们已经了解了Spring容器在创建和销毁Bean实例时的具体过程,同时也学习了如何通过Bean生命周期接口和注解来对Bean进行定制。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring学习笔记之bean生命周期 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • 关于SpringBoot创建存储令牌的媒介类和过滤器的问题

    Spring Boot是一个流行的Java框架,可以用于快速开发Web应用程序。在Web应用程序中,通常需要使用token进行身份验证和授权,因此创建和存储令牌是非常重要的。本文将介绍如何使用Spring Boot创建媒介类和过滤器来存储和验证token并解决与存储令牌有关的问题。 创建TokenStorage媒介类 TokenStorage是一个媒介类,用…

    Java 2023年5月19日
    00
  • 详解Spring Kafka中关于Kafka的配置参数

    下面我来详细讲解一下关于“详解Spring Kafka中关于Kafka的配置参数”的完整攻略。 1. Kafka中常用的配置参数 在使用Kafka时,可以通过配置不同的参数来更加灵活地自定义Kafka的行为。下面是Kafka中一些常用的配置参数: bootstrap.servers:Kafka集群的连接地址列表,指定了Kafka Broker的主机名和端口号…

    Java 2023年5月20日
    00
  • Spring+Http请求+HttpClient实现传参

    下面是详细讲解“Spring+Http请求+HttpClient实现传参”的完整攻略。 一、准备工作 首先,需要在项目中引入Spring和HttpClient的相关依赖。可以在pom.xml文件中添加以下依赖: <!– Spring –> <dependency> <groupId>org.springframewor…

    Java 2023年5月19日
    00
  • Java实现宠物商店管理系统

    Java实现宠物商店管理系统完整攻略 1. 需求分析 首先,我们需要明确商店管理系统所具备的功能,包括但不限于以下几个方面: 宠物信息管理 宠物类别管理 宠物销售管理 宠物库存管理 宠物订单管理 2. 系统设计 基于需求,我们可以设计出宠物商店管理系统的基本架构,其中包括以下几个模块: 宠物信息管理模块 宠物类别管理模块 宠物销售管理模块 宠物库存管理模块 …

    Java 2023年5月24日
    00
  • Mybatis-Plus BaseMapper的用法详解

    当使用Mybatis-Plus时,常需要对数据库进行增、删、改、查等操作。可以使用Mybatis-Plus提供的BaseMapper接口来快速实现这些操作,而不需要自己手动编写SQL语句。 1. BaseMapper概述 BaseMapper是Mybatis-Plus提供的基础Mapper接口。该接口提供了常见的数据库操作,开发人员可以直接继承或者注入该接口…

    Java 2023年5月20日
    00
  • Java求质数的几种常用算法分析

    针对“Java求质数的几种常用算法分析”,我们可以从以下几个方面进行讲解: 算法分析 方法1:暴力枚举 方法2:素数筛法 方法1:暴力枚举 这种算法比较简单,直接从1到n枚举每一个数字,然后依次验证数字是否为质数。具体实现如下: public static boolean isPrime(int n) { if (n <= 1) { return fa…

    Java 2023年5月19日
    00
  • 使用Spirng Boot Admin监控Spring Cloud应用项目

    下面是使用Spring Boot Admin监控Spring Cloud应用项目的完整攻略: 1. 安装和配置Spring Boot Admin 首先,需要在Spring Boot应用项目中添加相关依赖,以便于引入Spring Boot Admin。在pom.xml中加入以下内容: <dependency> <groupId>de.c…

    Java 2023年5月20日
    00
  • 分享令人目瞪口呆的 Java 代码技巧

    现在来详细讲解“分享令人目瞪口呆的 Java 代码技巧”的完整攻略。 1. 提升代码的可读性 首先,我们来谈论一下如何提升 Java 代码的可读性。 代码缩进 好的代码缩进是提升代码可读性的一种重要手段。一般来说,对于每个代码块内的语句,都应当向右缩进一个相等数量的空格,以示其属于该代码块的范畴。例如: if (condition) { // … } e…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部