Spring Boot 3中手动创建Prototype对象致EntityManager为空问题
问题原因
你直接通过new FormGenerator()创建对象时,这个实例不在Spring容器的管控范围内,哪怕给类加了@Scope("prototype"),Spring也不会自动为它注入EntityManager——只有由Spring容器实例化的bean,才会触发依赖注入逻辑。
解决方法
方法1:通过ObjectProvider获取Spring管理的原型bean(推荐)
这是最符合Spring设计理念的方式,既能获取全新的原型实例,又能保证依赖自动注入。
- 给
FormGenerator添加@Component注解,让Spring能扫描并管理它:@Component @Scope("prototype") public class FormGenerator { private int fieldCounter=0; @Autowired private EntityManager entityManager; ... } - 在
SchoolRepositoryCustomImpl中注入ObjectProvider<FormGenerator>,通过它获取新实例:@Repository public class SchoolRepositoryCustomImpl extends SimpleJpaRepository<School, Long> implements SchoolRepositoryCustom { private final ObjectProvider<FormGenerator> formGeneratorProvider; // 构造函数注入 public SchoolRepositoryCustomImpl(JpaEntityInformation<School, Long> entityInformation, EntityManager entityManager, ObjectProvider<FormGenerator> formGeneratorProvider) { super(entityInformation, entityManager); this.formGeneratorProvider = formGeneratorProvider; } @Override public List<School> advanceSearch(SchoolSearch search) { // 每次调用getObject()都会返回一个全新的FormGenerator实例 FormGenerator qg = formGeneratorProvider.getObject(); // 后续业务逻辑 } }
方法2:通过ApplicationContext获取原型bean
和方法1类似,只是换用ApplicationContext直接获取bean:
@Repository public class SchoolRepositoryCustomImpl extends SimpleJpaRepository<School, Long> implements SchoolRepositoryCustom { private final ApplicationContext applicationContext; public SchoolRepositoryCustomImpl(JpaEntityInformation<School, Long> entityInformation, EntityManager entityManager, ApplicationContext applicationContext) { super(entityInformation, entityManager); this.applicationContext = applicationContext; } @Override public List<School> advanceSearch(SchoolSearch search) { // 获取全新的原型实例 FormGenerator qg = applicationContext.getBean(FormGenerator.class); // 后续业务逻辑 } }
同样需要给FormGenerator添加@Component注解。
方法3:手动注入EntityManager(应急方案,不推荐)
如果不想让Spring完全管理FormGenerator,可以手动传递EntityManager:
- 在
FormGenerator中添加setter方法:@Scope("prototype") public class FormGenerator { private int fieldCounter=0; private EntityManager entityManager; public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; } ... } - 在Repository中手动设置依赖:
@Repository public class SchoolRepositoryCustomImpl extends SimpleJpaRepository<School, Long> implements SchoolRepositoryCustom { private final EntityManager entityManager; public SchoolRepositoryCustomImpl(JpaEntityInformation<School, Long> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.entityManager = entityManager; } @Override public List<School> advanceSearch(SchoolSearch search) { FormGenerator qg = new FormGenerator(); qg.setEntityManager(entityManager); // 后续业务逻辑 } }
这种方式绕过了Spring的依赖注入机制,仅适合临时应急,不推荐长期使用。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

