Автонастройка для RestRepositoryResource

Я хотел бы добиться автоматической настройки RestRepositoryResource (и некоторых дополнительных стандартных функций) для объекта. Я пытаюсь добиться этого с помощью аннотации к аннотированному классу @Configuration или @SpringBootApplication.

что-то вроде этого:

@EnableRestRepo(single = "foo", collection = "foos",entity=Foo.class, id=String.class)
@SpringBootApplication
public class App{
    public void main(String[] args){
        SpringApplication.run(App.class,args);
    }
}


@Entity
public class Foo{
    String id;
    String bar;   
    ... getters & setters   
}

затем это должно настроить (или аналогичную функциональность, я могу создать свои собственные конечные точки, если это необходимо) @RestRepositoryResource следующим образом:

@RestRepositoryResource(itemResourceRel = "foo", collectionResourceRel = "foos")
public interface Repo extends CrudRepository<Foo,String> {

    @RestResource(rel = "foo")
    Foo findOneById(@Param("id") String id);
}

Цель здесь состоит в том, чтобы уменьшить некоторые шаблоны при настройке некоторых основных функций. Очевидно, что этот пример будет дополнен некоторыми дополнительными элементами автоконфигурации, но это должно работать аналогичным образом.

Вопрос не столько в RestRepositoryResource, сколько в автоконфигурации с аннотациями, для которых требуются аргументы и классы универсального типа. Я был бы не против потратить некоторое время на реализацию этого, однако я понятия не имею, с чего начать.

Возможно ли что-то подобное, и если да, то как?

что вы думаете о этот подход?

xerx593 10.02.2019 22:32

Я видел этот пост, и он дает некоторые подсказки о подключении классов с аннотациями, однако это заставит меня реализовать постоянство самостоятельно, и я не хотел бы касаться этого, но ввел бы его на основе конфигурации. Например, я не хочу навязывать SQL или nosql.

p.streef 11.02.2019 07:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
2
243
1

Ответы 1

Не уверен, что понял вас на 100%, но пример кода здесь работает нормально и создает среду выполнения bean-компонентов на основе аннотации. Аннотация также имеет некоторые метаданные.

Общий интерфейс будет проксирован позже:

public interface GenericRepository<T extends GenericType, Long> extends JpaRepository<GenericType, Long> {

}

Аннотации для разных сущностей:

@Target(ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@OverrideAutoConfiguration(enabled = false)
@ImportAutoConfiguration
@Import({RestResourceAutoConfiguration.class})
public @interface EnableRestRepo {
  Class<?> entity();
  String id();
}

Класс конфигурации, который может регистрировать bean-компоненты во время выполнения:

@Configuration
@AutoConfigureAfter(value = WebMvcAutoConfiguration.class)
@ConditionalOnClass({CrudRepository.class})
public class RestResourceAutoConfiguration implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
      Reflections reflections = new Reflections("jav");
      Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(EnableRestRepo.class);
      for (Class<?> c : annotated) {
        EnableRestRepo declaredAnnotation = c.getDeclaredAnnotation(EnableRestRepo.class);
        Class<?> entity = declaredAnnotation.entity();
        String id = declaredAnnotation.id();
        Supplier<GenericRepository> genericRepositorySupplier = () -> (GenericRepository) Proxy.newProxyInstance( // register a proxy of the generic type in spring context
                c.getClassLoader(),
                new Class[]{GenericRepository.class},
                new MyInvocationHandler(entity));
            beanDefinitionRegistry.registerBeanDefinition(id + "-" + UUID.randomUUID().toString(),
                    new RootBeanDefinition(GenericRepository.class, genericRepositorySupplier)
        );
    }
}

spring.factories под META-INF

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
jav.RestResourceAutoConfiguration

Я думаю, что это правильное направление, я думаю. Моя цель состоит в том, чтобы иметь эту аннотацию один раз в основном классе приложения Spring Boot (или аннотированном классе @configuration), который автоматически настраивает микросервисы вокруг одного объекта/ресурса. Затем, используя другие аннотации, можно подключить дополнительные функции, такие как проверка и дополнительные шаги перед основными грубыми действиями. Поэтому, если возможно, я бы хотел, чтобы потребитель не объявлял свой собственный репозиторий просто объектом, именем отношения и базовым классом приложения загрузки Spring (как минимум). Дополню вопрос, когда снова буду за компом.

p.streef 11.02.2019 08:11

Другие вопросы по теме