【Spring】静态方法(工具类)中调用Spring管理的Bean

发布时间 2023-04-21 20:40:42作者: aaacarrot

背景

在一些业务开发,经常会写一些工具类,但这些工具类时常需要调用到 Spring管理的bean,这些Spring管理的bean 注入,
平常用的都是 @Autowired 注解一个成员变量,
问题就来了:
(1)成员变量(即Spring管理的bean)是非静态的,但工具类都是想写静态方法,静态方法不能引入一个非静态的变量。所以在静态方法里面写不了
(2)如果把成员变量(即Spring管理的bean)写成静态的话,这样的话,静态方法是可以用这个变量了,但是运行的时候,会喜提一个NPE。

比如下面这个例子, signRepository 会 NPE

@Component
public class ScriptExecuteContent {
 
@Autowired
private static SignRepository signRepository;
 
public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

静态方法怎样引入Spring管理的Bean呢

方法有二(应该不止两种,这里只说两种比较方便点的)

1、 @Autowired 用在构造函数上 (@Resource 也是一样的)
@Component
public class ScriptExecuteContent {

// 成员变量变成 static
private static SignRepository signRepository;


// 构造函数加上 @Autowired
@Autowired
public ScriptExecuteContent(SignRepository signRepository) {
    ScriptExecuteContent.signRepository = signRepository;
}

// 静态方法就可以用了
public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}
2、 使用 @PostConstruct 注解
@Component
public class ScriptExecuteContent {

// 这里定义成员变量
@Autowired
private SignRepository signRepository;

// 要把类也变成静态变量?
private static ScriptExecuteContent scriptExecuteContent;

// 构造方法
@PostConstruct
public void init() {
    scriptExecuteContent = this;
    scriptExecuteContent.signRepository = this.signRepository;
}

// 静态方法,用的时候是 scriptExecuteContent.signRepository 
public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = scriptExecuteContent.signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

嗯,通过这两种方式,也基本够用了。

还有另外一些方式,,,,, aware 还是啥的,后补吧。。。