Spring-Bean生命周期-构造器访问Autowired字段为null

Spring Bean 生命周期:为什么构造器里访问 @Autowired 字段是 null

Spring 依赖注入的坑很多,其中一个经典问题是"构造器里访问 @Autowired 字段拿到 null"。本文讲清楚 Bean 生命周期的执行顺序,以及正确的注入方式。

一、问题案例

一个新写的服务,启动就报 NullPointerException。排查后发现,代码在构造器里直接使用了 @Autowired 注入的字段:

java 复制代码
@Service
public class OrderService {

    @Autowired
    private UserService userService;   // 字段注入

    public OrderService() {
        userService.init();            // ❌ 构造器里使用,这行必炸
    }
}

userService 是 null。明明标了 @Autowired,为什么是 null?

二、原理:Bean 生命周期顺序

Spring 创建 Bean 的顺序是固定的:

复制代码
1. 实例化(调用构造器)        ← 此时字段全是 null
2. 依赖注入(@Autowired)    ← 字段在这一步才被赋值
3. @PostConstruct            ← 初始化回调
4. 交给容器使用

构造器在第 1 步执行,依赖注入在第 2 步。所以构造器执行时,字段还没被注入,全是 null。字段注入的本质是"先 new 出来,再回头填字段",必然存在这个时间差。

三、正确写法

方案一:构造器注入(推荐)

java 复制代码
@Service
public class OrderService {

    private final UserService userService;

    public OrderService(UserService userService) {   // ✅ 依赖作为构造参数
        this.userService = userService;
        userService.init();                          // ✅ 构造器里已可用
    }
}

依赖作为构造参数传入,构造器里天然可用,字段还能声明为 final。

方案二:把初始化逻辑挪到 @PostConstruct

java 复制代码
@Autowired
private UserService userService;

@PostConstruct
public void init() {
    userService.init();   // ✅ @PostConstruct 时字段已注入
}

四、延伸:三个初始化回调的顺序

如果需要在 Bean 初始化时执行逻辑,有三个入口,执行顺序如下:

顺序 方式 时机
1 @PostConstruct 字段注入完成后
2 InitializingBean.afterPropertiesSet() @PostConstruct 之后
3 @Bean(initMethod = "xxx") afterPropertiesSet 之后

三者都在依赖注入之后执行,都能安全访问字段。唯独构造器不行。

五、总结

  • 构造器执行时,@Autowired 字段尚未注入,访问必为 null。
  • 推荐使用构造器注入 ,或把初始化逻辑放到 @PostConstruct。
  • 三个初始化回调(@PostConstruct / afterPropertiesSet / initMethod)都在注入之后。

我是无羡(小剑),全栈偏后端的独立开发者。

作品集:无羡 · 独立开发者作品集

如果对你有帮助,欢迎点赞、收藏、关注。

相关推荐
实名上网宋凯宣4 小时前
Django
后端·python·django
天河归来5 小时前
第三方接口不稳定,如何让核心任务继续完成
java·大数据
Knight_AL6 小时前
Java 文件下载时文件名中的 `#` 被转换成 `%23`?一次 URL 编码与解码问题排查
java·开发语言
利威尔xu6 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
逃逸线LOF7 小时前
Ribbon负载均衡原理(Irule组件、源码分析)
后端·spring cloud·ribbon
砚底藏山河7 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
慢云智慧空间7 小时前
从设备智能到空间理解,空间智能终端解决方案商如何重新定义行业标准
后端
利威尔xu7 小时前
Go IM 源码实战(13):30 个会话只有 2 个红点,未读数错在三条路径
redis·后端·微服务·面试·golang
猿究院_夏燊8 小时前
MySQL 的四种隔离级别
java·数据库·mysql
薛定谔的猫-菜鸟程序员8 小时前
软件架构设计师开发资料大全(从入门到精通)
后端·python·系统架构·flask·架构设计师