【问题标题】:Autowired throws null pointer [duplicate]Autowired抛出空指针[重复]
【发布时间】:2019-10-09 20:55:21
【问题描述】:

我在自动连接我的一个类时遇到空指针异常。

我尝试过使用不同的注解,例如@Component@ComponentScan

public class ClassA {
    public final String str = "String";

    public ClassA(){
        System.out.println("Class A initiated");
    }
}


public class ClassB {

    @Autowired
    public ClassA classA;

    public ClassB(){
     System.out.println(classA.str);
    }


}

@Configuration
public class Config {

    @Bean
    public ClassA classA(){
        return new ClassA();
    }

    @Bean
    public ClassB classB(){
        return new ClassB();
    }
}

堆栈跟踪:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'classB' defined in class path resource [com/test/demo/Config.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.test.demo.ClassB]: Factory method 'classB' threw exception; nested exception is java.lang.NullPointerException

【问题讨论】:

  • 一个没有在任何地方初始化的字段怎么可能在类的构造函数中不为空?如果对象尚未构造,Spring 无法自动装配对象的字段。

标签: java spring


【解决方案1】:

而不是使用@Autowired。通过 ClassB 的构造函数注入 ClassA。

public class ClassB {
private final ClassA classA;

public ClassB(ClassA classA){
     this.classA = classA;
     System.out.println(classA.str);
}

然后将ClassB的Bean配置改为ClassA。

【讨论】:

    【解决方案2】:

    构造函数运行之前 Spring 注入自动连接字段,因此classA 字段仍然为空。

    将您的代码移到构造函数(和字段初始值设定项)之外,您应该会看到正确的值。

    【讨论】:

    • 抱歉移动了哪个构造函数的代码?
    • @priyam.soni ClassB 构造函数。
    【解决方案3】:

    如果您希望在构造函数本身中提取值,则可以使用构造函数注入而不是字段注入:

    public class ClassB {
        public ClassA classA;
    
        @Autowired
        public ClassB(ClassA classA){
         this.classA = classA;
         System.out.println(classA.str);
        }
    }
    

    从 Spring 4.3 开始,具有单个构造函数的类可以省略 @Autowired 注释。Spring 将在执行包扫描时遇到我们的“ClassB”类,并将通过调用 @Autowired 注释构造函数来初始化其实例。

    在您的代码中,自动装配发生在调用无参数构造函数之后。因此,当您尝试使用 classA 对象访问“str”时,会导致空指针异常,因为 classA 尚未自动装配。

    【讨论】:

      【解决方案4】:

      尝试将@Component@Service 放在ClassA

      @Component
      public class ClassA {
          public final String str = "String";
      
          public ClassA(){
              System.out.println("Class A initiated");
          }
      }
      

      这是因为 ClassA 类不是 Spring Bean。

      【讨论】:

        猜你喜欢
        • 2018-08-14
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多