策略模式对象初始化为空解决方案及项目中具体的使用

使用类:

@Component
public class TaskReceiver {
     
    @Autowired
    TaskHandlerMapping mapper;

    @RabbitHandler
    @RabbitListener(queues = {MqTaskConstant.QUEUE_WS_CAMUNDA_EVENT_TASK}  )
    public void sendNotice(Message message, Channel channel) throws IOException {
        if (message.getBody() == null) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        String str = new String(message.getBody());
        try {
            
            JsonNode taskMessage = CNPCJacksonUtil.decode(str, JsonNode.class);
            String eventName = taskMessage.get("eventName").asText();
            //获取真正处理消息的处理者
            TaskEventTypeHandler handler = mapper.getHandler(eventName);
            //不同情况进行入库
            if(handler != null){
                handler.handleMessage(str);
            }
        }catch(Exception e){
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

注意:

//需要注入策略类,否则策略没办法初始化
@Autowired
TaskHandlerMapping mapper; 

TaskEventTypeHandler handler = mapper.getHandler(eventName);

映射类

//映射类主要是获取到具体的策略 
@Component
public class TaskHandlerMapping
{
    Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
    //这里注入也可以使用@AutoWired
    private final TaskCreateHandler taskCreateHandler;
    private final TaskAssignmentHandler taskAssignmentHandler;
 
    public TaskHandlerMapping(TaskCreateHandler taskCreateHandler, TaskAssignmentHandler taskAssignmentHandler )
    {
        this.taskCreateHandler = taskCreateHandler;
        this.taskAssignmentHandler = taskAssignmentHandler;
    }

    @PostConstruct
    public void config()
    {
        handlerList.put(TaskConstant.CREATE, taskCreateHandler);
        handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
    }
    public TaskEventTypeHandler getHandler(String eventName)
    {
        return handlerList.get(eventName);
    }

}

策略接口:

@Component
public interface TaskEventTypeHandler {

    void handleMessage(String message) throws Exception ;

}

具体的策略A

@Component
public class TaskCreateHandler implements TaskEventTypeHandler {

    @Override
    public void handleMessage(String taskMessage) throws Exception {

    }

}

具体的策略B

@Component
public class TaskAssignmentHandler implements TaskEventTypeHandler {
    @Override
    public void handleMessage(String message) {

    }

}

整体的逻辑: receiver接受到mq消息进行消费,因为消息分不同的情况:任务的指派和生成等6种情况都需要入库,并且入库的数据不同,因为给每一种写了对应的策略。

在这里插入图片描述

坑:

1 static代码块初始化会导致注入的策略为空。 因为static随着类的加载而加载,此时策略还没有初始化到springContext 中 . 因此下面这种写法不可取

 static Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
 @Autowired
 private static TaskCreateHandler taskCreateHandler;
 @Autowired  //为空,spring没有初始化
 private static TaskAssignmentHandler taskAssignmentHandler;
 
 static {
     handlerList.put(TaskConstant.CREATE, taskCreateHandler);
     handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
 }

2 初始化顺序 Constructor >> @Autowired >> @PostConstruct

因为上面的初始化时机的问题,使用@PostConstruct进行初始化:

@Component
public class TaskHandlerMapping
{
    
     Map<String, TaskEventTypeHandler> handlerList = new ConcurrentHashMap<>();
    @Autowired
    private  TaskCreateHandler taskCreateHandler;
    @Autowired
    private  TaskAssignmentHandler taskAssignmentHandler;

    //这样可以初始化
    @PostConstruct
    public void config()
    {
        handlerList.put(TaskConstant.CREATE, taskCreateHandler);
        handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
    }
    //用static初始化就不行,taskCreateHandler和taskAssignmentHandler都为null,因为static初始化太早了
  //   static {
  //       handlerList.put(TaskConstant.CREATE, taskCreateHandler);
  //       handlerList.put(TaskConstant.ASSIGNMENT, taskAssignmentHandler);
   //  }
    
    public TaskEventTypeHandler getHandler(String eventName)
    {
        return handlerList.get(eventName);
    }

}

版权声明:本文为whxwkb原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。