为什么 Spring 容器不会注入 static 字段

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

爬虫神器,无代码爬取,就来:bright.cn

1. 问题所示

实战代码如下:

public class SocialUtils {

    @Resource
    private static SocialUserService socialUserService;

    @Resource
    private static SocialUserBindMapper socialUserBindMapper;
    
    /**
     * 获取当前登录用户的 openId(微信 H5 公众号)
     * @return openId,若未绑定返回 null
     */
    public static String getCurrentUserWechatMpOpenId() {
        Long userId = WebFrameworkUtils.getLoginUserId();
        if (userId == null) return null;

        SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(
                userId,
                UserTypeEnum.MEMBER.getValue(),
                SocialTypeEnum.WECHAT_MP.getType());

        if (socialUserBind == null) {
            return null;
        }

        return socialUserService.getOpenId(socialUserBind.getSocialUserId());
    }
}

出现的结果如下:

Cannot invoke "cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(java.lang.Long, java.lang.Integer, java.lang.Integer)" because "cn.iocoder.yudao.module.gate.utils.SocialUtils.socialUserBindMapper" is null
	at cn.iocoder.yudao.module.gate.utils.SocialUtils.getCurrentUserWechatMpOpenId(SocialUtils.java:37)

后续发现是 静态变量不能使用 @Resource 或 @Autowired 自动注入

当前代码中用了 static 修饰字段:

@Resource
private static SocialUserService socialUserService;

@Resource
private static SocialUserBindMapper socialUserBindMapper;

Spring 容器不会注入静态字段,所以这两个对象 始终是 null,导致调用时报:

Cannot invoke ... because "SocialUtils.socialUserBindMapper" is null

后续可以将将 SocialUtils 改为 Spring Bean,并将方法改为非静态

@Component
public class SocialUtils {

    @Resource
    private SocialUserService socialUserService;

    @Resource
    private SocialUserBindMapper socialUserBindMapper;

    /**
     * 获取当前登录用户的 openId(微信 H5 公众号)
     * @return openId,若未绑定返回 null
     */
    public String getCurrentUserWechatMpOpenId() {
        Long userId = WebFrameworkUtils.getLoginUserId();
        if (userId == null) return null;

        SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(
                userId,
                UserTypeEnum.MEMBER.getValue(),
                SocialTypeEnum.WECHAT_MP.getType());

        if (socialUserBind == null) {
            return null;
        }

        return socialUserService.getOpenId(socialUserBind.getSocialUserId());
    }
}

使用时注入这个工具类:

@Autowired
private SocialUtils socialUtils;

public CabinetPickupVO getCabinetPickupByCntr(String cntr) {
    String openId = socialUtils.getCurrentUserWechatMpOpenId();
    return appCabinetPickupMapper.selectGateCabinetPickupOne(cntr, openId);
}

2. 深度拓展

那下面探讨下为啥Spring 容器确实不会注入 static 字段

根本原因是:Spring 依赖注入机制是基于对象实例的,不是类本身

  1. Spring 是通过反射,对 对象(实例) 的字段进行赋值
  2. 而 static 字段是属于 类级别(Class) 的,不属于某个对象实例
    所以,Spring 容器在实例化 Bean 并注入属性时,不会也无法注入 static 字段

🧪 举个简单例子:

@Component
public class MyUtils {

    @Autowired
    private static SomeService someService; // ❌ 无效!始终为 null

    public static void doSomething() {
        someService.xxx(); // NullPointerException
    }
}

上面这种写法 someService 永远是 null,因为 Spring 没办法注入静态字段

✅ 正确写法(推荐):
✅ 方法 :去掉 static,改成普通字段 + 普通方法

@Component
public class MyUtils {

    @Autowired
    private SomeService someService;

    public void doSomething() {
        someService.xxx();
    }
}

然后在别的类中注入这个工具类:

@Autowired
private MyUtils myUtils;

myUtils.doSomething(); // OK

3. 应用

✅ 方法一:使用非静态字段 + 静态方法中传参使用

@Component
public class MyService {

    @Autowired
    private UserRepository userRepository;

    public void doSomething() {
        userRepository.findAll();
    }

    public static void staticMethod(MyService service) {
        service.doSomething(); // 间接访问依赖
    }
}

✅ 方法二:初始化静态字段(通过 @PostConstruct 或构造器)

@Component
public class MyService {

    @Autowired
    private UserRepository userRepository;

    private static UserRepository staticRepo;

    @PostConstruct
    public void init() {
        staticRepo = userRepository; // ✅ 把注入的字段赋值给 static 变量
    }

    public static void staticMethod() {
        staticRepo.findAll(); // 正常调用
    }
}

✅ 方法三:不使用静态字段,使用 Spring 管理的 Bean
这种方式最推荐 —— 尽量避免 static,转而使用组件注入:

@Service
public class StaticAvoidService {
    public void handleLogic() {
        // 业务逻辑
    }
}

@Component
public class Caller {

    @Autowired
    private StaticAvoidService service;

    public void invoke() {
        service.handleLogic(); // 使用实例注入的方式
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值