前言
🤟 找工作,来万码优才:👉 #小程序://万码优才/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 依赖注入机制是基于对象实例的,不是类本身
- Spring 是通过反射,对 对象(实例) 的字段进行赋值
- 而 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(); // 使用实例注入的方式
}
}