Spring中Bean的生命周期

在这里插入图片描述

博主 默语带您 Go to New World.
个人主页—— 默语 的博客👦🏻 优秀内容
《java 面试题大全》
《java 专栏》
《idea技术专区》
《spring boot 技术专区》
《MyBatis从入门到精通》
《23种设计模式》
《经典算法学习》
《spring 学习》
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨


默语是谁?

大家好,我是 默语,别名默语博主,擅长的技术领域包括Java、运维和人工智能。我的技术背景扎实,涵盖了从后端开发到前端框架的各个方面,特别是在Java 性能优化、多线程编程、算法优化等领域有深厚造诣。

目前,我活跃在CSDN、掘金、阿里云和 51CTO等平台,全网拥有超过10万的粉丝,总阅读量超过1400 万。统一 IP 名称为 默语 或者 默语博主。我是 CSDN 博客专家、阿里云专家博主和掘金博客专家,曾获博客专家、优秀社区主理人等多项荣誉,并在 2023 年度博客之星评选中名列前 50。我还是 Java 高级工程师、自媒体博主,北京城市开发者社区的主理人,拥有丰富的项目开发经验和产品设计能力。希望通过我的分享,帮助大家更好地了解和使用各类技术产品,在不断的学习过程中,可以帮助到更多的人,结交更多的朋友.


我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。


使用Spring框架主要工作就是面对Bean开发BOP,作为IOC容器提供的Bean都是已经被框架处理好的Bean,平时使用只要DI即可,然而想灵活使用一个Bean则少不了对Bean的生命周期有一个掌握。

Spring Framework 作为Java Bean的管理者,对Bean对象的进行了详细的分解来为满足用户的个性化需求。整体而言Bean的生命周期可以分为四步

  1. 实例化
  2. 属性设置
  3. 初始化
  4. 销毁

在每一步,Spring都提供的接口以方便对不同步骤的Bean进行处理,常见的接口有:InstantiationAwareBeanPostProcessor、BeanNameAware、BeanPostProcessor、InitializingBean、DisposableBean,其详细情况如下图

说明:

InstantiationAwareBeanPostProcessor:具有5个接口方法,处理的实例化的Bean,BeanPostProcessor是InstantiationAwareBeanPostProcessor父类,具有2个接口方法,处理的是初始化的bean。

先看一个完整的例子

目标Bean

@Data
@Slf4j
@Accessors(chain = true)
public class ProcessorBean implements BeanNameAware, InitializingBean, DisposableBean {

    @Value("${bean.name:defaultName}")
    private String name;

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

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

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

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

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

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

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

注册

@Configuration
public class ComponentConfig {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod", name = "processorBean")
    public ProcessorBean processorBean() {
        return new ProcessorBean();
    }
}

处理器

@Slf4j
@Component
public class BeanProcessor implements InstantiationAwareBeanPostProcessor {

    private void println() {
        log.info("--------------------------------------------");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanClass == ProcessorBean.class) {
            println();
            log.info("---> postProcessBeforeInstantiation: beanClass={} beanName={}", beanClass, beanName);
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (bean instanceof ProcessorBean) {
            log.info("---> postProcessAfterInstantiation: bean={} beanName={}", bean, beanName);
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (bean instanceof ProcessorBean) {
            log.info("---> postProcessProperties: pvs={} bean={} beanName={}", pvs, bean, beanName);
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ProcessorBean) {
            log.info("---> postProcessBeforeInitialization:  bean={} beanName={}",  bean, beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ProcessorBean) {
            log.info("---> postProcessAfterInitialization: bean={} beanName={}",  bean, beanName);
            println();
        }
        return bean;
    }
}

调用

public class ProcessorApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext=SpringApplication.run(ProcessorApplication.class, args);
        applicationContext.getBean("processorBean");
        applicationContext.close();
    }
}

控制台

 Root WebApplicationContext: initialization completed in 1405 ms
 --------------------------------------------
 ---> postProcessBeforeInstantiation: beanClass=class cn.tinyice.demo.processor.component.ProcessorBean beanName=processorBean
 ---> postProcessAfterInstantiation: bean=ProcessorBean(name=null) beanName=processorBean
 ---> postProcessProperties: pvs=PropertyValues: length=0 bean=ProcessorBean(name=null) beanName=processorBean
 beanName=processorBean
 ---> postProcessBeforeInitialization:  bean=ProcessorBean(name=defaultName) beanName=processorBean
 --PostConstruct--
 afterPropertiesSet
 --initMethod--
 ---> postProcessAfterInitialization: bean=ProcessorBean(name=defaultName) beanName=processorBean
 --------------------------------------------
 Initializing ExecutorService 'applicationTaskExecutor'
 Tomcat started on port(s): 8080 (http) with context path ''
 Started ProcessorApplication in 2.036 seconds (JVM running for 2.903)
 Shutting down ExecutorService 'applicationTaskExecutor'
 --PreDestroy--
 --destroy--
 --destroyMethod--

接口方法说明:(部分方法已注释,name未使用@Value注入)


Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

    • 在实例化之前调用,返回类型 Object
      • ==null: 默认值,意味着通过Spring来完成之后的实例化,然后初始化
      • !=null: 意味着开发者主动完成了实例化和初始化

例如:返回一个对象

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
	if (beanClass == ProcessorBean.class) {
		println();
		log.info("---> postProcessBeforeInstantiation: beanClass={} beanName={}", beanClass, beanName);
		return new ProcessorBean().setName("newName");
	}
	return null;
}

控制台

 --------------------------------------------
 ---> postProcessBeforeInstantiation: beanClass=class cn.tinyice.demo.processor.component.ProcessorBean beanName=processorBean
 ---> postProcessAfterInitialization: bean=ProcessorBean(name=newName) beanName=processorBean
 --------------------------------------------
  • boolean postProcessAfterInstantiation(Object bean, String beanName)
    • 在实例化之后调用,返回类型 boolean
      • == true: 默认值,意味着开发者可以对实例化的Bean进行属性设置
      • == false: 意味着不会再调用postProcessProperties方法

例如:返回false

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
	if (bean instanceof ProcessorBean) {
		log.info("---> postProcessAfterInstantiation: bean={} beanName={}", bean, beanName);
	}
	return false;
}

控制台

 --------------------------------------------
 ---> postProcessBeforeInstantiation: beanClass=class cn.tinyice.demo.processor.component.ProcessorBean beanName=processorBean
 ---> postProcessAfterInstantiation: bean=ProcessorBean(name=null) beanName=processorBean
 ---> postProcessBeforeInitialization:  bean=ProcessorBean(name=null) beanName=processorBean
 ---> postProcessAfterInitialization: bean=ProcessorBean(name=null) beanName=processorBean
 --------------------------------------------
  • PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    • 在实例化后置处理之后调用,用来处理Bean的Property值

示例

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
	if (bean instanceof ProcessorBean) {
		// 先设置一个值
		((ProcessorBean) bean).setName("beanName");
		log.info("---> postProcessProperties: pvs={} bean={} beanName={}", pvs, bean, beanName);
		// 由于没有使用XML配置,无法配置property, 所以这里新加了一个
		PropertyValue propertyValue = new PropertyValue("name", beanName);
		// 修改
		MutablePropertyValues changes = (MutablePropertyValues) pvs.changesSince(pvs);
		changes.addPropertyValue(propertyValue);
		// 返回修改后的pvs
		return changes;
	}
	return pvs;
}

控制台: 注意属性值的变化

 --------------------------------------------
 ---> postProcessBeforeInstantiation: beanClass=class cn.tinyice.demo.processor.component.ProcessorBean beanName=processorBean
 ---> postProcessAfterInstantiation: bean=ProcessorBean(name=null) beanName=processorBean
 ---> postProcessProperties: pvs=PropertyValues: length=0 bean=ProcessorBean(name=beanName) beanName=processorBean
 ---> postProcessBeforeInitialization:  bean=ProcessorBean(name=processorBean) beanName=processorBean
 ---> postProcessAfterInitialization: bean=ProcessorBean(name=processorBean) beanName=processorBean
 --------------------------------------------
  • Object postProcessBeforeInitialization(Object bean, String beanName)
    • Bean属性配置完毕,即将初始化之前调用。
  • Object postProcessAfterInitialization(Object bean, String beanName)
    • Bean初始化完成之后调用,之后的Bean就是开发者真正调用的完整的Bean

BeanNameAware

  • void setBeanName(String name)
    • Spring生成BeanName并在设置时调用该方法,实现该接口可以获取该名称

InitializingBean

  • void afterPropertiesSet()
    • 初始化且属性设置完成之后调用

DisposableBean

  • void destroy()
    • 容器关闭时或者Bean主动销毁时调用

说明:postProcessAfterInstantiation之后就可以操作目标Bean了,postProcessProperties是针对Spring 配置文件中property属性的配置进行编辑,而在postProcessProperties与postProcessBeforeInitialization之间完成了属性的注入,包括依赖注入、@Value注入等,后续就是对Bean进行Getter、Setter调用来设置bean的上下文、字段值。

在这里插入图片描述


🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

在这里插入图片描述

更多推荐