非静态方法快速调用
前言
上一篇文章提到了在监听器&过滤器中使用工具类获取bean对象的问题,工具类中出现了代码扫描的问题:Make the enclosing method "static" or remove this set.
这个问题其实就是静态和非静态的问题,在很多时候我们会遇到类似情况,例如静态方法调用非静态方法、静态方法调用非静态变量、给静态变量赋值等。解决办法有很多,我使用的方式是将方法或变量定义为非静态,然后进一步封装到静态变量中,就能使用静态调用的方式来调用非静态了。
正文
定义一个工具类,然后将需要调用的非静态方法所在类定义为一个静态对象,使用@Autowired的方式给静态对象赋值。
@Component
public class BaseUtil {
public static RedisTemplate redisTemplate;
public static BaseDao baseDao;
public static BasePropertiesConstants basePropertiesConstants;
public static SpringContextUtil springContextUtil;
@Autowired
public BaseUtil(@Qualifier("redisTemplateCustomize") RedisTemplate redisTemplate, BaseDao baseDao, BasePropertiesConstants basePropertiesConstants, SpringContextUtil springContextUtil) {
BaseUtil.redisTemplate = redisTemplate;
BaseUtil.baseDao = baseDao;
BaseUtil.basePropertiesConstants = basePropertiesConstants;
BaseUtil.springContextUtil= springContextUtil;
}
/**
* 从config表中获取配置信息
*
* @param key
* @return
* @throws Exception
* @Author 96XL
* @Date 2021/10/16
*/
public static String selectInfoFromConfig(String key) {
HashOperations hashOperations = redisTemplate.opsForHash();
// 先查询缓存中是否存在,如果存在则直接返回
if (hashOperations.hasKey(BaseStaticConstants.REDISDATA_WXECPICRESP, key)) {
Object value = hashOperations.get(BaseStaticConstants.REDISDATA_WXECPICRESP, key);
if (value != null) {
return value.toString();
}
}
// 不存在则查询数据库
String value = baseDao.selectInfoFromConfig(key);
// 将查询结果放入缓存中
hashOperations.put(BaseStaticConstants.REDISDATA_WXECPICRESP, key, value);
return value;
}
}
比如上面这段代码,RedisTemplate用来操作redis,一般使用需要在类中注入RedisTemplate对象,这样写就可以通过BaseUtil.redisTemplate.xxx来调用RedisTemplate的api,无需再进行对象注入。如:BaseUtil.redisTemplate.opsForValue().get(key);
另外,@Qualifier("redisTemplateCustomize")指定注入的RedisTemplate是我自定义的,而不是框架默认的,关于自定义RedisTemplate配置后面单独再讲。
BasePropertiesConstants中我放的是使用@Value注解从配置文件中读取的变量,如果想要直接通过类名使用变量,那么就需要把变量定义为静态,使用注解和set方法给变量赋值。如:
@Component
public class BasePropertiesConstants {
public static String str;
@Value("${str}")
public void setStr(String str) {
BasePropertiesConstants.str = str;
}
}
public void test() {
System.out.println(BasePropertiesConstants.str);
}
但是这样同样会出现代码扫描的问题:Make the enclosing method "static" or remove this set.
如果想要避免这个问题,那么需要把变量定义为非静态,直接使用注解给变量赋值,同时在使用的时候将类对象注入进来。如:
@Component
public class BasePropertiesConstants {
@Value("${str}")
public String str;
}
@Autowired
private BasePropertiesConstants basePropertiesConstants;
public void test() {
System.out.println(basePropertiesConstants.str);
}
使用上面我这种写法,就可以直接使用下面的方式使用该变量,无需再注入:
@Component
public class BasePropertiesConstants {
@Value("${str}")
public String str;
}
public void test() {
System.out.println(BaseUtil.basePropertiesConstants.str);
}
当然,BasePropertiesConstants的存在只是为了规范与统一管理,直接把这个变量定义在调用的类中也可以,以及还有其他很多方法,这里不做过多赘述。
BaseDao中我放的是一些常用的sql,比如操作系统配置表的sql。在代码中经常从配置表中获取配置信息,这些配置信息基本是不怎么变的,如果每次使用都从数据库中获取的话过于繁琐,如果在代码中定义成常量的话又不方便管理。所以在示例代码中写了一个获取配置信息的方法,并且把这个方法定义为静态,这样就可以通过 BaseUtil.selectInfoFromConfig(key);
的方式随时获取到配置信息。同样,这样定义的BaseDao才能在selectInfoFromConfig静态方法中被使用。
SpringContextUtil这样定义也是同样的原因,这样就可以避免代码扫描的问题了。通过这样的方式可以把一些非静态变量或不涉及到具体业务的非静态方法进行封装,调用起来就会方便的多了。