@PostConstruct、@DependsOn、@Order注解嵌套使用办理Bean加载优先级问题 ...

打印 上一主题 下一主题

主题 1117|帖子 1117|积分 3351

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
踩坑:@PostConstruct、@DependsOn、@Order注解嵌套使用案例

   本日在工作中写需求代码时,遇到的一个关于Sping Bean对象加载优先级问题,结合了Spring源码,大概总结了一下遇到Bean加载序次需求问题时,比较常用的3个注解:@PostConstruct、@DependsOn、@Order。
  一、@Order注解的作用



  • @Order注解的作用是界说Spring IOC容器中Bean的实行序次的优先级。
使用案例:
  1. @Component
  2. @Order(0)
  3. public class Test01 {
  4.    ...
  5. }
  6. @Component
  7. @Order(1)
  8. public class Test02 {
  9.    ...
  10. }
  11. @Component
  12. @Order(2)
  13. public class Test03 {
  14.    ...
  15. }
复制代码
如上述代码所示,通过@Order注解界说优先级,3个Bean对象从IOC容器中的加载序次为:Test01、Test02、Test03
二、@PostConstruct注解的作用



  • @PostConstruct注解可以用于修饰一个非静态的、返回值类型为 void 的方法(eg:myInit())。
  • 该方法(myInit())会在服务器加载Servlet的时间被实行,且只会被实行一次
  • 该方法(myInit())的调用实行在构造函数之后,在Servlet的 init() 方法之前,在Servlet的 destroy()方法之后
使用案例:
  1. @Component
  2. public class Test {
  3.    @PostConstruct
  4.    private void init() {
  5.       // 初始化
  6.       System.out.println("World!");
  7.    }
  8.   
  9.    public Test(){
  10.        System.out.println("Hello");
  11.    }
  12. }
复制代码
输出效果:
  1. Hello
  2. World!
复制代码
三、@DependsOn注解的作用



  • 该注解的作用顾名思义,就是 “谁依赖谁”。
  • 如果在Test02类上加上@DependsOn(value = "test01"),那么就阐明Test02在加载时,要依赖于Test01,Spring IOC 容器会优先加载Test01,然后再加载Test02。
举个现实业务场景的案例,假设如今有2个类Test01、Test02,必要交给Spring IOC容器托管:
  1. /**
  2. * Test01是一个拥有1个静态变量的类
  3. */
  4. @Component
  5. public class Test01 {
  6.     // 该静态变量的属性值需要通过Spring容器赋值,值(hello)定义在application.properties中。
  7.     // 注意:@Value注解不可以给静态变量注入属性值 (否则获取的注入结果为null) !
  8.     // 因此HELLO的属性值注入要在setter方法上加上@Value注解,参考文章:【https://blog.csdn.net/weixin_43591980/article/details/121503720】
  9.     public static String HELLO;
  10.   
  11.     public static String WORLD;
  12.   
  13.     @Value("${spring.test.hello}")// 值为hello
  14.     public void setHELLO(String hello) {
  15.         HELLO = hello;
  16.     }
  17.   
  18.     @Value("${spring.test.world}")// 值为world
  19.     public void setWORLD(String world) {
  20.         WORLD = easak;
  21.     }
  22. }
复制代码
再来看Test02类的代码(前提要求:Test02类必要在我们的Spring Boot项目启动时首先被初始化调用!):
  1. /**
  2. * Test02拥有一个@PostConstruct注解修饰的init()初始化方法和无参构造函数
  3. */
  4. @Component
  5. public class Test02 {
  6.     @PostConstruct
  7.     public void init(){
  8.        ...
  9.     }
  10.   
  11.     public Test02(){
  12.                                 ...
  13.     }
  14. }
复制代码
业务需求:我必要在Test02的无参构造方法加载时,控制台打印Test01类中的HELLO静态变量值,然后在 init()方法实行时,控制台打印Test01类中的WORLD静态变量值。
刚开始我的第一想法是,直接这样写就好了:
  1. @PostConstruct
  2. public void init(){
  3.    System.out.println(Test01.HELLO);
  4. }
  5.   
  6. public Test02(){
  7.                 System.out.println(Test02.WORLD);
  8. }
复制代码
但是终极控制台打印的效果为:
  1. null
  2. null
复制代码
  Why?为什么是这个效果?
  

  • 由于,Test02类会在我们的Spring Boot项目启动时首先被初始化调用,也就是说IOC容器会首先去加载Test02对象,而这时间Test01还尚未被加载到容器中,这时间Test01中的两个静态变量HELLO、WORLD还没有通过@Value注解注入属性值,所以效果理所应当是输出 null ~
   办理方案:使用@DependsOn注解
  我们对Test02类进行改进:
  1. @Component
  2. @DependsOn(value = "test01")// 通过该注解,向Spring容器声明,该类的加载需要依赖于Test01,当加载Test02时,要先去加载Test01!
  3. public class Test02 {
  4.     @PostConstruct
  5.     public void init(){
  6.        System.out.println(Test01.HELLO);
  7.     }
  8.   
  9.     public Test02(){
  10.                                 System.out.println(Test01.WORLD);
  11.     }
  12. }
复制代码
查看打印效果:
  1. hello
  2. world
复制代码
  注:也可以使用@Order注解给Test01、Test02类声明加载优先级,优先加载Test01,然后再加载Test02!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表