Discuss / 手写Spring / 如果A在构造方法创建时依赖了B的属性,而B的属性为字段注入,此时触发空指针异常怎么办?

如果A在构造方法创建时依赖了B的属性,而B的属性为字段注入,此时触发空指针异常怎么办?

Topic source

li192863

#1 Created at ... [Delete] [Delete and Lock User]

已经做完了这个项目,快手一面问到了这个问题:如果A在构造方法创建时依赖了B的属性,而B的属性为字段注入,此时在A的构造方法里触发了空指针异常怎么办?

廖雪峰

#2 Created at ... [Delete] [Delete and Lock User]

不可能出现这种情况。

引用B的属性的前提是B初始化完毕。

#3 Created at ... [Delete] [Delete and Lock User]

最近刚学到这里,试验了一下,会报错,我的测试代码如下:

A类

@Componentpublic class A {    A(@Autowired B b){        b.c.hello();    }}

B类

@Componentpublic class B {    @Autowired    C c;}

C类

@Componentpublic class C {   public void hello(){       System.out.println("hello");   }}

报错如下:

com.itranswarp.summer.exception.BeanCreationException: Exception when create bean 'a': com.itranswarp.chainDependency.myClass.A

  at com.itranswarp.summer.context.AnnotationConfigApplicationContext.createBeanAsEarlySingleton(AnnotationConfigApplicationContext.java:217)
  at com.itranswarp.summer.context.AnnotationConfigApplicationContext.lambda$createNormalBeans$6(AnnotationConfigApplicationContext.java:123)
  ....

廖雪峰

#4 Created at ... [Delete] [Delete and Lock User]

因为先处理强依赖,再处理弱依赖,所以你想初始化调用b.c.hello()只能挪到@PostConstruct里

@Component
public class A {
    B b;
    A(@Autowired B b) { 
       this.b = b;
    }

    @PostConstruct
    void init() {
        b.c.hello();
    }
}

#5 Created at ... [Delete] [Delete and Lock User]

使用构造方法注入:将B作为A的构造方法参数,而不是依赖于字段注入。这样可以确保在A对象实例化时,B的实例已经被正确传入。


  • 1

Reply