Springboot工具类如何使用自动绑定

问题描述

在Springboot中,对于MVC对应的组件如Service,Controller,Model等组件我们会习惯性的使用@Value,@Autowired等方法完成组件和变量值的自动绑定工作,但是在工具类中,如果我们是无法直接使用自动绑定的。

重点写在前面

Spring的依赖注入实际上是依赖于Set方法进行注入值的,Spring是基于对象层面的依赖注入,而静态属性/静态变量实际上是属于类的。

问题1:在静态工具类中自动绑定静态变量

问题代码

在配置文件application.properties中定义了如下变量 link.host=www.csdn.net,在代码中尝试使用该自动绑定该变量。

程序代码:

public class TestUtil {
    @Value("${link.host}")
    private static String linkHost; // 想要将link.host的值自动绑定到linkHost中

    public static JSONObject getAccessToken(String appid, String secret) {
        String apiURL = linkHost + "/test/"; //这里希望直接使用linkHost的值
        String responseStr = HttpUtil.sendGet(apiURL);
        JSONObject json = JSONObject.fromObject(responseStr);
        return json.getString("access_token");
        return json;
    }
}

问题说明

当在方法getAccessToken中尝试使用静态变量linkHost的值时,会发现该值为空。经过研究发现springboot不允许/不支持把值注入到静态变量中。

问题解决方法

springboot支持通过set方法实现注入,我们可以利用非静态set方法注入静态变量

修正后的代码

@Component // 需要添加Component注释才会被springboot管理
public class TestUtil {
    @Value("${link.host}")
    private static String linkHost;

    // *核心:通过非静态set方法实现注入*
    @Value("${link.host}")
    public void setLinkHost(String linkHost) {
        XunTongUtil.linkHost = linkHost;
    }

    public static JSONObject getAccessToken(String appid, String secret) {
        String apiURL = linkHost + "/test/;
        String responseStr = HttpUtil.sendGet(apiURL);
        JSONObject json = JSONObject.fromObject(responseStr);
        return json.getString("access_token");
        return json;
    }
}

问题2: 在静态工具类中注入Bean

问题代码

public class AccountManageClient {

    @Autowired
    private PcodeService pcodeService; // 尝试自动绑定Service

    private static String getDepartmentPcode(String department) {
        try {
            List<PcodePO> pcodes = pcodeService.findAll();  // 尝试使用自动绑定的service
            for (PcodePO pcode : pcodes) {
                if (department.contains(pcode.getDepartment())) {
                    return pcode.getPcode();
                }
            }
        } catch (Exception e) {
        }
        return "";
    }
}

问题解决方法

要解决该问题,需要在保留原静态的属性(@Autowired)的同时,添加一个该类的静态属性。同时声明一个返回值为void的方法,在其中将非静态属性赋值给静态属性,该方法需要使用@PostConstruct注释

修正后的代码

@Component // 1. 需要添加Component注释才会被springboot管理
public class AccountManageClient {
    public static AccountManageClient accountManageClient; // 2.添加一个该类的静态对象作为属性

    @Autowired
    private PcodeService pcodeService;

    // 3. 使用@PostConstruct方法引导绑定
    @PostConstruct
    public void init() {
        accountManageClient = this;
        accountManageClient.pcodeService = this.pcodeService;
    }

    private static String getDepartmentPcode(String department) {
        try {
            List<PcodePO> pcodes = accountManageClient.pcodeService.findAll(); // 4. 使用时需要这样实现
            for (PcodePO pcode : pcodes) {
                if (department.contains(pcode.getDepartment())) {
                    return pcode.getPcode();
                }
            }
        } catch (Exception e) {
        }
        return "";
    }
}

重点总结

  1. 一定要对工具类添加@Component注释
  2. 要使用非静态方法对静态变量/对象进行手动绑定

引申阅读 - @PostConstruct

  • @PostConstruct是Java EE5规范之后,Servlet新增的两个影响servlet声明周期的注解之一,另外一个是@PreConstruct。这两个都可以用来修饰一个非静态的返回值为void的方法,并且该方法不能抛出异常。
  • @PostConstruct注解修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet中的init方法。被该注解修饰的方法会在构造器执行之后,init方法执行之前执行。Spring中允许开发者在受理的Bean中去使用它,当IOC容器被实例化管理当前bean时,被该注解修饰的方法会执行,完成一些初始化的工作。
  • @PreConstruct注解修饰的方法会在服务器卸载Servlet的时候运行,类似于Servlet中的destroy方法。被该注解修饰的方法会在destroy方法执行之后,Servlet彻底卸载之前执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值