代码之家  ›  专栏  ›  技术社区  ›  hellzone

如何从组件中注入applicationContext?

  •  0
  • hellzone  · 技术社区  · 5 年前

    我想在mycomponent类中使用applicationcontext实例。当我尝试自动连线时,当Spring在启动时初始化我的组件时,我得到了空指针异常。

    有没有办法在MyComponent类中自动连接ApplicationContext?

    @SpringBootApplication
    public class SampleApplication implements CommandLineRunner {
    
        @Autowired
        MyComponent myComponent;
    
        @Autowired
        ApplicationContext context;  //Spring autowires perfectly at this level
    
        public static void main(String[] args) {
            SpringApplication.run(SampleApplication.class, args);
        }
    
    }
    
    
    @Component
    public class MyComponent{
    
        @Autowired
        ApplicationContext ctx;
    
        public MyComponent(){
            ctx.getBean(...) //throws null pointer
        }
    
    }
    
    1 回复  |  直到 5 年前
        1
  •  3
  •   Vüsal    5 年前

    如果要确保依赖项(bean)已初始化并在构造函数中就绪,则应使用构造函数注入,而不是字段注入:

        @Autowired
        public MyComponent(ApplicationContext ctx){
            ctx.getBean(...) // do something
        }
    

    另一种方法是 @PostConstruct 如下所示:

    @Component
    public class MyComponent {
    
        @Autowired
        ApplicationContext ctx;
    
        public MyComponent(){
    
        }
    
        @PostConstruct
        public void init() {
            ctx.getBean(...); // do something
        }
    
    }
    

    你得到 NPE 因为spring需要首先创建bean( MyComponent )然后设置字段的值,因此在构造函数中,字段的值是 null .

        2
  •  0
  •   Xobotun Sohlowmawn    5 年前

    问题是 MyComponent 在spring autowires之前调用构造函数 ApplicationContext 是的。 有两种方法:

    –在构造函数中注入依赖项( better way )以下内容:

    @Component
    public class MyComponent{
        private final ApplicationContext ctx;
    
        @Autowired
        public MyComponent(ApplicationContext ctx) {
            this.ctx = ctx;
            ctx.getBean(...);
        }
    }
    

    或者通过现场注射(更糟糕的方式)注射并使用 @PostConstruct 生命周期注释:

    @Component
    public class MyComponent {
        @Autowired
        private ApplicationContext ctx; // not final
    
        @PostConstruct
        private void init() {
            ctx.getBean(...);
        }
    }
    

    它可能不太安全,但我认为它提供了更可读的代码。


    哦,还有我个人使用的方式 lombok 是的。 它使得几乎没有样板代码,直到您真正需要在构建时执行一些操作或拥有一些不可自动连线的字段。:天

    @Component
    @AllArgsConstructor(onConstructor_ = @Autowired)
    public class MyComponent {
        private final ApplicationContext ctx;
    
        @PostConstruct
        private void init() {
            ctx.getBean(...);
        }
    }