Spring工厂类初始化时Service中Repository无法注入的问题
问题根源
你手动创建的AnnotationConfigApplicationContext是一个独立的Spring子上下文,它仅扫描了你指定的ProcessDoctorFile和ProcessPatientFile类,完全没有包含DoctorRepository所在的包路径,导致子上下文无法识别主上下文里的Repository Bean,自然出现注入失败的异常。同时你的工厂类本身是@Component会被主上下文管理,但构造函数里又新建子上下文,造成了上下文隔离的问题。
解决方案
方案一:依赖主Spring上下文(最直接修正)
修改工厂类,去掉手动创建子上下文的逻辑,改为注入主上下文:
@Component public class ProcessFileFactory { private final ApplicationContext applicationContext; // 构造函数注入主上下文 public ProcessFileFactory(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public ProcessImportFiles getInstance(String fileType) { if (ImportTypes.DOCTORS.toString().equals(fileType)) { return applicationContext.getBean(ProcessDoctorFile.class); } if (ImportTypes.PATIENTS.toString().equals(fileType)) { return applicationContext.getBean(ProcessPatientFile.class); } return null; } }
同时修改控制器,通过依赖注入获取工厂实例,避免静态调用:
@RestController public class YourImportController { private final ProcessFileFactory fileFactory; // 构造函数注入工厂类 public YourImportController(ProcessFileFactory fileFactory) { this.fileFactory = fileFactory; } // 接口方法示例 @PostMapping("/import") public void handleFileImport(@RequestParam String fileType, MultipartFile file, Sheet sheet) { ProcessImportFiles processor = fileFactory.getInstance(fileType); if (processor != null) { processor.processImportFile(file.getName(), sheet); } } }
方案二:用Spring自动注入Map管理实现类(更优雅的Spring风格)
Spring可以自动将所有实现ProcessImportFiles接口的Bean注入到一个Map中,键为Bean名称,无需手动判断类型:
@Component public class ProcessFileFactory { private final Map<String, ProcessImportFiles> processorMap; // 构造函数自动注入所有ProcessImportFiles实现类 public ProcessFileFactory(Map<String, ProcessImportFiles> processorMap) { this.processorMap = processorMap; } public ProcessImportFiles getInstance(String fileType) { String beanName = matchFileTypeToBeanName(fileType); return processorMap.get(beanName); } private String matchFileTypeToBeanName(String fileType) { if (ImportTypes.DOCTORS.toString().equals(fileType)) { return "processDoctorFile"; // 对应ProcessDoctorFile的@Service默认Bean名 } if (ImportTypes.PATIENTS.toString().equals(fileType)) { return "processPatientFile"; } return null; } }
这种方式的优势是后续新增ProcessImportFiles实现类时,只需添加@Service注解,无需修改工厂类,符合开闭原则。
关键注意事项
- 确保
DoctorRepository上添加了@Repository注解,且主配置类(或@SpringBootApplication标注的主类)的扫描范围包含Repository所在包。 - 禁止手动创建Spring上下文(除非明确需要隔离环境),否则会破坏Spring的Bean共享机制。
- 尽量避免静态方法调用Bean,静态逻辑脱离Spring依赖管理,容易引发各类注入问题。
内容的提问来源于stack exchange,提问作者Bubbles
相关产品推荐
相关产品推荐

