SpringBoot优雅的调用工具类并在工具类中获取自动注入的bean或属性

通常,我们在写工具类时,会将其所属方法,属性规定为 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或属性,并且可以使用静态方法来实现具体的功能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值