Spring Boot中new创建对象时@Autowired注入为null问题排查
Spring依赖注入的生效前提非常明确:只有被Spring IoC容器接管、由容器负责创建和生命周期管理的对象,容器才会解析它上面的@Autowired等注入注解,完成依赖装配。
你用new Species()手动创建实例时,这个Species对象是你自己在JVM中实例化的普通Java对象,完全不在Spring容器的管控范围内,容器根本感知不到这个对象的存在,自然不会给它注入Planet属性,返回null是必然结果。
你之前尝试加@Configuration注解不生效也很正常:只要你还在手动new对象,不管类上加什么Spring注解,这个手动创建的实例都和容器没有关系,注入永远不会生效。另外你提到的@Configuaration属于拼写错误,正确注解名是@Configuration,拼写错误的注解本身就不会被Spring识别。
另外你贴的示例代码还有Java语法问题:Java类声明不需要在类名后加括号,class Planet()、class Species()是错误写法,正确写法是class Planet {、class Species {,否则代码无法通过编译。
方案1(推荐,符合Spring开发规范):将Species也交给Spring容器托管
给Species类加上Spring Bean注解,全程不要手动new这个类的实例:
// Species.java @Component // 加注解,让Spring接管这个类的实例创建、生命周期 public class Species { private Long spId; private String spName; @Autowired private Planet planet; // 构造方法、getter、setter }
后续需要使用Species实例时,同样通过注入的方式获取,比如在其他Spring管理的类中:
@Service public class TestService { // 直接注入Species实例,这个实例里的planet属性已经被容器自动填充 @Autowired private Species species; }
容器在创建Species Bean的时候,会自动把已经托管的Planet实例注入到对应的属性中,不会再出现null的问题。
方案2(仅适用于特殊场景,不推荐常规业务使用):手动给非托管对象填充依赖
如果确实存在场景必须手动new对象、没法把类交给容器全生命周期管理,可以拿到Spring的Bean工厂后手动给实例完成注入:
// 假设species是你手动new出来的对象 Species species = new Species(); // 调用Spring API给这个手动创建的对象填充标记了@Autowired的依赖 applicationContext.getAutowireCapableBeanFactory().autowireBean(species);
执行完这行代码后,species对象的planet属性才会被容器注入对应的Bean实例。
注意:常规业务开发优先用第一种方案,所有需要依赖注入的类统一交给Spring容器管理,能避免绝大多数注入失效问题。
内容的提问来源于stack exchange,提问作者Faizanur Rahman

