Spring与bean有关的生命周期示例详解

 更新时间:2020年07月27日 08:35:17   作者:eaglelihh  
这篇文章主要给大家介绍了关于Spring与bean有关的生命周期的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

记得以前的时候,每次提起Spring中的bean相关的生命周期时,内心都无比的恐惧,因为好像有很多,自己又理不清楚:什么beanFactory啊,aware接口啊,beanPostProcessor啊,afterPropertiesSet啊,initMethod啊等等。

今天终于理清这些关系了,并且又新增了对postConstruct和lifecycle的理解。

执行顺序

- 首先是 BeanFactoryPostProcessor,它是针对所有bean的definition的,只执行一次

下面是针对每个bean的初始

  • - 实现了一系列aware接口的,比如BeanNameAware,ApplicationContextAware,调用其set方法
  • - 执行BeanPostProcessor的postProcessBeforeInitialization方法
  • - 带有@PostConstruct注解的方法
  • - 实现InitializingBean接口的afterPropertiesSet方法
  • - 指定的initMethod方法
  • - 执行BeanPostProcessor的postProcessAfterInitialization方法
  • - 实现了SmartLifecycle接口的start方法(实现Lifecycle接口的不会自动调用,需要显式的调用start方法)

下面是针对每个bean的销毁

  • - 实现了SmartLifecycle接口的stop方法(实现Lifecycle接口的不会自动调用,需要显式的调用stop方法)
  • - 带有@PreDestroy注解的方法
  • - 实现DisposableBean接口的destroy方法
  • - 指定的destroyMethod方法

目前就想到这么多了,其他的麻烦在评论区留言呀~

代码实例

bean实体类

/**
 * @date: 2020-07-22
 * 
 * 一个简单的枚举类 
 */
public enum BeanType {
  NORMAL, LIFECYCLE, SMART_LIFECYCLE;
}

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
 * @author: lihui
 * @date: 2020-07-22
 * 一个简单的bean
 */
@Slf4j
public class NormalBean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {
  private BeanType beanType;

  public NormalBean() {
    this(BeanType.NORMAL);
  }

  public NormalBean(BeanType beanType) {
    this.beanType = beanType;
  }

  @PostConstruct
  public void postConstruct() {
    log.info("{}, postConstruct", beanType);
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    log.info("{}, afterPropertiesSet", beanType);
  }

  public void initMethod() {
    log.info("{}, initMethod", beanType);
  }

  @PreDestroy
  public void preDestroy() {
    log.info("{}, preDestroy", beanType);
  }

  @Override
  public void destroy() throws Exception {
    log.info("{}, destroy", beanType);
  }

  public void destroyMethod() {
    log.info("{}, destroyMethod", beanType);
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    log.info("setApplicationContext, applicationContext : {}", applicationContext);
  }

  @Override
  public void setBeanName(String name) {
    log.info("setBeanName, bean name : {}", name);
  }
}

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.Lifecycle;
/**
 * @author: lihui
 * @date: 2020-07-22
 * 实现了Lifecycle的一个bean
 */
@Slf4j
public class LifecycleBean extends NormalBean implements Lifecycle {
  private volatile boolean running = false;

  public LifecycleBean() {
    super(BeanType.LIFECYCLE);
  }

  @Override
  public void start() {
    log.info("start");
    running = true;
  }

  @Override
  public void stop() {
    log.info("stop");
    running = false;
  }

  @Override
  public boolean isRunning() {
    return running;
  }
}

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.SmartLifecycle;
/**
 * @author: lihui
 * @date: 2020-07-22
 * 实现了SmartLifecycle的一个bean
 */
@Slf4j
public class SmartLifecycleBean extends NormalBean implements SmartLifecycle {
  private volatile boolean running = false;

  public SmartLifecycleBean() {
    super(BeanType.SMART_LIFECYCLE);
  }

  @Override
  public void start() {
    log.info("start");
    running = true;
  }

  @Override
  public void stop() {
    log.info("stop");
    running = false;
  }

  @Override
  public boolean isRunning() {
    return running;
  }
}

配置类

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
 * @author: lihui
 * @date: 2020-07-25
 */
@Slf4j
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    log.info("postProcessBeanFactory, beanFactory:{}", beanFactory);
  }
}

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * @author: lihui
 * @date: 2020-07-25
 */
@Slf4j
public class MyBeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    log.info("postProcessBeforeInitialization, bean:{}", beanName);
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    log.info("postProcessAfterInitialization, bean:{}", beanName);
    return bean;
  }
}

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author: lihui
 * @date: 2020-07-22
 */
@Configuration
@Slf4j
public class Config {

  @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
  public NormalBean normalBean() {
    return new NormalBean();
  }

  @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
  public LifecycleBean lifecycleBean() {
    return new LifecycleBean();
  }

  @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
  public SmartLifecycle smartLifecycle() {
    return new SmartLifecycleBean();
  }

  @Bean
  public static MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {
    return new MyBeanFactoryPostProcessor();
  }

  @Bean
  public static MyBeanPostProcessor myBeanPostProcessor() {
    return new MyBeanPostProcessor();
  }
}

Main类

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author: lihui
 * @date: 2020-07-22
 */
@Slf4j
public class Main {
  public static void main(String[] args) throws InterruptedException {
    ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
    ctx.registerShutdownHook();
    Thread.sleep(5000);
    log.info("line ----------------------------- line");
    ctx.start();
    ctx.stop();
    log.info("line ----------------------------- line");
  }
}

结果说明

结果正如前面所说的执行顺序一致,主要注意的就是Lifecycle接口和SmartLifecycle接口,只有实现了SmartLifecycle接口的bean在初始化时才会被自动调用,而实现了Lifecycle接口的除非显式调用start和stop方法才会被调用。

总结

到此这篇关于Spring与bean有关的生命周期的文章就介绍到这了,更多相关Spring与bean生命周期内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8并行流中自定义线程池操作示例

    Java8并行流中自定义线程池操作示例

    这篇文章主要介绍了Java8并行流中自定义线程池操作,结合实例形式分析了并行流的相关概念、定义及自定义线程池的相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • 使用idea生成springboot程序的docker镜像的操作指南

    使用idea生成springboot程序的docker镜像的操作指南

    这篇文章给大家详细的介绍了使用idea生成springboot程序的docker镜像的操作指南,文中通过图文结合给大家讲解的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2023-12-12
  • SpringBoot动态表操作服务的实现代码

    SpringBoot动态表操作服务的实现代码

    在现代的应用开发中,尤其是在数据库设计不断变化的情况下,动态操作数据库表格成为了不可或缺的一部分,在本篇文章中,我们将以一个典型的动态表操作服务为例,详细介绍如何在 Spring Boot 中使用 JdbcTemplate 实现动态表管理,需要的朋友可以参考下
    2025-01-01
  • SpringBoot向resources下写文件的两种方式

    SpringBoot向resources下写文件的两种方式

    这篇文章给大家分享了两种SpringBoot向resources下写文件的方式,每种方式都有详细的代码示例,对我们的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-08-08
  • SpringBoot基于SpringSecurity表单登录和权限验证的示例

    SpringBoot基于SpringSecurity表单登录和权限验证的示例

    这篇文章主要介绍了SpringBoot基于SpringSecurity表单登录和权限验证的示例。文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • IntelliJ IDEA Tomcat控制台中文乱码问题的四种解决方案

    IntelliJ IDEA Tomcat控制台中文乱码问题的四种解决方案

    这篇文章主要给大家分享了4种方法完美解决IntelliJ IDEA Tomcat控制台中文乱码问题,文中有详细的图文介绍,对我们的学习或工作有一定的帮助,需要的朋友可以参考下
    2023-08-08
  • SpringBoot集成Redis实现消息队列的方法

    SpringBoot集成Redis实现消息队列的方法

    这篇文章主要介绍了SpringBoot集成Redis实现消息队列的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 浅析Mybatis 在CS程序中的应用

    浅析Mybatis 在CS程序中的应用

    如果是自己用的Mybatis,不需要考虑对配置文件加密,如果不是,那就需要考虑加密,这篇文章主要讲如何配置CS的Mybatis
    2013-07-07
  • Spring Boot入门(web+freemarker)

    Spring Boot入门(web+freemarker)

    这篇文章主要介绍了Spring Boot入门(web+freemarker)的相关资料,需要的朋友可以参考下
    2017-06-06
  • SpringBoot自定义bean绑定实现

    SpringBoot自定义bean绑定实现

    这篇文章主要介绍了SpringBoot自定义bean绑定,最常见的配置绑定的场景,是在自定义的bean中通过@Value注解将某个属性和对应的配置绑定
    2022-10-10

最新评论