Spring @Autowired注入接口时无法调用实现类继承方法的原因咨询
核心结论
Spring确实注入的是TestDAOImpl的实例,你无法调用save()方法和Spring无关,是Java静态类型语法的编译期限制导致的。
问题根因
Java是静态类型语言,编译阶段只会校验变量声明的类型里的方法是否存在,不会校验实际运行时的实例类型的方法。
你在TestServiceImpl里声明的变量类型是TestDAO,这个接口本身只定义了createUser()方法,没有save()方法的声明,所以编译阶段就会报错,哪怕运行时实际注入的是有save()方法的TestDAOImpl实例也不允许直接调用。
你可以写一段纯Java代码验证,不需要Spring也会有同样的问题:
TestDAO testDao = new TestDAOImpl(); testDao.save(); // 编译直接报错,和Spring完全无关
Spring @Autowired注入接口的工作逻辑
- 容器启动时会扫描所有注册的Bean(你的
TestDAOImpl需要加@Repository等注解才会被Spring托管,另外注意你给出的示例代码里TestDAOImpl漏写了implements TestDAO,实际项目必须加上,否则Spring找不到TestDAO的实现类) - 当检测到
@Autowired标注的TestDAO类型字段时,Spring会在容器中查找所有实现了TestDAO接口的Bean,当匹配到唯一的实现类TestDAOImpl时,就会把该实例注入到字段中,运行时该变量指向的确实是TestDAOImpl的实例。 - 如果你要调用
save()方法,运行期可以通过强转验证:// 运行时可以正常执行,证明注入的确实是TestDAOImpl实例 ((CommonDAO) testDao).save();
要调用save()的正确实现方案
推荐用面向接口的方式修改,避免强转和耦合:
- 方案1:让
TestDAO继承CommonDAO,这样TestDAO就包含了save()方法的声明,你可以直接用TestDAO类型的变量调用public interface TestDAO extends CommonDAO { User createUser(); } - 方案2:如果
save()是通用DAO能力,也可以单独注入CommonDAO类型的变量,单例模式下两个注入的是同一个TestDAOImpl实例。
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

