Spring 静态方法使用注入

昨天又遇到,又去搜索+翻旧代码,这里做一下简单记载。

在静态方法中直接使用注入报错:non-static variable request cannot be referenced from a static context,错误示例如下:

1
2
3
4
5
6
7
8
9
10
@Component
public class HelloWorld {
@Autowired
private HttpServletRequest request;

public static void sayHello() {
String path = request.getSession().getServletContext().getRealPath("");
// ...
}
}

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class HelloWorld {
@Autowired
private HttpServletRequest request;

private static HelloWorld helloWorld;

@PostConstruct
public void initialize() {
helloWorld = this;
helloWorld.request = this.request;
}

public static void sayHello() {
String path = helloWorld.request.getSession().getServletContext().getRealPath("");
// ...
}
}

@PostConstruct 这个注解并不是 Spring 提供的,其实是 Java 自己的注解,是 javax.annotation 包下的,被用来修饰一个非静态的 void 方法。被 @PostConstruct 修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器执行一次。PostConstruct 在构造函数之后执行,init 方法之前执行。

@PostConstruct注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

@PostConstruct注释规则:除了拦截器这个特殊情况以外,其他情况都不允许有参数,否则 spring 框架会报 IllegalStateException;而且返回值要是void,但实际也可以有返回值,至少不会报错,只会忽略。

另外,还有其它解法,不再赘述。如 spring项目中静态方法中使用注入的bean 写了一个工具类,通过 spring 上下文获取这个 bean,转成静态的。