Spring Boot中@Autowired注入MyBatis静态Mapper为何为空?
你遇到的问题本质上是两个核心原因导致的:Spring不支持注入静态成员,以及你的Model类并没有被Spring容器管理,这也是为什么你加了@Configurable等注解仍然无效的原因。下面详细拆解并给出可行的解决方案:
一、为什么静态字段无法被@Autowired注入?
Spring的依赖注入是基于对象实例的——它只会为容器中管理的Bean实例注入依赖,而静态成员属于类本身,不属于任何实例。@Autowired注解作用在静态字段上时,Spring会直接忽略这个注入请求,所以你的sourceMapper和domainMapper始终是null。
另外,你Controller里的Mapper能正常工作,是因为Controller被@Controller标记,属于Spring管理的Bean,Spring会为它的实例注入依赖;而你的Source、Domain类,即使加了注解,如果你是通过new或者直接调用静态方法的方式使用,这些类的实例并没有被Spring创建和管理,自然不会触发依赖注入。
二、可行的解决方案
方案一:遵循Spring设计理念,使用实例化的Bean(推荐)
把Model类改成Spring管理的Bean,去掉静态字段和静态方法,改用实例字段和实例方法,让Spring统一管理依赖。
以Source类为例修改:
// 标记为Spring组件,让容器管理它的实例 @Component public class Source { // 用实例字段替代静态字段,推荐构造方法注入(Spring 4.3+无需@Autowired) private final SourceMapper sourceMapper; public Source(SourceMapper sourceMapper) { this.sourceMapper = sourceMapper; } // 把静态方法改成实例方法 public Source findOrCreate(String url) { // ... 你的逻辑处理 System.out.println("sourceMapper = " + sourceMapper); Source source = sourceMapper.findByHost(host); // ... 其他逻辑 return source; } }
然后在需要调用的Controller中注入Source实例:
@Controller public class YourController { private final Source sourceService; // 构造方法注入Source实例 public YourController(Source sourceService) { this.sourceService = sourceService; } @GetMapping("/your-path") public ResponseEntity<?> handleRequest(@RequestParam String url) { Source source = sourceService.findOrCreate(url); // ... 后续处理逻辑 return ResponseEntity.ok(source); } }
这种方式完全符合Spring的依赖注入设计,代码解耦性强,也方便单元测试。
方案二:保留静态方法的妥协方案(不推荐)
如果因为业务限制必须保留静态方法,可以通过非静态的setter方法让Spring注入后赋值给静态字段,同时需要把Model类加入Spring容器:
以Domain类为例修改:
// 标记为Spring组件,让容器创建实例 @Component public class Domain { private static DomainMapper domainMapper; // 非静态的setter方法,让Spring注入后赋值给静态字段 @Autowired public void setDomainMapper(DomainMapper domainMapper) { Domain.domainMapper = domainMapper; } public static void incrementCounter(String host) { // ... 你的逻辑处理 Domain d = domainMapper.find(host, thisMonth); // ... 其他逻辑 } }
⚠️ 注意:这种方式虽然能解决当前问题,但会让代码耦合Spring容器,静态字段的使用也会带来测试困难、线程安全等潜在问题,仅建议在无法重构代码的临时场景使用。
内容的提问来源于stack exchange,提问作者Chloe

