为什么 Autowired 引入字段为 Null?

使用 @Autowired 做类或接口的自动引入时,可能会出现引入的类为 null 这里我们使用 Spring Boot 来演示几种引发 null 例子。

@Autowired 正常使用

HelloWorldService

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package com.mangobeta.test.service;

import org.springframework.stereotype.Service;

@Service
public class HelloWorldService {
    public void sayHello(String name)  {
        System.out.println("Hello " + name);
    }

}

HelloWorldServiceTest

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.mangobeta.test.service;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class HelloWorldServiceTest {

    @Autowired
    HelloWorldService helloWorldService;

    @Test
    void sayHello() {
        helloWorldService.sayHello("mangobeta");
    }
}

@Autowired 引发 Null 几种情况

在静态字段上使用@Autowired

将以下 HelloWorldService 用作 Spring 应用程序中的 bean 会失败,因为不支持对静态字段的依赖项注入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@SpringBootTest
class HelloWorldServiceTest {

    @Autowired
    private static HelloWorldService helloWorldService;

    @Test
    void sayHello() {
        helloWorldService.sayHello("mangobeta");
    }
}

异常信息:

1
2
3
4
5
6
7
java.lang.NullPointerException
	at com.mangobeta.test.service.HelloWorldServiceTest.sayHello(HelloWorldServiceTest.java:16)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

字段缺省 @Autowired

在Spring应用程序中将下面的 HelloWorldService 用作 Bean 会失败。 由于字段上没有@Autowired(或 @Inject 或 @Resource),因此 Spring 不知道需要将依赖项注入字段。 因此该字段依然为 null。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@SpringBootTest
class HelloWorldServiceTest {

    HelloWorldService helloWorldService;

    @Test
    void sayHello() {
        helloWorldService.sayHello("mangobeta");
    }
}

Bean 实例对 Sping Bean 不可见

注释为 @Autowired 的字段为 null ,因为 Spring 不知道你用 new 创建的 HelloWorldService 的副本,也不知道要对其自动连接。

新建 MangoBetaService

1
2
3
4
5
6
7
8
9

@Service
public class MangoBetaService {

    public void test() {
        System.out.println("test");
    }

}

HelloWorldService 更改如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Service
public class HelloWorldService {
    @Autowired
    MangoBetaService mangoBetaService;

    public void sayHello(String name)  {
        System.out.println("Hello " + name);
        mangoBetaService.test();
    }

}

测试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@SpringBootTest
class HelloWorldServiceTest {

//    @Autowired
//    HelloWorldService helloWorldService;

    @Test
    void sayHello() {
        (new HelloWorldService()).sayHello("mangobeta");
    }
}

mangoBetaService 会抛出 NullPointerException 异常

参考文档

updatedupdated2020-10-252020-10-25
Load Comments?