自动装配的 bean 在 setter 之外为空

Autowired bean is null outside of setter

我在 Spring Boot 中通过 setter 将一个 bean 注入到另一个 bean 中。该 bean 在 setter 内部时不为空,但是当我从另一个方法调用它时,它 returns 为空。

我已经尝试了所有组合(通过构造函数和 setter 注入,仅自动装配字段,自动装配字段和 setter...)。

SpringConfiguration.java

@Bean
public BeanToInject beanToInject(){
    return new BeanToInject();
}
@Bean
public TargetClass targetClass(){
    return new TargetClass();
}

BeanToInject.java

@Component
public class BeanToInject{
    public BeanToInject(){}
    //More stuff
}

TargetClass.java

@Component
public class TargetClass {

    private BeanToInject beanToInject;

    public TargetClass(){}

    @Autowired
    public void setBeanToInject(BeanToInject beanToInject){
        this.beanToInject = beanToInject;
        System.out.print("1. " + this.beanToInject); //Here is instanced
    }

    public void anotherMethod(){
        System.out.print("2. " + beanToInject); //Here is null
        beanToInject.doSomeStuff(); //Here comes the exception
    }

}

输出:

//Spring stuff...
1. com.foo.bar.BeanToInject@blahblah
2. null

//------And then, the exception

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at acteso.standard.deskapp.gui.LoginController.btAceptar(LoginController.java:82)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8411)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access00(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent(GlassViewEventHandler.java:432)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null(WinApplication.java:177)
    at java.lang.Thread.run(Unknown Source)

我想这个例外根本就没有用。我正在使用 JavaFX,但当异常来自 Spring.

时并不重要

不知道是我漏了注解还是配置错了

编辑:

实际上这是一个关于 Spring 和 JavaFX 创建它们自己的 TargetClass 实例的问题,所以 BeanToInject 是重复的。我按照本教程 Spring 管理 JavaFX 控制器解决了这个问题:Add Spring to JavaFX。感谢大家的帮助!

一个例子

BeanOne(BeanToInject)

public class BeanOne {

}

BeanTwo(目标类)

public class BeanTwo {

    BeanOne beanOne;


    @Autowired
    public void setBeanOne(BeanOne beanOne) {
        this.beanOne = beanOne;
        System.out.println("From setter "+beanOne);
    }

    public void testMethod() {
        System.out.println("From testMethod "+beanOne);
    }


}

配置。注意,这里只用了@Bean

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

@Configuration
public class TestConfiguration {

    @Bean
    public BeanOne getBeanOne() {
        return new BeanOne();
    }

    @Bean
    public BeanTwo getBeanTwo() {
        return new BeanTwo();
    }
}

测试应用程序

public class TestApp {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestConfiguration.class);

        ctx.registerShutdownHook();

        BeanTwo bean = ctx.getBean(BeanTwo.class);

        bean.testMethod();
    }

}

运行

时的输出
From setter BeanOne@7f1302d6
From testMethod BeanOne@7f1302d6

Spring 容器在创建 BeanTwo 时注入 BeanOne 的实例。在此期间,将打印 "From setter" 消息。

然后我们从 ApplicationContext 中获取这个 BeanTwo 实例并调用 testMethod(),它给出 "From testMethod" 消息。

从外观上看,在您的情况下,您正在自己创建 BeanTwo (TargetClass) 实例 (new TargetClass())。这样的 bean 不受 Spring 容器管理,并且在创建时将 BeanOne 引用为 null。