赞
踩
通常,我们在写工具类时,会将其所属方法,属性规定为 static 类型的,方便调用,
如下:
- // 调用
- FileUtil.getFiles();
-
- public class FileUtil {
-
- private static String FILE_PATH = "D:\\files";
-
- public static String getFiles() {
- return FILE_PATH;
- }
- }
通过 FileUtil.getFiles(); 可以直接调用静态方法,不必获取 FileUtil 对象实例,或使用@Autowired自动注入。
但是,当工具类本身需要使用spring注入对象实例或者需要从配置文件获取属性值时,这时候
在使用静态方法往往就会存在一些限制。
如下:
使用spring注入对象实例
- // 调用会报空指针错误
- FileUtil.getFiles();
-
- @Component
- public class FileUtil {
-
- private static String FILE_PATH = "D:\\files";
-
- @Autowired
- private static SysFileService service;
-
- public static String getFiles() {
- return service.download(FILE_PATH);
- }
- }
从配置文件获取属性值
- // 调用结果为null
- FileUtil.getFiles();
-
- // 以下两种写法均无法正常从配置文件获取值
- @Component
- public class FileUtil {
-
- @Value("${files.filePath}")
- private static String FILE_PATH;
-
- public static String getFiles() {
- return FILE_PATH;
- }
- }
-
- // 或
-
- @Component
- @ConfigurationProperties(prefix = "files")
- public class FileUtil {
-
-
- private static String FILE_PATH;
-
- public static String getFiles() {
- return FILE_PATH;
- }
- }
上述代码,无法正常获取值,这是因为 FILE_PATH 变量不能是静态变量(因为@Value和@ConfigurationProperties注解不能赋值到静态变量上,虽然也可以通过一些方法成功赋值静态变量,但这里不做详述), 如果把 static 修饰词去掉,则可以正常获取,但这样一来,由于 FILE_PATH 不是静态变量,也就无法在静态方法中使用了!
以上,是存在的问题,接下来,讲讲如何优雅的来解决问题。
使用spring注入对象实例
- // 调用正常
- FileUtil.getFiles();
-
- @Component
- public class FileUtil {
-
- private static String FILE_PATH = "D:\\files";
-
- private static FileUtil instance;
-
- @Autowired
- private SysFileService service;
-
- @PostConstruct
- public void init() {
- instance = this;
- }
-
- public static String getFiles() {
- return instance.service.download(FILE_PATH);
- }
- }
使用了@PostConstruct来完成对应bean的获取。
原理:@PostConstruct注解被用来修饰一个非静态void方法。该注解方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
由此,在自动注入后,instance 对象被赋值为 this,即成功获得一个自动注入后的一个 FileUtil 类对象(手动赋值 instance),所以,getFiles方法中使用 instance 对象时就不会是一个 null 值。
从配置文件获取属性值
- // 调用正常
- FileUtil.getFiles();
-
- public class FileUtils {
-
- private static final String FILE_PATH;
-
- static {
- File file = File.getInstance();
- FILE_PATH = file.FILE_PATH;
- }
-
- public static String getFiles() {
- return FILE_PATH;
- }
-
- @Component
- @ConfigurationProperties("files")
- public static class File {
- private String FILE_PATH;
-
- public static File getInstance() {
- return ApplicationContextUtil.getBean(File.class);
- }
- }
- }
这里使用了上下文和静态代码块来完成对应bean的获取。
简单讲下原理:上下文可以让我们自己获取需要的bean实例,静态代码块会在类初始化的时候执行且仅执行一次(静态代码块是最优先被执行的,在类构造器执行之前)。
先使用 File 静态内部类(可以简单看作一个普通类)来正常获取配置文件的值! 其中 getInstance方法的 ApplicationContextUtil.getBean 方法实现了 ApplicationContextAware 接口,用来获取 File bean 本身,然后在 FileUtil 类的静态代码块中调用 File.getInstance() 获取实例。就可以成功赋值 FILE_PATH 了。
后记:
推荐使用该方法!
构造器注入
- // 调用正常
- FileUtil.getFiles();
-
- @Component
- public class FileUtil {
-
- private static String FILE_PATH = "D:\\files";
-
- private static SysFileService service;
-
- public FileUtilss(SysFileService service) {
- FileUtil.service = service;
- }
-
- public static String getFiles() {
- return service.download(FILE_PATH);
- }
- }
以上,我们解决了如何在工具类中优雅的使用Spring(依赖注入)获取bean或属性,并且可以使用静态方法来实现具体的功能!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。