好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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();

     }

}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

package   com.xk.spring.init;

 

 

/**

  * 用于如何配置讲解bean的初始化方法

  * @author xk

  * @since 2023.04.30 15:26

  */

public   class   RedisService{

     public   RedisService(){

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

     }

}

单元测试方法如下:

?

1

2

3

4

5

     @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方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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类内容如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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单元测试方法,得出如下结果:

?

1

2

3

这是RedisService构造方法

( 2 )这是一个 @PostConstruct 初始化方法

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

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

1.3、实现InitializingBean接口

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

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初始化方法" );

     }

}

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

?

1

2

3

4

这是RedisService构造方法

( 2 )这是一个 @PostConstruct 初始化方法

( 3 )这是一个InitializingBean初始化方法

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

1.4、总结

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

?

1

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

2、配置bean的销毁方法

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

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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方法:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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单元测试方法,得出如下结果:

?

1

2

3

4

5

这是RedisService构造方法

( 2 )这是一个 @PostConstruct 初始化方法

( 3 )这是一个InitializingBean初始化方法

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

( 1 )这是一个 @Bean   destroyMethod销毁方法

2.2、使用@PreDestroy注解

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

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单元测试方法,得出如下结果:

?

1

2

3

4

5

6

这是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类如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

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销毁方法" );

     }

}

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

?

1

2

3

4

5

6

7

这是RedisService构造方法

( 2 )这是一个 @PostConstruct 初始化方法

( 3 )这是一个InitializingBean初始化方法

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

( 2 )这是一个 @PreDestroy 销毁方法

( 3 )这是一个DisposableBean销毁方法

( 1 )这是一个 @Bean   destroyMethod销毁方法

2.4、总结

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

?

1

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

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

原文链接:https://juejin.cn/post/7228109484940886073

查看更多关于一文详解spring注解配置bean的初始化方法和销毁方法的详细内容...

  阅读:13次