Micronaut - создание, получение и уничтожение bean-компонентов ApplicationContext

Мне необходимо динамически создавать и уничтожать HttpClient объекты, чтобы соответствовать клиентам, которые регистрируются / отменяют регистрацию в моем приложении Micronaut. В рамках этого я хочу добавить их как beans в контекст приложения, чтобы они автоматически использовали пользовательские HttpFilters также в проекте.

Я думал, что будет довольно просто управлять этими bean-компонентами, используя ApplicationContext методы bean-компонентов с именем Qualifier, чтобы отслеживать их, но то, как эти API-интерфейсы, кажется, ведут себя, меня сбивает с толку:

  1. applicationContext.createBean(HttpClient.class, Qualifiers.byName("myLabel"), myUrl) не работает с:
io.micronaut.context.exceptions.NoSuchBeanException: No bean of type 
[io.micronaut.http.client.HttpClient] exists. Make sure the bean is not disabled by bean 
requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the 
bean is enabled then ensure the class is declared a bean and annotation processing is 
enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as 
an annotation processor).

Почему важно, существует ли компонент? Я пытаюсь его создать!

  1. applicationContext.findBean(HttpClient.class) не работает с:
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type  [io.micronaut.http.client.DefaultHttpClient]

Message: Missing bean argument [LoadBalancer loadBalancer] for type: io.micronaut.http.client.DefaultHttpClient. Required arguments: LoadBalancer loadBalancer,HttpClientConfiguration configuration,String contextPath,HttpClientFilterResolver filterResolver

Почему он пытается его создать? Я просто хочу его найти!

(ПРИМЕЧАНИЕ. applicationContext.getBean(HttpClient.class, Qualifiers.byName("myLabel")) может работать здесь, но поскольку я не смог решить первый пункт, я не смог это проверить)

  1. applicationContext.destroyBean(HttpClient.class) не позволяет указывать Qualifier в методе, что означает, что я не могу использовать его для удаления bean-компонента из контекста. Он также возвращает null после создания bean-компонента без квалификатора (applicationContext.createBean(HttpClient.class, myUrl)), что говорит о том, что он все равно не может найти созданный bean-компонент ...

Полагаю, я использую неправильный API, но какой правильный?

В общем, я полностью запутался - любая помощь по правильному использованию этих API будет приветствоваться.


person user2521119    schedule 19.03.2021    source источник


Ответы (1)


HttpClient - это интерфейс, предназначенный для определения http-клиента, но не bean-компонента (обратите внимание, что реализация по умолчанию ~ DefaultHttpClient ~, предоставляемая Micronaut, не является bean-компонентом). Следовательно, любые вызовы упомянутых ApplicationContext методов поиска или создания контекста приведут к ошибкам:

  • ApplicationContext#createBean
  • ApplicationContext#findBean
  • ApplicationContext#getBean
  • ... // другие методы создания экземпляров

Обратите внимание, что это сделано намеренно, поскольку API HttpClient предназначен для автоматического внедрения и работы с рекомендациями АОП.

Вы можете ввести необработанный (с помощью методов по умолчанию) HttpClient:

@Singleton
public class MyBeanIml implements MyBean {

  @Client
  HttpClient client;

  // ...
}

Или для пользовательских методов, сгенерированной реализации, вы можете использовать HttpClient декларативную реализацию:

@Client("endpoint-uri")
public interface MyHttpClient {

  @Get
  String query();

  // ...
}

Не указывая точных требований для создания пользовательских (динамических, кстати, слишком расплывчатых в этом контексте) HttpClients, вы можете использовать собственный bean-компонент @Prototyped, обертывающий внедренный HttpClient, которые могут быть созданы с вашими пользовательскими параметрами, и где вы делегируете свои методы упакованному HttpClient или реализуете свои собственные методы:

@Prototype
public class CustomHttpClientImpl implements CustomHttpClientImpl.CustomHttpClient {

    @Inject
    @Client
    private final HttpClient httpClient;

    private final String endpoint;

    public CustomHttpClientImpl(@Parameter String endpoint, HttpClient httpClient) {
        this.httpClient = httpClient;
        this.endpoint = endpoint;
    }

        @Override
    public String query() {
        return this.httpClient.toBlocking()
                .exchange(HttpRequest.GET(URI.create(this.endpoint)), String.class)
                .body();
    }
    
    // delegate to the `httpClient` bean or implement your custom API querying methods

    public interface CustomHttpClient {

        String query();
    }
}

Затем вы можете создать свои экземпляры bean-компонентов Prototyped, используя ApplicationContext:

applicationContext.createBean(CustomHttpClient.class, "som-uri-for-custom-client");
person tmarwen    schedule 20.03.2021