
在 spring boot 启动类中直接 new 实例会导致 @autowired 注入失败,根本原因是该对象未被 spring 容器管理;必须将使用 @autowired 的类也声明为 spring bean(如添加 @component),并确保通过容器获取实例。
在 spring boot 启动类中直接 new 实例会导致 @autowired 注入失败,根本原因是该对象未被 spring 容器管理;必须将使用 @autowired 的类也声明为 spring bean(如添加 @component),并确保通过容器获取实例。
你遇到的 NullPointerException 并非 @SpringBootApplication 的问题,而是 Spring IoC 容器机制的基本约束:只有由 Spring 容器创建和管理的 Bean,其内部的 @Autowired 字段才会被自动注入。
在你的代码中:
Print print = new Print(); // ❌ 手动 new —— 不受 Spring 管理,test 字段始终为 null print.testSayHello();
此时 Print 是普通 Java 对象,Spring 完全 unaware,因此 @Autowired Test test 不会生效,调用 test.sayHello() 必然抛出空指针异常。
✅ 正确做法如下:
1. 将 Print 声明为 Spring Bean
为其添加 @Component(或 @Service/@Repository 等语义化注解):
package com.example.domain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; // ✅ 添加此注解
@Component // ← 关键:使 Print 成为 Spring 管理的 Bean
public class Print {
@Autowired
private Test test; // 推荐使用 private + setter 或构造器注入(更安全)
public void testSayHello() {
test.sayHello();
}
}
2. 从 Spring 容器中获取 Print 实例
修改启动类,通过 ApplicationContext 获取 Bean(而非 new):
package com.example;
import com.example.domain.Print;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class DbApplication {
public static void main(String[] args) {
// 启动应用并获取上下文
ConfigurableApplicationContext context =
SpringApplication.run(DbApplication.class, args);
// ✅ 从容器中获取 Print Bean(自动完成依赖注入)
Print print = context.getBean(Print.class);
print.testSayHello(); // 输出:Hello
// 应用退出前关闭上下文(可选,但推荐)
context.close();
}
}
⚠️ 补充说明与最佳实践
-
构造器注入更推荐:避免字段注入的 null 风险,且利于单元测试:
@Component public class Print { private final Test test; public Print(Test test) { // Spring 自动注入 this.test = test; } public void testSayHello() { test.sayHello(); } } 包扫描范围默认覆盖主类所在包及其子包:只要 Print 和 Test 在 com.example 或其子包下(当前结构已满足),@SpringBootApplication 即可自动扫描到它们。
切勿混合手动 new 与依赖注入:这是初学者典型误区——Spring 的核心价值在于统一托管对象生命周期,绕过容器就等于放弃 Spring。
总结:@Autowired 生效的前提是——目标类是 Spring Bean,且使用者也是 Spring Bean 或通过 ApplicationContext 获取。记住一句话:“谁创建,谁负责注入”;Spring 只对自己创建的对象执行依赖注入。











