【SpringBoot】Bean生命周期自定义初始化和销毁

举报
MoCrane 发表于 2024/08/13 10:11:08 2024/08/13
【摘要】 上篇文章详细讲诉了Bean的生命周期和作用域,在生命周期中提到了如何自定义初始化Bean,可能很多人不知道如何自定义初始化,这里详细补充讲解一下:使用@Bean注解指定初始化和销毁方法、实现InitializingBean接口和DisposableBean接口自定义初始化和销毁、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解、使用BeanPostProcesso

一、@Bean注解指定初始化和销毁方法

  • 创建BeanTest类,自定义初始化方法和销毁方法。
  • 在@Bean注解的参数中指定BeanTest自定义的初始化和销毁方法:
  • 销毁方法只有在IOC容器关闭的时候才调用。

代码如下:

public class BeanTest {
public BeanTest(){
    System.out.println("BeanTest被创建");
}

public void init(){
    System.out.println("BeanTest被初始化");
}

public void destory(){
    System.out.println("BeanTest被销毁");
}
}
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: MyConfig
* @Description: TODO描述
* @Date: 2024/1/21 22:59
*/
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
@Bean(initMethod = "init",destroyMethod = "destory")
public BeanTest beanTest(){
    return new BeanTest();
}
}
//测试代码
AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println("IoC容器创建完成");

在这里插入图片描述

  • 可以看到调用的是自定义的方法,这里解释一下,测试时,运行完代码块程序就结束了,所哟IoC容器就被关闭,所以调用了IoC销毁方法。同时可以看到初始化方法在对象创建完成后调用。
  • 当组件的作用域为单例时在容器启动时即创建对象,而当作用域为原型(PROTOTYPE)时在每次获取对象的时候才创建对象。并且当作用域为原型(PROTOTYPE)时,IOC容器只负责创建Bean但不会管理Bean,所以IOC容器不会调用销毁方法。

二、实现InitializingBean接口和DisposableBean接口

看一下两接口的方法:

public interface InitializingBean {

/**
 * Invoked by the containing {@code BeanFactory} after it has set all bean properties
 * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
 * <p>This method allows the bean instance to perform validation of its overall
 * configuration and final initialization when all bean properties have been set.
 * @throws Exception in the event of misconfiguration (such as failure to set an
 * essential property) or if initialization fails for any other reason
 * Bean都装配完成后执行初始化
 */
void afterPropertiesSet() throws Exception;
}
====================================================================
public interface DisposableBean {

/**
 * Invoked by the containing {@code BeanFactory} on destruction of a bean.
 * @throws Exception in case of shutdown errors. Exceptions will get logged
 * but not rethrown to allow other beans to release their resources as well.
 */
void destroy() throws Exception;

}

代码如下:

public class BeanTest1 implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
    System.out.println("BeanTest1销毁");
}

@Override
public void afterPropertiesSet() throws Exception {
    System.out.println("BeanTest1初始化");
}

public BeanTest1() {
    System.out.println("BeanTest1被创建");
}
}
=========================

@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
@Bean
public BeanTest1 beanTest1(){
    return new BeanTest1();
}
}

在这里插入图片描述

三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解

  • 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。
  • 被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
  • 被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

代码如下:

public class BeanTest2 {
public BeanTest2(){
    System.out.println("BeanTest2被创建");
}

@PostConstruct
public void init(){
    System.out.println("BeanTest2被初始化");
}

@PreDestroy
public void destory(){
    System.out.println("BeanTest2被销毁");
}
}
========================
//
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
@Bean
public BeanTest2 beanTest2(){
    return new BeanTest2();
}
}

在这里插入图片描述

四、BeanPostProcessor接口

BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。

BeanPostProcessor的源码如下:

public interface BeanPostProcessor {

/**
 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
 * or a custom init-method). The bean will already be populated with property values.
 * The returned bean instance may be a wrapper around the original.
 * <p>The default implementation returns the given {@code bean} as-is.
 * @param bean the new bean instance
 * @param beanName the name of the bean
 * @return the bean instance to use, either the original or a wrapped one;
 * if {@code null}, no subsequent BeanPostProcessors will be invoked
 * @throws org.springframework.beans.BeansException in case of errors
 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
 */
@Nullable
  //bean初始化方法调用前被调用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

/**
 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
 * or a custom init-method). The bean will already be populated with property values.
 * The returned bean instance may be a wrapper around the original.
 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
 * post-processor can decide whether to apply to either the FactoryBean or created
 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
 * <p>This callback will also be invoked after a short-circuiting triggered by a
 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
 * in contrast to all other BeanPostProcessor callbacks.
 * <p>The default implementation returns the given {@code bean} as-is.
 * @param bean the new bean instance
 * @param beanName the name of the bean
 * @return the bean instance to use, either the original or a wrapped one;
 * if {@code null}, no subsequent BeanPostProcessors will be invoked
 * @throws org.springframework.beans.BeansException in case of errors
 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
 * @see org.springframework.beans.factory.FactoryBean
 */
@Nullable
//bean初始化方法调用后被调用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

代码如下:

@Component
public class MyBeanPostProcess implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
    return bean;
}
}
============================
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
@Bean
public BeanTest1 beanTest1(){
    return new BeanTest1();
}

@Bean
public BeanTest2 beanTest2(){
    return new BeanTest2();
}
}

运行结果如下:

BeanTest1被创建
postProcessBeforeInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
BeanTest1初始化
postProcessAfterInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
BeanTest2被创建
postProcessBeforeInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
BeanTest2被初始化
postProcessAfterInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
IoC容器创建完成
BeanTest2被销毁
BeanTest1销毁

通过上述运行结果可以发现使用BeanPostProcessor的运行顺序为
IOC容器实例化Bean---->调用BeanPostProcessor的postProcessBeforeInitialization方法---->调用bean实例的初始化方法---->调用BeanPostProcessor的postProcessAfterInitialization方法。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。