Spring控制器请求处理方法中注入接口及实现类的异常问题
问题1:注入FooBarRepository接口时报错的原因及解决
核心原因
你大概率是在控制器的@GetMapping方法参数中直接声明FooBarRepository,此时Spring会将其当作请求参数解析,而非依赖注入。Spring无法实例化接口,因此抛出No primary or single unique constructor found for interface错误。
结合Thymeleaf能正常访问Bean的情况,你的DefaultFooBarRepository已被Spring正确扫描并注册,问题本质是注入方式混淆了请求参数绑定与依赖注入。
无需额外配置的解决方法
使用标准依赖注入方式,即可让Spring自动关联接口与实现类:
- 构造注入(推荐):
@Controller public class FooBarController { private final FooBarRepository fooBarRepository; // Spring自动匹配唯一实现类DefaultFooBarRepository public FooBarController(FooBarRepository fooBarRepository) { this.fooBarRepository = fooBarRepository; } @GetMapping("/") public String get() { fooBarRepository.getFooBars(); return "view"; } } - 字段注入:
@Controller public class FooBarController { @Autowired private FooBarRepository fooBarRepository; @GetMapping("/") public String get() { fooBarRepository.getFooBars(); return "view"; } } - 方法参数注入(需标注@Autowired):
若一定要在方法参数中注入,必须明确标注@Autowired告知Spring这是依赖注入:@Controller public class FooBarController { @GetMapping("/") public String get(@Autowired FooBarRepository fooBarRepository) { fooBarRepository.getFooBars(); return "view"; } }
问题2:注入DefaultFooBarRepository时AppProperties为null的矛盾原因
核心原因
同样是注入方式错误导致的:你可能在控制器方法参数中直接声明DefaultFooBarRepository,或手动new DefaultFooBarRepository(),这两种情况都会创建新实例,而非使用Spring上下文里已完成依赖注入的Bean。
- 手动new实例时,Spring不会参与依赖注入,因此
AppProperties为null; - 在方法参数中声明时,Spring会尝试从请求参数中获取
AppProperties(而非上下文Bean),找不到则传入null。
而Thymeleaf访问的@fooBarRepository是Spring上下文里已初始化的Bean,它的AppProperties已被正确注入,因此能正常工作。
解决方法
使用标准依赖注入方式注入实现类即可:
@Controller public class FooBarController { private final DefaultFooBarRepository fooBarRepository; public FooBarController(DefaultFooBarRepository fooBarRepository) { this.fooBarRepository = fooBarRepository; } @GetMapping("/") public String get() { fooBarRepository.getFooBars(); return "view"; } }
内容的提问来源于stack exchange,提问作者Garret Wilson
相关产品推荐
相关产品推荐

