Сортировать пружину @Beans по уровню метода @Заказ аннотации - PullRequest
5 голосов
/ 27 мая 2019

Моя библиотека имеет дело с несколькими bean-компонентами (перехватчиками), которые указаны в произвольном порядке (потому что они распределены по нескольким файлам конфигурации). Прежде чем я смогу применить их, я должен отсортировать их по приоритету. Я использую AnnotationAwareOrderComparator.sort(beans) для этого. Это хорошо работает до тех пор, пока на уровне класса этого перехватчика добавляется аннотация @Order. Но он не работает, когда я пытаюсь использовать его в классах @Configuration для методов @Bean:

@Configuration
public class Config {

    @Bean
    @Order(1)
    public ServerInterceptor exceptionTranslatingServerInterceptor() {
        return ...;
    }

    @Bean
    @Order(2)
    public ServerInterceptor authenticatingServerInterceptor() {
        return ...;
    }

    @Bean
    @Order(3)
    public ServerInterceptor authorizationCheckingServerInterceptor() {
        return ...
    }

}

Но если я добавлю такой тест:

@Test
void testOrderingOfTheDefaultInterceptors() {
    List<ServerInterceptor> expected = new ArrayList<>();
    expected.add(applicationContext.getBean(ExceptionTranslatingServerInterceptor.class));
    expected.add(applicationContext.getBean(AuthenticatingServerInterceptor.class));
    expected.add(applicationContext.getBean(AuthorizationCheckingServerInterceptor.class));

    List<ServerInterceptor> actual = new ArrayList<>(this.registry.getServerInterceptors());
    assertEquals(expected, actual); // Accidentally passes
    // System.out.println(actual);

    Collections.shuffle(actual);
    AnnotationAwareOrderComparator.sort(actual);
    assertEquals(expected, actual); // Fails
    // System.out.println(actual);
}

Тогда тест не пройден. Из своей отладки я знаю, что AnnotationAwareOrderComparator.findOrder(Object) всегда возвращает ноль (не указано) для порядка этих бинов. Возможно, потому что экземпляры bean-компонентов не проксируются и, таким образом, не реализуют порядок и не имеют аннотации порядка на своем уровне класса. Есть ли BeanPostProcessor или опция конфигурации, которую я должен включить?

Controll-Flow

Как мне сказать Spring либо сохранить аннотированный порядок, либо использовать определения bean-компонентов контекста приложения для соответствующей сортировки bean-компонентов?

1 Ответ

1 голос
/ 01 июня 2019

Чтобы ваш тестовый сценарий работал, вам нужно использовать интерфейс Ordered вместо аннотации.Давайте рассмотрим исходный код AnnotationAwareOrderComparator.Обратите внимание, что вы передаете объекты напрямую в метод сортировки.AnnotationAwareOrderComparator использует findOrder на помещенных объектах, чтобы найти один из трех артефактов @Priority annotation @Order annotation или @Ordered interface.В вашем случае вы передаете экземпляры перехватчика, поэтому проверка if для Methidf и для Class вернет false.Вы нажмете последний метод if: if (obj != null)

, в этом случае он просто проверит ваши классы объектов на аннотацию @Order, которая в вашем случае будет нулевой.Эффективно ваш контрольный пример просто неверен.Однако обратите внимание, что ваш тестовый сценарий будет работать так, как ожидается, если вы реализуете заказанный интерфейс.

public static void sort(List list) {
        if (list.size() > 1) {
            Collections.sort(list, INSTANCE);
        }
    }

protected Integer findOrder(Object obj) {
        // Check for regular Ordered interface
        Integer order = super.findOrder(obj);
        if (order != null) {
            return order;
        }

        // Check for @Order and @Priority on various kinds of elements
        if (obj instanceof Class) {
            return OrderUtils.getOrder((Class) obj);
        }
        else if (obj instanceof Method) {
            Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
            if (ann != null) {
                return ann.value();
            }
        }
        else if (obj instanceof AnnotatedElement) {
            Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
            if (ann != null) {
                return ann.value();
            }
        }
        else if (obj != null) {
            return OrderUtils.getOrder(obj.getClass());
        }

        return null;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...