предисловие
Когда я недавно просматривал фреймворк, я нашел этот интерфейс, и я подытожу его здесь, надеясь помочь всем и в то же время улучшить себя.
Общее введение в интерфейс заказа
В фреймворке Spring есть интерфейс под названием Ordered.Подумайте об Ordered, который мы применили к базе данных.Легко подумать, что его значение используется для сортировки. Итак, вопрос в том, почему такой интерфейс сортировки должен быть определен в Spring? Мы знаем, что Spring Framework использует множество шаблонов разработки стратегий. Паттерн разработки стратегии означает, что у нас есть большое количество различных реализаций одного и того же интерфейса. Итак, при таком количестве реализаций, какая из них выполняется первой, а какая позже? Это создает проблему упорядочения и расстановки приоритетов, поэтому для решения этой проблемы вводится интерфейс Ordered.
Формальное введение в упорядоченный интерфейс
Во-первых, давайте посмотрим на интерфейс Ordered через исходный код spring, Исходный код выглядит следующим образом:
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
Из приведенного выше кода видно, что реализация упорядоченного интерфейса очень проста. Существует наивысший приоритет и самый низкий приоритет, а также предоставляет метод для получения значения порядка текущего класса реализации. в порядке весны. Чем меньше значение, тем выше приоритет, чем больше значение, тем ниже приоритет.
Применение заказанного интерфейса
После представления упорядоченного интерфейса давайте взглянем на реальный сценарий приложения. Существует типичный сценарий, мы знаем, что управление транзакциями Spring реализовано через аспект aop. Когда мы пишем собственную реализацию aop, мы сокращаем часть кода одновременно с транзакционным аспектом. Итак, кто должен выполнить Spring первым? В качестве конкретного примера мы написали аспект, который переключает источник данных. Если выполнение транзакции предшествует переключению источника данных, то переключение источника данных завершается ошибкой. Мы определенно хотим сначала выполнить переключение источника данных, а затем выполнить транзакцию. Так приходит сценарий применения заказанного. Предположим, мы пишем следующий аспект.
@Component
@Aspect
public class ChangeDataBase implements Ordered {
//拦截所有的service操作
@Pointcut("execution( * com.color.*.service.*.*(..))")
public void point() {
}
@Before("point()")
public void onlyReadPre() {
DataSourceContextHolder.setDataSourceType(DataSourceType.MYSQL);
System.out.println("数据库切换MYSQL");
}
@After("point()")
public void onlyReadPast() {
DataSourceContextHolder.setDataSourceType(DataSourceType.ORACLE);
System.out.println("数据库切换回ORACLE");
}
@Override
public int getOrder() {
return 1;
}
}
В приведенном выше коде мы определяем pointcut для перехвата всех сервисных методов. Затем перед выполнением метода мы переключаем базу данных на mysql, а после выполнения метода базу данных переключаем на oracle. Наконец, перепишите метод getOrder заказанного интерфейса. Здесь мы устанавливаем уровень порядка на 1. В настоящее время мы настраиваем аспект транзакции. Настройте порядок в xml.
<tx:annotation-driven transaction-manager="transactionManager" order="2"/>
Если вы используете метод внедрения bean-компонентов, вы можете напрямую реализовать интерфейс и использовать его, как указано выше. В это время мы узнаем. Метод переключения источника данных всегда будет выполняться перед транзакцией, которая достигает нашей цели.
Использование аннотации заказа
Читатели, дочитавшие до сих пор, думают, что реализовать интерфейс слишком хлопотно, есть ли более удобный способ? Конечно, давайте введем аннотацию @Order. Давайте сначала посмотрим на исходный код аннотации заказа.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
int value() default 2147483647;
}
Приоритет по умолчанию наименьший. Когда мы его используем, нам нужно только отметить порядок в классе. Мы моделируем два класса, аннотируем их порядком, а затем загружаем класс с пустым конструктором параметров при запуске контейнера Spring.Благодаря печати в конструкторе пустых параметров мы можем видеть порядок инициализации и выполнения класса. Создайте наш первый класс порядка.
@Component
//使用order属性,设置该类在spring容器中的加载顺序
@Order(1)
public class Order1 {
private final int ORDERED = 1;
public Order1(){
System.out.println(this);
}
@Override
public String toString() {
return "Order1 is loaded @ORDERED=" + ORDERED + "]";
}
}
Создайте наш второй класс порядка.
@Component
//使用order属性,设置该类在spring容器中的加载顺序
@Order(2)
public class Order2 {
private final int ORDERED = 2;
public Order2(){
System.out.println(this);
}
@Override
public String toString() {
return "Order2 is loaded @ORDERED=" + ORDERED + "]";
}
}
После запуска контейнера spring мы видим следующие результаты в консольном выполнении.
Order1 is loaded @ORDERED=1]
Order2 is loaded @ORDERED=2]
Введение orderComparator
Итак, если мы хотим узнать порядковое значение класса или сравнить порядковое значение двух классов, большего и меньшего, как нам действовать на этот раз? Spring предоставляет нам класс. OrderComparator, через этот класс, после того, как мы получим экземпляр, мы можем использовать методы getOrder или сравнения, предоставленные им, для достижения вышеуказанных требований. Как обычно, давайте сначала посмотрим на исходный код.
public class OrderComparator implements Comparator<Object> {
public static final OrderComparator INSTANCE = new OrderComparator();
public OrderComparator() {
}
public Comparator<Object> withSourceProvider(OrderComparator.OrderSourceProvider sourceProvider) {
return (o1, o2) -> {
return this.doCompare(o1, o2, sourceProvider);
};
}
public int compare(@Nullable Object o1, @Nullable Object o2) {
return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
boolean p1 = o1 instanceof PriorityOrdered;
boolean p2 = o2 instanceof PriorityOrdered;
if (p1 && !p2) {
return -1;
} else if (p2 && !p1) {
return 1;
} else {
int i1 = this.getOrder(o1, sourceProvider);
int i2 = this.getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
}
private int getOrder(@Nullable Object obj, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
Object[] sources = ObjectUtils.toObjectArray(orderSource);
Object[] var6 = sources;
int var7 = sources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Object source = var6[var8];
order = this.findOrder(source);
if (order != null) {
break;
}
}
} else {
order = this.findOrder(orderSource);
}
}
}
return order != null ? order.intValue() : this.getOrder(obj);
}
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = this.findOrder(obj);
if (order != null) {
return order.intValue();
}
}
return 2147483647;
}
@Nullable
protected Integer findOrder(Object obj) {
return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
}
@Nullable
public Integer getPriority(Object obj) {
return null;
}
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
public static void sortIfNecessary(Object value) {
if (value instanceof Object[]) {
sort((Object[])((Object[])value));
} else if (value instanceof List) {
sort((List)value);
}
}
@FunctionalInterface
public interface OrderSourceProvider {
@Nullable
Object getOrderSource(Object var1);
}
}
Сначала сосредоточимся на методе doCompare. Логика судебного решения следующая: Если объект o1 имеет тип интерфейса Ordered, а o2 — тип интерфейса PriorityOrdered, то приоритет o2 выше, чем у o1. Если объект o1 относится к интерфейсному типу PriorityOrdered, а o2 — к интерфейсному типу Ordered, то приоритет o1 выше, чем у o2. В других случаях, если оба являются типами интерфейса Ordered или оба являются типами интерфейса PriorityOrdered, вызовите метод getOrder интерфейса Ordered, чтобы получить значение порядка.Чем больше значение порядка, тем меньше приоритет. Так что одним словом это так. При сортировке OrderComparator, если один из двух объектов реализует интерфейс PriorityOrdered, приоритет этого объекта выше. Если оба объекта относятся к классу PriorityOrdered или классу реализации интерфейса Ordered, сравните метод getOrder интерфейса Ordered, чтобы получить значение порядка. Чем ниже значение, тем выше приоритет.
Давайте еще раз посмотрим на метод getOrder. После передачи объекта получите исходный объект через поставщика. Если он не пустой, продолжайте судить. Если это объект массива, обойдите объект, получите заказ и выпрыгните. Если это не массив, порядок объекта получается напрямую. Наконец, если ордер не пустой, то возвращается значение int ордера напрямую, когда он пустой, он просматривается через findOrder, и возвращается максимальное значение ордера, то есть самый низкий приоритет.
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = this.findOrder(obj);
if (order != null) {
return order.intValue();
}
}
return 2147483647;
}
Суммировать
Пока внесены порядковые вещи пока.В тексте неизбежны недочеты.Надеюсь все смогут внести поправки,спасибо.