spirng framework源码解析之spring-core-order注解(七)

754 阅读3分钟

这是我参与8月更文挑战的第七天,活动详情查看:8月更文挑战

Order规定执行的先后顺序的一个注解,默认值为INT_MAX, 值越低优先级就越搞,并不会影响启动的顺序,影响启动顺序的是依赖关系和@DependsOn有关,也就是说如果想约定启动的顺序可以用@DependsOn来解决,另外接口Ordered也可以实现排序的功能,实现其getOrder方法即可:

public interface Ordered {

   int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
   int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
   // 用法与@Order注解类似,只是一个是注解一个是基于接口
   int getOrder();

然后使用OrderUtils抽象工具类进行封装处理,考虑到性能问题,这里spring采用Map的子类ConcurrentReferenceHashMap进行本地缓存。该子类的源码中是这样描述的如果未明确指定,此实现将默认使用软引用(java引用类型)。这种引用类型的作用就是告诉GC,当内存不足时,哪些是不重要的。而软引用类型就是这样的一类。若是回收后,还是内存不足那么才会抛出 OutOfMemory 错误,软引用类型十分适合缓存场景,感兴趣的同学可以试试。ok,我们继续别扯太远了,它最终是通过AnnotationAwareOrderComparator.sort()实现的,而AnnotationAwareOrderComparator继承了OrderComparator类,而OrderComparator又实现了java.util.Comparator接口,从而实现了排序的功能,这也就是它为什么可以进行排序处理的原理。ok,我们来验证下

首先新建子项目,继承父依赖的版本,只导入以下maven包即可

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
</dependency>
/**
 * @author dongqin
 * @description order注解 比较器测试
 * @date 2021/08/06
 */
public class AnnotationAwareOrderComparatorTest {

    private final static Log LOG = LogFactory.getLog(AnnotationAwareOrderComparatorTest.class);

    private static List<Object> listObject = new ArrayList<>(2);

    public static void main(String[] args) {
        listObject.add(new Role());
        listObject.add(new User());
        
        // 日志输出排序前的结果
        doPrintLogByIndex(0);
        doPrintLogByIndex(1);
        
        if (LOG.isInfoEnabled()) {
            LOG.info("开始执行[AnnotationAwareOrderComparator#sort(List list)]");
        }
        
        // 进行排序
        AnnotationAwareOrderComparator.sort(listObject);
        
        // 日志输出排序后的结果
        doPrintLogByIndex(0);
        doPrintLogByIndex(1);
    }

    /**
     * 通过索引打印日志
     *
     * @param index 索引
     */
    public static void doPrintLogByIndex(int index) {
        Object o = listObject.get(index);
        if (o instanceof User) {
            if (LOG.isInfoEnabled()) {
                LOG.info(String.format("第[%d]个执行的是类:[%s]", ++ index , User.class.getName()));
            }
            return;
        }
        if (LOG.isInfoEnabled()) {
            StringBuffer buffer = new StringBuffer();
            buffer.append("第[");
            buffer.append(++ index);
            buffer.append("]个执行的是类:[");
            buffer.append(Role.class.getName());
            buffer.append("]");
            LOG.info(buffer.toString());
        }
    }
}

@Order(-200)
class User {

    @Override
    public String toString() {
        return "User{}";
    }
}

@Order(2)
class Role {
    @Override
    public String toString() {
        return "Role{}";
    }
}

运行main方法,结果如下所示

Connected to the target VM, address: '127.0.0.1:20869', transport: 'socket'
八月 07, 2021 12:37:06 上午 com.dqcer.dxptools.core.order.AnnotationAwareOrderComparatorTest doPrintLogByIndex
信息: 第[1]个执行的是类:[com.dqcer.dxptools.core.order.Role]
八月 07, 2021 12:37:06 上午 com.dqcer.dxptools.core.order.AnnotationAwareOrderComparatorTest doPrintLogByIndex
信息: 第[2]个执行的是类:[com.dqcer.dxptools.core.order.User]
八月 07, 2021 12:37:06 上午 com.dqcer.dxptools.core.order.AnnotationAwareOrderComparatorTest main
信息: 开始执行[AnnotationAwareOrderComparator#sort(List list)]
八月 07, 2021 12:37:06 上午 com.dqcer.dxptools.core.order.AnnotationAwareOrderComparatorTest doPrintLogByIndex
信息: 第[1]个执行的是类:[com.dqcer.dxptools.core.order.User]
八月 07, 2021 12:37:06 上午 com.dqcer.dxptools.core.order.AnnotationAwareOrderComparatorTest doPrintLogByIndex
信息: 第[2]个执行的是类:[com.dqcer.dxptools.core.order.Role]
Disconnected from the target VM, address: '127.0.0.1:20869', transport: 'socket'

Process finished with exit code 0

通过实践证明了通过AnnotationAwareOrderComparator.sort()确实能够实现排序功能.