zoukankan      html  css  js  c++  java
  • @PostConstruct及跳坑记录

    @PostConstruct及跳坑记录

    @PostConstruct的一个控制方法加载顺序的一个注解,如果使用恰当,可以方便解决很多问题,如果使用不当,也会出现一些认为莫名其妙的问题。

    这里说一下@PostConstruct和@Autowired 一起使用的一些问题。

    首先@PostConstruct是javax.annotation包下的注解,并不是Spring提供的。看一下servlet中的加载顺序。

    graph TB 服务器加载Sevlet-->Servlet-Construct Servlet-Construct-->PostConstruct PostConstruct-->init init-->service service-->destroy destroy-->PreDestroy PreDestroy-->服务器卸载sevlet完毕

    再来看一下Spring中的加载顺序:

    graph LR Construct-->Autowired Autowired-->PostConstruct
    • @Autowired是在构造方法执行之后开始执行的
    • @PostConstruct是在依赖注入完成后开始执行

    举一个跳坑的例子

    场景

    两个service:Aservice和Bservice,一个bean:Cbean;
    在Bservice中的@PostConstruct方法中动态注入一个对象Cbean,Aservice中需要依赖Cbean。

    跳坑演示

    public class Cbean {
        private int id;
        private String name;
    }
    

    Bservie中的一个PostConstruct方法动态注册Cbean到spring中

    @Component
    public class Bservie {
        @Autowired
        private ApplicationContext context;
    
        @PostConstruct
        public void init() {
            Cbean c = new Cbean();
            c.setId(1);
            c.setName("name");
            //获取BeanFactory
            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory();
            //动态注册bean.
            defaultListableBeanFactory.registerSingleton("cbean",c);
        }
    }
    

    Aservice中需要注入Cbean

    @Component
    public class Asevice {
        @Autowired
        private Cbean cbean;
        
        @Autowired
        private Bservie bservie;
    }
    

    这里的AService的加载顺序为:构造器-->Autowired Cbean;

    此时Bservice中的PostConstruct还没有触发执行,所以spring池中没有Cbean,自然抛出异常:

    Field cbean in com.xplan.testpostconstruct.Asevice required a bean of type 'com.xplan.testpostconstruct.Cbean' that could not be found.
    

    当然,如Aservice中有多个Autowired,加载顺序是从上到下的。

    这个困局的解法只需要把Aservice中的两个属性调整下顺序即可,这样就先加载Bservie,在创建Bservie的过程中会触发PostConstruct的方法,自然此局就解了。

    @Component
    public class Asevice {
    
        @Autowired
        private Bservie bservie;
    
        @Autowired
        private Cbean cbean;
    
    }
    

    通过这个示例,可以体会一下这些注解之间的微妙关系。

    源码链接:https://gitee.com/chengluchao/graphql-clc/tree/master/test-post-construct/src/main/java/com/xplan/testpostconstruct

    世界上所有的坑都是自己的无知造成的,想要避坑,就得不断提高自己的道行。

    CLC

  • 相关阅读:
    P1541 乌龟棋
    P1725 琪露诺
    P1622 释放囚犯
    P1417 烹调方案
    积木大赛
    换教室
    C#文件和目录的操作
    C#应用程序所有已经打开的窗体的集合
    C#winform自定义滚动条
    C#ADO.NET基础二
  • 原文地址:https://www.cnblogs.com/chenglc/p/13740872.html
Copyright © 2011-2022 走看看