一文详解spring注解配置bean的初始化方法和销毁方法

 更新时间:2023年05月02日 09:40:25   作者:IT人的天地  
本篇我们讲解下spring项目中如何为bean指定初始化方法和销毁方法。当spring完成bean的属性赋值之后,就会执行bean的初始化方法,而当spring要销毁bean实例的时候,也会调用bean的销毁方法。文中有详细的代码实例,需要的朋友可以参考下

本篇我们讲解下spring项目中如何为bean指定初始化方法和销毁方法。当spring完成bean的属性赋值之后,就会执行bean的初始化方法,而当spring要销毁bean实例的时候,也会调用bean的销毁方法。我们可以在初始化方法中做一些资源加载的操作,比如缓存数据到redis。而在销毁方法中,可以做一些资源释放的操作,比如删除redis缓存数据、释放数据库连接等。由于我们现在很少写spring的xml文件,所以这次就讲解通过注解的方式来指定bean的初始化方法和销毁方法。我们先定义如下的配置类、业务服务类和单元测试方法,供后面测试使用。

package com.xk.spring.init;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** 测试初始化方法和销毁方法
 *
 * @author xk
 * @since 2023.04.30 15:31
 */
@Configuration
public class InitConfig {

    @Bean
    public RedisService redisService(){
        return new RedisService();
    }
}
package com.xk.spring.init;


/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService{
    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }
}

单元测试方法如下:

    @Test
    public void testInitAndDestroyConfig(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(InitConfig.class);
        applicationContext.close();
    }

1、配置bean的初始化方法

1.1、使用@Bean注解的initMethod属性

我们在配置类中使用@Bean注解生成bean实例的时候,可以使用@Bean注解的initMethod属性指定初始化方法,initMethod的值是目标bean对应的类中的方法名,当spring完成bean的属性赋值之后,就会执行initMethod对应的这个方法。

修改RedisService服务类内容如下,增加自定义的initMethod方法:

package com.xk.spring.init;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService {
    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }
}

修改InitConfig配置类如下,指定@Bean注解的initMethod属性值为RedisService类中的initMethod方法:

package com.xk.spring.init;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** 测试初始化方法和销毁方法
 *
 * @author xk
 * @since 2023.04.30 15:31
 */
@Configuration
public class InitConfig {

    @Bean(initMethod = "initMethod")
    public RedisService redisService(){
        return new RedisService();
    }
}

最后执行testInitAndDestroyConfig单元测试方法,得出如下结果:

这是RedisService构造方法
(1)这是一个@Bean initMethod初始化方法

1.2、使用@PostConstruct注解

@PostConstruct注解用于在bean完成依赖注入(属性赋值)之后需要执行的方法上,它是被用在bean对应的类中定义的方法,而且一个类中只能有一个方法被标记@PostConstruct注解。只要方法所属的类不是拦截器类而且方法本身无参且没有返回值,那就可以在这个方法上面使用@PostConstruct注解。(如果方法所属类的是拦截器类,在满足一定的要求时也可以使用@PostConstruct注解,但这种情况很少使用,所以此处先不提。)我们保持InitConfig类不变,修改RedisService类内容如下:

package com.xk.spring.init;


import javax.annotation.PostConstruct;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService{

    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }
    
    @PostConstruct
    private void initMethod2(){
        System.out.println("(2)这是一个@PostConstruct初始化方法");
    }
}

最后执行testInitAndDestroyConfig单元测试方法,得出如下结果:

这是RedisService构造方法
(2)这是一个@PostConstruct初始化方法
(1)这是一个@Bean initMethod初始化方法

可以看出,标记@PostConstruct注解的方法要比@Bean注解的InitMethod属性指定的方法先执行。

1.3、实现InitializingBean接口

InitializingBean接口只有一个afterPropertiesSet方法,假如一个bean完成了属性赋值,并且这个bean对应的类实现了该接口,spring就会调用afterPropertiesSet方法。我们继续在前两步的基础上进行修改,保持InitConfig类不变,修改RedisService类如下:

package com.xk.spring.init;

import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService implements InitializingBean {

    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }

    @PostConstruct
    private void initMethod2(){
        System.out.println("(2)这是一个@PostConstruct初始化方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("(3)这是一个InitializingBean初始化方法");
    }
}

最后执行单元测试,得出结果如下:

这是RedisService构造方法
(2)这是一个@PostConstruct初始化方法
(3)这是一个InitializingBean初始化方法
(1)这是一个@Bean initMethod初始化方法

1.4、总结

bean的初始化方法调用位于bean的属性赋值之后,我们可以同时使用以上三种方式来指定bean的初始化方法,而且执行顺序如下:

@PostConstruct指定的方法-->InitializingBean接口的afterPropertiesSet方法-->@Bean的initMethod属性指定的方法

2、配置bean的销毁方法

2.1、使用@Bean注解的destroyMethod属性

我们在配置类中使用@Bean注解生成bean实例的时候,可以使用@Bean注解的destroyMethod属性指定bean的销毁方法,destroyMethod的值是目标bean对应的类中的方法名,当spring完成bean的属性赋值之后,就会执行destroyMethod对应的这个方法。

我们修改RedisService服务类内容如下,增加自定义的destroyMethod方法:

package com.xk.spring.init;

import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService implements InitializingBean {

    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }

    @PostConstruct
    private void initMethod2(){
        System.out.println("(2)这是一个@PostConstruct初始化方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("(3)这是一个InitializingBean初始化方法");
    }

    public void destroyMethod(){
        System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
    }

}

修改InitConfig配置类如下,指定@Bean注解的destroyMethod属性值为RedisService类中的destroyMethod方法:

package com.xk.spring.init;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** 测试初始化方法和销毁方法
 *
 * @author xk
 * @since 2023.04.30 15:31
 */
@Configuration
public class InitConfig {

    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public RedisService redisService(){
        return new RedisService();
    }
}

最后执行testInitAndDestroyConfig单元测试方法,得出如下结果:

这是RedisService构造方法
(2)这是一个@PostConstruct初始化方法
(3)这是一个InitializingBean初始化方法
(1)这是一个@Bean initMethod初始化方法
(1)这是一个@Bean destroyMethod销毁方法

2.2、使用@PreDestroy注解

@PreDestroy注解用于在bean被销毁时需要执行的方法上,它是被用在bean对应的类中定义的方法,而且一个类中只能有一个方法被标记@PreDestroy注解。只要方法所属的类不是拦截器类而且方法本身无参且没有返回值,那就可以在这个方法上面使用@PreDestroy注解。(如果方法所属类的是拦截器类,在满足一定的要求时也可以使用@PreDestroyt注解,但这种情况很少使用,所以此处先不提。)我们保持InitConfig类不变,修改RedisService类内容如下:

package com.xk.spring.init;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService implements InitializingBean, DisposableBean {

    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }

    @PostConstruct
    private void initMethod2(){
        System.out.println("(2)这是一个@PostConstruct初始化方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("(3)这是一个InitializingBean初始化方法");
    }

    public void destroyMethod(){
        System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
    }

    @PreDestroy
    public void destroyMethod2() {
        System.out.println("(2)这是一个@PreDestroy销毁方法");
    }

}

最后执行testInitAndDestroyConfig单元测试方法,得出如下结果:

这是RedisService构造方法
(2)这是一个@PostConstruct初始化方法
(3)这是一个InitializingBean初始化方法
(1)这是一个@Bean initMethod初始化方法
(2)这是一个@PreDestroy销毁方法
(1)这是一个@Bean destroyMethod销毁方法

可以看出,标记@PreDestroy注解的方法要比@Bean注解的destroyMethod属性指定的方法先执行。

2.3、实现DisposableBean接口

DisposableBean接口只有一个destroy方法,假如一个bean对应的类实现了该接口,spring在bean(或容器)销毁时就会调用destroy方法。我们继续在前面代码的基础上进行修改,保持InitConfig类不变,修改RedisService类如下:

package com.xk.spring.init;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 用于如何配置讲解bean的初始化方法
 * @author xk
 * @since 2023.04.30 15:26
 */
public class RedisService implements InitializingBean, DisposableBean {

    public RedisService(){
        System.out.println("这是RedisService构造方法");
    }

    public void initMethod(){
        System.out.println("(1)这是一个@Bean initMethod初始化方法");
    }

    @PostConstruct
    private void initMethod2(){
        System.out.println("(2)这是一个@PostConstruct初始化方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("(3)这是一个InitializingBean初始化方法");
    }

    public void destroyMethod(){
        System.out.println("(1)这是一个@Bean destroyMethod销毁方法");
    }

    @PreDestroy
    public void destroyMethod2() {
        System.out.println("(2)这是一个@PreDestroy销毁方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("(3)这是一个DisposableBean销毁方法");
    }
}

最后执行单元测试,得出结果如下:

这是RedisService构造方法
(2)这是一个@PostConstruct初始化方法
(3)这是一个InitializingBean初始化方法
(1)这是一个@Bean initMethod初始化方法
(2)这是一个@PreDestroy销毁方法
(3)这是一个DisposableBean销毁方法
(1)这是一个@Bean destroyMethod销毁方法

2.4、总结

bean的销毁方法调用位于bean(或容器)被销毁的时候,我们可以同时使用以上三种方式来指定bean的销毁方法,而且执行顺序如下:

@PreDestroy指定的方法-->DisposableBean接口的destroy方法-->@Bean的destroyMethod属性指定的方法

以上就是一文详解spring注解配置bean的初始化方法和销毁方法的详细内容,更多关于spring注解配置bean初始化方法和销毁方法的资料请关注脚本之家其它相关文章!

相关文章

  • java Date装成英文String后,无法再转回Date的解决方案

    java Date装成英文String后,无法再转回Date的解决方案

    本文介绍了java Date装成英文String后,无法再转回Date的解决方案。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Java 实战项目之毕业设计管理系统的实现流程

    Java 实战项目之毕业设计管理系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SSM+jsp+mysql+maven实现毕业设计管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • springboot集成@DS注解实现数据源切换的方法示例

    springboot集成@DS注解实现数据源切换的方法示例

    本文主要介绍了springboot集成@DS注解实现数据源切换的方法示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Springboot通过url访问本地图片代码实例

    Springboot通过url访问本地图片代码实例

    这篇文章主要介绍了springboot通过url访问本地图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Java多线程并发编程(互斥锁Reentrant Lock)

    Java多线程并发编程(互斥锁Reentrant Lock)

    这篇文章主要介绍了ReentrantLock 互斥锁,在同一时间只能被一个线程所占有,在被持有后并未释放之前,其他线程若想获得该锁只能等待或放弃,需要的朋友可以参考下
    2017-05-05
  • Java利用剪贴板实现交换程序间数据的方法

    Java利用剪贴板实现交换程序间数据的方法

    这篇文章主要介绍了Java利用剪贴板实现交换程序间数据的方法,需要的朋友可以参考下
    2014-07-07
  • Mybatis-Plus查询中如何排除标识字段

    Mybatis-Plus查询中如何排除标识字段

    这篇文章主要介绍了Mybatis-Plus查询中排除标识字段的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 基于HTTP协议实现简单RPC框架的方法详解

    基于HTTP协议实现简单RPC框架的方法详解

    RPC全名(Remote Procedure Call),翻译过来就是远程过程调用,本文将为大家介绍如何基于HTTP协议实现简单RPC框架,感兴趣的小伙伴可以了解一下
    2023-06-06
  • mybatis升级mybatis-plus时踩到的一些坑

    mybatis升级mybatis-plus时踩到的一些坑

    这篇文章主要给大家介绍了关于mybatis升级mybatis-plus时踩到的一些坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • java实现菜单树的示例代码

    java实现菜单树的示例代码

    这篇文章主要为大家详细介绍了java实现菜单树的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12

最新评论