手动创建Spring原型Bean后Autowired属性为null,如何实现自动装配?
嘿,这个坑我之前踩过!你猜的完全没错——手动用new创建的对象根本不在Spring容器的管理范围内,所以@Autowired标记的依赖自然不会被注入进来。下面给你几个实用的解决方案,根据你的场景选就行:
方案一:直接从Spring容器获取原型Bean(最推荐)
既然你的DayLayout已经标记了@Component和@Scope("prototype"),Spring本身就支持每次获取新实例,完全没必要自己手动new。你只需要在需要创建DayLayout的类里,先注入ApplicationContext:
@Autowired private ApplicationContext applicationContext;
然后通过它获取实例:
DayLayout dayLayout = applicationContext.getBean(DayLayout.class);
这样拿到的实例不仅会自动注入schedulingService和generalService,而且因为是prototype作用域,每次调用getBean都会返回全新的对象,和你手动new的效果完全一致。
方案二:让Spring为手动创建的对象补做依赖注入
如果因为某些原因你已经手动new了对象,也可以让Spring容器帮你完成依赖注入。同样需要先注入ApplicationContext,然后调用autowireBean方法:
DayLayout dayLayout = new DayLayout(); applicationContext.autowireBean(dayLayout);
这一步会自动处理@Autowired(或@Resource等)标记的属性注入。如果你的DayLayout类里有@PostConstruct这类生命周期回调方法,还需要额外调用initializeBean来触发这些逻辑:
applicationContext.initializeBean(dayLayout, "customDayLayout");
第二个参数是给这个手动创建的Bean起个名称,随便填一个合法的字符串就行。
方案三:使用@Configurable注解(适合必须手动new的场景)
如果你的业务逻辑必须要手动new对象,而且不想每次都依赖ApplicationContext,可以试试Spring的@Configurable注解。不过这个方法需要依赖AspectJ,配置稍微复杂一点:
- 先在你的Spring配置类上启用该功能:
@Configuration @EnableSpringConfigured public class AppConfig { // 其他配置内容 }
- 然后给
DayLayout类加上@Configurable注解:
@Component @Scope("prototype") @Configurable public class DayLayout extends VerticalLayout { @Autowired private SchedulingService schedulingService; @Autowired private GeneralService generalService; // ... 其他代码 }
这样之后,哪怕你直接new DayLayout(),Spring也会自动帮你注入所需的依赖。不过如果不是非用不可的场景,还是优先考虑前两种方案,毕竟配置更简单。
内容的提问来源于stack exchange,提问作者Druudik

