一个类中的非静态成员注入方式非常常见,但有一天我需要写一个工具类,这个工具类中的方法都是静态方法,因此成员必须是静态成员。我用到了Redis查询,获取redis的方法并非静态方法,而是一个spring注入的bean。
如何在静态类(类中的方法都为静态)中,用spring注入静态成员呢?
@Autowired
private static RedisHelperManager redisHelperManager;
这样肯定是不行的!,并且在用到该变量时会抛出运行时异常java.lang.NullPointerException
,为什么呢?静态变量不属于对象的属性,属于类属性,spring是基于对象层面的注入。
通过搜索,主要有以下三种实现方式:
- 通过setter方法为静态变量注入
-
@PostConstruct
方式注入 -
@PostConstruct
方式的变形
除第3种外,其他都是从网上搜集整理。
通过setter方法为静态变量注入
有人说这是spring官方在意识到对静态变量支持不友好后推出的方式,我并没有找到官方文档,但它却是可以。也是一个最简单且容易理解的方式。
基于注解的方式
将注解放在setter方法之上
@Component
public class DistinctUtil {
private static RedisHelper redisHelper;
@Autowired
public void setRedisHelper(RedisHelper redisHelper) {
DistinctUtil.redisHelper = redisHelper;
}
public static void doDistinct() {
redisHelper.sdiff();
}
}
XML配置方式
public class DistinctUtil {
private static RedisHelper redisHelper;
public void setRedisHelper(RedisHelper redisHelper) {
DistinctUtil.redisHelper = redisHelper;
}
public static void doDistinct() {
// 为演示精简代码
redisHelper.sdiff();
}
}
<bean class="cn.com.dotleo.DistinctUtil">
<property name="redisHelper" ref="redisHelper"/>
</bean>
@PostConstruct
方式注入
这种方式是我在网上搜到的另一种注入方式,@PostConstruct
和 @PreDestroy
一个是在初始化之后调用,一个是在销毁之前调用。这里用到了@PostConstruct
,在初始化后将一个对象赋值给了该类的静态变量。
基于注解的方式
@Component
public class DistinctUtil {
@Autowired
private RedisHelper redisHelper;
private static DistinctUtil distinctUtil;
@PostConstruct
public void init() {
this.redisHelper = redisHelper;
distinctUtil = this;
}
public static void doDistinct() {
distinctUtil.redisHelper.sdiff();
}
}
XML方式
public class DistinctUtil {
private RedisHelper redisHelper;
private static DistinctUtil distinctUtil;
public void init() {
this.redisHelper = redisHelper;
distinctUtil = this;
}
public static void doDistinct() {
distinctUtil.redisHelper.sdiff();
}
public void setRedisHelper(RedisHelper redisHelper) {
this.redisHelper = redisHelper;
}
<bean class="cn.com.dotleo.DistinctUtil" init-method="init">
<property name="redisHelper" ref="redisHelper"/>
</bean>
@PostConstruct
方式的变形
既然可以在初始化之后赋值,那也必然可以在初始化时赋值,因此想到了第三种方法。
##基于注解的方式
@Component
public class DistinctUtil {
private static DistinctUtil instance;
@Autowired
private RedisHelper redisHelper;
public DistinctUtil() {
instance = this;
}
public static void doDistinct() {
// 为演示精简代码
instance.redisHelper.sdiff();
}
}
这样,spring注入一个DistinctUtil类,并自动注入RedisHelper,在构造函数中将该类赋值给了静态的成员变量。之后可以通过该成员变量调用注入的redisHelper的方法。
XML配置方式
public class DistinctUtil {
private static DistinctUtil instance;
private RedisHelper redisHelper;
public DistinctUtil(RedisHelper redisHelper) {
this.redisHelper = redisHelper;
instance = this;
}
public static void doDistinct() {
// 为演示精简代码
instance.redisHelper.sdiff();
}
}
<bean class="cn.com.dotleo.DistinctUtil">
<constructor-arg name="redisHelper" ref="redisHelper"/>
</bean>
Help me
由于本人水平有限,只是从网上搜集方法并记录备忘,如果能帮助到别人非常荣幸。但我并不是很清楚这两类方式(第1种为一类,2、3种为一类)的区别或者优缺点,烦请评论区赐教。