目的
获取配置文件(.yml,.properties )中的配置,配置参数已经封装在了Mqconfig,我们需要在工具类的静态方法中,通过自动注入获取该配置。但是直接注入会报空指针异常。 不想看描述的直接跳 解决办法
场景描述
我需要封装了一个rocketMQ发送消息工具类MqMsgUtils,需要去调用Mqconfig的参数,Mqconfig主要是映射application.yml中的参数,如果是一般的方法可以直接注入,但是静态方法优先级仅次于构造方法,大于自动注入,所以这里调用会导致自动注入失败为空对象
整个Bean初始化中的执行顺序:
Constructor(构造方法,静态方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
MqConfig
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
@ConfigurationProperties(prefix = "rocketmq")
@Data
public class MqConfig {
private String accessKey;
private String secretKey;
private String nameSrvAddr;
private String topic;
private String groupId;
private String tag;
private String orderTopic;
private String orderGroupId;
private String orderTag;
public Properties getMqPropertie() {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.AccessKey, this.accessKey);
properties.setProperty(PropertyKeyConst.SecretKey, this.secretKey);
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr);
return properties;
}
}
MqMsgUtils
import com.aliyun.openservices.ons.api.*;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import com.wjd.op.common.config.MqConfig;
import com.wjd.op.common.rocketMq.MqSendCallBack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.Executors;
/**
* @program: MqMsgUtils
* @description: mq消息处理工具类
* @author: whhh
* @create: 2021/8/31 16:41
**/
@Slf4j
@Component
public class MqMsgUtils {
@Autowired
private static ProducerBean producerBean;//这里2个静态对象都会报空指针
@Autowired
private static MqConfig config;
/**
* @param tag 标签
* @param msgDetail 消息体,二进制的形式
* @Author: whhh
* @Description: 异步发送消息
* @DateTime: 2021/8/31 16:44
*/
public static void sendMsgAsync(String tag, byte[] msgDetail) {
//对于使用异步接口,设置单独的回调处理线程池,拥有更灵活的配置和监控能力。
producer.setCallbackExecutor(Executors.newFixedThreadPool(10));
//定义消息体
Message msg = new Message(mqConfig.getTopic(), tag, msgDetail);
//在无法正常收到消息情况下,可通过MQ 控制台查询消息并补发
msg.setKey("ORDERID_100");
// 发送消息,只要不抛异常就是成功
try {
//发送消息并定义毁掉函数
producer.sendAsync(msg, new MqSendCallBack());
} catch (ONSClientException e) {
log.warn("发送失败");
e.printStackTrace();
}
}
}
解决办法
使用@PostConstruct注解,利用该注解的方法在整个Bean初始化中的执行顺序,所以我们使用该注解可以去调用一个init方法初始化我们的普通变量,然后把我们注入的对象赋值给静态对象,代码如下
import com.aliyun.openservices.ons.api.*;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import com.wjd.op.common.config.MqConfig;
import com.wjd.op.common.rocketMq.MqSendCallBack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.Executors;
/**
* @program: MqMsgUtils
* @description: mq消息处理工具类
* @author: whhh
* @create: 2021/8/31 16:41
**/
@Slf4j
@Component
public class MqMsgUtils {
@Autowired
private ProducerBean producerBean;
@Autowired
private MqConfig config;
private static ProducerBean producer;
private static MqConfig mqConfig;
//重点:
//我们先利用上面的Autowired注解自动注入2个对象
//然后利用PostConstruct修饰的普通方法初始化我们的静态变量
//下面的工具类方法调用静态对象就会初始化了
/**
* @Author: whhh
* @Description: 初始化config和producerBean
* @DateTime: 2021/9/2 9:59
*/
@PostConstruct
private void init(){
//实际调用的是peoducer,mqConfig
//自动注入的是producerBean,config
//注入后将值赋给静态变量
producer=producerBean;
mqConfig=config;
}
/**
* @param tag 标签
* @param msgDetail 消息体,二进制的形式
* @Author: whhh
* @Description: 异步发送消息
* @DateTime: 2021/8/31 16:44
*/
public static void sendMsgAsync(String tag, byte[] msgDetail) {
//对于使用异步接口,设置单独的回调处理线程池,拥有更灵活的配置和监控能力。
producer.setCallbackExecutor(Executors.newFixedThreadPool(10));
//定义消息体
Message msg = new Message(mqConfig.getTopic(), tag, msgDetail);
//在无法正常收到消息情况下,可通过MQ 控制台查询消息并补发
msg.setKey("ORDERID_100");
// 发送消息,只要不抛异常就是成功
try {
//发送消息并定义毁掉函数
producer.sendAsync(msg, new MqSendCallBack());
} catch (ONSClientException e) {
log.warn("发送失败");
e.printStackTrace();
}
}
}