基于springboot应用Ordered接口

记录:275

场景:应用org.springframework.core.Ordered接口,从spring的IOC容器中取出bean实例,按照指定顺序执行bean的指定方法,比如初始化方法。执行顺序取Ordered接口实现类的getOrder方法返回值,按照从小到大排序,依次执行。本例按照从小到大,具体按需即可。

版本:Spring Boot 2.6.3

一、案例场景

1.三个类A、B、C都实现Ordered接口,并有init方法。

2.Spring容器加载完成A、B、C三个类后,需要按照指定顺序调用init方法。

3.本例调用init方法顺序是,C、B、A。

4.分别对A、B、C实现类的getOrder返回值设置为1223、1222、1221。

二、使用类

org.springframework.core.Ordered,排序接口。

java.util.ArrayList,在List中是按照写入顺序存放。

org.springframework.beans.factory.InitializingBean,初始化接口。允许一个bean在它的所有必须属性被BeanFactory设置后,来执行初始化的工作。实现afterPropertiesSet方法。

org.springframework.beans.factory.DisposableBean,销毁接口。允许在容器销毁该bean的时候获得一次回调。实现destroy方法。

org.springframework.util.CollectionUtils,有相关对集合的操作,比如isEmpty判断Map是否为空,判断Collection是否为空。

java.util.Collections,一个集合类,本例使用sort方法对入参的List进行排序,排序规则依据Comparator实现类。

java.util.Comparator,一个比较器接口,本例实现compare方法,排序List中对象顺序。

三、代码

1.IExampleOrdered接口

IExampleOrdered接口,继承Ordered。

public interface IExampleOrdered extends Ordered {
    void init();
    String getInitName();
}

2.AbstractExampleOrdered抽象类

AbstractExampleOrdered抽象类,实现IExampleOrdered接口。

public abstract class AbstractExampleOrdered 
        implements IExampleOrdered {
  @Override
  public String getInitName() {
      return this.getClass().getSimpleName();
  }
}

3.OrderedUtils工具类

OrderedUtils排序和调用实现类的init工具类。

@Slf4j
public class OrderedUtils {
  private static final List<IExampleOrdered> beanList = new ArrayList<>();
  /**
   * spring已经初始化过得bean添加到List中
   */
  public static void addBean(IExampleOrdered exampleOrdered) {
      if (exampleOrdered == null) return;
      beanList.add(exampleOrdered);
  }
  public static List<IExampleOrdered> getBeanList() {
      return beanList;
  }
  public static void handleBeans() {
  
   if (!CollectionUtils.isEmpty(beanList)) {
     // 使用的Collections.sort排序,取值是Ordered接口的getOrder()值
     Collections.sort(beanList, new handleComparator());
     log.info("handleBeans开始执行.");
     // 排序后getOrder()值更小的放在List更靠前位置
     for (IExampleOrdered exampleOrdered : beanList) {
       String printInfo = String.format("类: %s, getOrder值: %s",
            exampleOrdered.getInitName(),
            exampleOrdered.getOrder());
       try {
          log.info(printInfo + ",执行.");
          exampleOrdered.init();
       } catch (Exception e) {
          log.info(printInfo + ",异常.");
          e.printStackTrace();
       }
     }
     log.info("handleBeans执行完成.");
   }
  }
  private static class handleComparator implements Comparator<IExampleOrdered> {
      @Override
      public int compare(IExampleOrdered o1, IExampleOrdered o2) {
          return o1.getOrder() - o2.getOrder();
      }
  }
  public static void clear() {
      if (beanList.size() > 0) {
          beanList.clear();
      }
  }
}

4.HandleWorker

HandleWorker,实现InitializingBean和DisposableBean接口。本类由spring容器加载。触发调用实现Ordered排序接口的类的init方法。

@Slf4j
@Component
public class HandleWorker implements InitializingBean, DisposableBean {
  @Override
  public void afterPropertiesSet() throws Exception {
   log.info("HandleWorker->afterPropertiesSet开始执行.");
   try {
     ApplicationContext appContext = SpringUtil.getApplicationContext();
     Map<String, IExampleOrdered> beans = appContext.getBeansOfType(IExampleOrdered.class);
     if (!CollectionUtils.isEmpty(beans)) {
      Set<Map.Entry<String, IExampleOrdered>> entrySet = beans.entrySet();
      for (Map.Entry<String, IExampleOrdered> map : entrySet) {
          // 取出所有IExampleOrdered接口实现类
          OrderedUtils.addBean(map.getValue());
      }
      // 测试使用
      printBeanList();
      // 依次执行IExampleOrdered接口实现类的init函数
      OrderedUtils.handleBeans();
     }
   } catch (Exception e) {
       e.printStackTrace();
   }
   log.info("HandleWorker->afterPropertiesSet完成.");
  }
  @Override
  public void destroy() throws Exception {
   log.info("HandleWorker->destroy开始执行.");
   OrderedUtils.clear();
   log.info("HandleWorker->destroy完成.");
  }
  // 测试验证
  private void printBeanList() {
   List<IExampleOrdered> beanList = OrderedUtils.getBeanList();
   log.info("处理前beanList排序:");
   for (IExampleOrdered var : beanList) {
      String printInfo = String.format("类: %s, getOrder值: %s",
       var.getInitName(),
       var.getOrder());
      log.info(printInfo);
   }
  }
}

5.排序接口实现类

Ordered接口实现类ExampleStepServiceA、ExampleStepServiceB、ExampleStepServiceC。区别在于getOrder()获取的值不一样。

5.1 ExampleStepServiceA

ExampleStepServiceA类,getOrder()返回值:1223。

@Component
@Slf4j
public class ExampleStepServiceA 
       extends AbstractExampleOrdered {
  @Override
  public void init() {
    log.info("ExampleStepServiceA->init,执行.");
  }
  @Override
  public int getOrder() {
    return 1223;
  }
}

5.2 ExampleStepServiceB

ExampleStepServiceB类,getOrder()返回值:1222。

@Component
@Slf4j
public class ExampleStepServiceB 
    extends AbstractExampleOrdered {
 @Override
 public void init() {
     log.info("ExampleStepServiceB->init,执行.");
 }
 @Override
 public int getOrder() {
     return 1222;
 }
}

5.3 ExampleStepServiceC

ExampleStepServiceC类,getOrder()返回值:1221。

@Component
@Slf4j
public class ExampleStepServiceC extends AbstractExampleOrdered {
  @Override
  public void init() {
    log.info("ExampleStepServiceC->init,执行.");
  }
  @Override
  public int getOrder() {
    return 1221;
  }
}

6.测试

6.1 启动日志

HandleWorker的InitializingBean的afterPropertiesSet方法触发调用。

 6.2 关闭日志

HandleWorker的DisposableBean的destroy方法触发调用。

 以上,感谢。

2022年6月17日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值