
在 spring boot 中,若手动 new 对象(如 new print()),即使类中使用了 @autowired,依赖也不会被注入,因为该实例未由 spring 容器管理。解决方法是让 print 也成为 spring bean(如添加 @component),并通过容器获取实例。
在 spring boot 中,若手动 new 对象(如 new print()),即使类中使用了 @autowired,依赖也不会被注入,因为该实例未由 spring 容器管理。解决方法是让 print 也成为 spring bean(如添加 @component),并通过容器获取实例。
Spring Boot 的核心机制是基于容器驱动的:只有由 Spring 容器创建并管理的 Bean,才能享受依赖注入(@Autowired)、AOP、生命周期回调等特性。在你的代码中,DbApplication.main() 方法里直接调用 new Print(),这绕过了 Spring 容器——Print 实例是 JVM 原生创建的普通对象,Spring 对其完全“不可见”,因此其中的 @Autowired Test test 字段始终为 null,最终触发 NullPointerException。
✅ 正确做法是:
- 将 Print 声明为 Spring Bean(例如添加 @Component);
- 从 Spring 应用上下文(ApplicationContext)中获取 Print 实例,而非手动 new;
- 确保所有依赖类(如 Test)也已正确标注为组件(你已做了:@Component ✅)。
以下是修正后的完整代码示例:
// com.example.domain.Print.java
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 + final + 构造器注入(更安全,见下方说明)
public void testSayHello() {
test.sayHello();
}
}
// com.example.DbApplication.java
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) {
// 启动 Spring Boot 应用,并获取应用上下文
ConfigurableApplicationContext context = SpringApplication.run(DbApplication.class, args);
// ✅ 从容器中获取 Print Bean(自动完成依赖注入)
Print print = context.getBean(Print.class);
print.testSayHello(); // 输出:Hello
// 应用退出前关闭上下文(非必需,但推荐用于资源清理)
context.close();
}
}
? 补充建议与最佳实践:
-
优先使用构造器注入:相比字段注入(@Autowired 字段),构造器注入更符合不可变性与测试友好原则。修改 Print 如下:
@Component public class Print { private final Test test; public Print(Test test) { // Spring 自动注入 Test 实例 this.test = test; } public void testSayHello() { test.sayHello(); } } ❌ 避免混合使用 new 和 Spring 管理对象:一旦启用 @SpringBootApplication,应全面转向依赖容器管理对象生命周期。
? @SpringBootApplication 已隐含 @ComponentScan(默认扫描主类所在包及其子包),因此 com.example.domain.Test 和 com.example.domain.Print 均能被自动发现——前提是它们都标注了 @Component 或其派生注解(如 @Service, @Repository)。
总结:@Autowired 不是“魔法语法”,它只在 Spring 容器创建的 Bean 中生效。牢记 —— 谁创建,谁负责注入。用 new 创建 → 无注入;用 context.getBean() 或 @Autowired 注入 → 有注入。











