You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:45:04