"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Explorando Feijões Sintéticos em Quarkus. Um poderoso mecanismo de extensão

Explorando Feijões Sintéticos em Quarkus. Um poderoso mecanismo de extensão

Publicado em 2024-09-02
Navegar:539

Exploring Synthetic Beans in Quarkus. A Powerful Extension Mechanism

No mundo do Quarkus, o domínio da injeção de dependência é rico e versátil, oferecendo aos desenvolvedores uma infinidade de ferramentas para gerenciar e controlar beans. Uma dessas ferramentas é o conceito de feijão sintético. Os beans sintéticos são um poderoso mecanismo de extensão que permite registrar beans cujos atributos não são derivados de uma classe, método ou campo Java. Em vez disso, todos os atributos de um bean sintético são definidos por uma extensão.

Neste artigo, vamos nos aprofundar no mundo dos feijões sintéticos no Quarkus. Exploraremos a necessidade dos feijões sintéticos, suas aplicações práticas e como criá-los e usá-los em suas aplicações Quarkus.

Compreendendo o feijão sintético

No Quarkus, os beans são os blocos de construção da sua aplicação, gerenciados pela estrutura Contexts and Dependency Injection (CDI). Normalmente, os beans CDI são classes Java anotadas com várias anotações CDI, como @ApplicationScoped, @RequestScoped ou @Inject. Essas anotações
permitir que o CDI gerencie automaticamente o ciclo de vida e a injeção de beans.

No entanto, há situações em que você pode precisar registrar um bean que não se encaixa perfeitamente no modelo CDI tradicional. É aqui que entra o feijão sintético. Os beans sintéticos são criados por extensões e têm seus atributos totalmente definidos por essas extensões. No mundo do CDI normal, você conseguiria isso usando os métodos AfterBeanDiscovery.addBean() e SyntheticComponents.addBean(). No Quarkus, isso é feito usando SyntheticBeanBuildItem.

Quando você precisa de feijão sintético?

Então, quando você pode precisar usar feijões sintéticos no Quarkus? Os feijões sintéticos são uma ferramenta poderosa quando:

  1. Integração de bibliotecas de terceiros: Você está trabalhando com uma biblioteca de terceiros que não possui anotações de CDI, mas precisa ser integrada ao seu aplicativo baseado em CDI. Os feijões sintéticos permitem preencher essa lacuna.

  2. Registro Dinâmico de Bean: Você precisa registrar beans dinamicamente em tempo de execução, dependendo da configuração ou de outros fatores. Os feijões sintéticos oferecem flexibilidade para criar e registrar feijões dinamicamente.

  3. Gerenciamento de Bean Personalizado: Você precisa de um controle refinado sobre o escopo e o comportamento de um bean que não pode ser alcançado com anotações CDI padrão.

  4. Implementando Beans Especializados: Você deseja criar beans especializados com atributos exclusivos que não correspondem às classes ou métodos Java tradicionais.

  5. Mocking Dependency for Testing: Os beans sintéticos fornecem uma maneira útil de simular dependências e injetar implementações simuladas para fins de teste.

SínteseFinishedBuildItem

O SynthesisFinishedBuildItem é usado para indicar que o processo de descoberta e registro do bean CDI foi concluído. Isso permite que as extensões saibam quando é seguro interagir com os beans que foram registrados.

Por exemplo:

@BuildStep  
void onSynthesisFinished(SynthesisFinishedBuildItem synthesisFinished){
    // CDI bean registration is complete, can now safely interact with beans
    }

SyntheticBeansRuntimeInitBuildItem

O SyntheticBeansRuntimeInitBuildItem é usado para registrar um retorno de chamada que será invocado em tempo de execução após todos os beans sintéticos terem sido inicializados. Isso é útil se você precisar executar lógica de inicialização adicional envolvendo beans sintéticos.

Por exemplo:

@BuildStep
SyntheticBeansRuntimeInitBuildItem initSyntheticBeans(){

    return new SyntheticBeansRuntimeInitBuildItem(ids->{
    // Perform logic with initialized synthetic beans
    });

    }

O retorno de chamada passado para SyntheticBeansRuntimeInitBuildItem receberá um Set contendo os IDs de todos os beans sintéticos inicializados.

Então, em resumo, SynthesisFinishedBuildItem indica que a descoberta do bean foi concluída, enquanto SyntheticBeansRuntimeInitBuildItem permite inicializar a lógica dependendo dos beans sintéticos.

Criando Beans Sintéticos com SyntheticBeanBuildItem

No Quarkus, criar beans sintéticos é um processo simples, graças à classe SyntheticBeanBuildItem. Vamos seguir as etapas para criar e usar um bean sintético:

  1. Crie a classe do feijão sintético: Comece definindo a classe do feijão sintético. Esta aula será a base do seu feijão sintético.
package com.iqnev;

public class MySyntheticBean {

  // Define the behavior and attributes of your synthetic bean
  public void printMessage() {
    System.out.println("Hello from synthetic bean!");
  }
}
  1. Crie uma extensão Quarkus: Você precisará criar uma extensão Quarkus para registrar seu feijão sintético. Esta classe de extensão usará SyntheticBeanBuildItem para configurar seu bean.

Abordagem de geração de bytecode

package com.iqnev;

import io.quarkus.arc.deployment.SyntheticBeanBuildItem;

public class MySyntheticBeanExtension {

  @BuildStep
  SyntheticBeanBuildItem syntheticBean() {
    return SyntheticBeanBuildItem
        .configure(MySyntheticBean.class)
        .scope(ApplicationScoped.class)
        .creator(mc -> {
          mc.returnValue(new MySyntheticBean());
        })
        .done();
  }
}

O método .creator() em SyntheticBeanBuildItem é usado para gerar o bytecode que criará instâncias do bean sintético em tempo de execução.

O argumento passado para .creator() é um Consumer que permite gerar bytecode Java dentro de um método.

Neste exemplo:

  1. mc é a instância do MethodCreator
  2. mc.returnValue(new MySyntheticBean()) gera o bytecode para criar uma nova instância de MySyntheticBean e retorná-lo do método.

Então, essencialmente, estamos dizendo ao Quarkus para gerar um método parecido com:

MySyntheticBean createSyntheticBean(){
    return new MySyntheticBean();
    }

Este método gerado será então chamado para instanciar o MySyntheticBean quando ele precisar ser injetado ou usado.

A razão pela qual a geração de bytecode é usada é que os beans sintéticos não correspondem a classes/métodos Java reais, então temos que gerar explicitamente um método para instanciá-los

A saída de SyntheticBeanBuildItem é um bytecode registrado no momento da construção. Isso limita como as instâncias são criadas em tempo de execução. As opções comuns são:

  1. Gere bytecode diretamente via .creator()
  2. Use uma subclasse BeanCreator
  3. Produzir instância via método @Recorder

Abordagem do gravador

As abordagens @Record e .runtimeValue() são formas alternativas de fornecer instâncias para beans sintéticos no Quarkus.

Isso permite instanciar o bean sintético por meio de um método de classe de gravador anotado com @Record(STATIC_INIT).

Por exemplo:

@Recorder
public class MyRecorder {

  @Record(STATIC_INIT)
  public MySyntheticBean createBean() {
    return new MySyntheticBean();
  }

}

  @BuildStep
  SyntheticBeanBuildItem syntheticBean(MyRecorder recorder) {
    return SyntheticBeanBuildItem
        .configure(MySyntheticBean.class)
        .runtimeValue(recorder.createBean());
  }

Aqui o .runtimeValue() faz referência ao método recorder para instanciar o bean. Isso permite passar um RuntimeValue diretamente para fornecer a instância do bean sintético.

Por exemplo:

@BuildStep 
SyntheticBeanBuildItem syntheticBean(){

    RuntimeValue bean= //...

    return SyntheticBeanBuildItem
    .configure(MySyntheticBean.class)
    .runtimeValue(bean);

    }

O RuntimeValue pode vir de um gravador, fornecedor, proxy etc.

Então, em resumo:

  • @Record é uma abordagem para gerar o RuntimeValue
  • .runtimeValue() define o RuntimeValue no SyntheticBeanBuildItem

Ambos atingem o mesmo objetivo de fornecer uma instância de tempo de execução, apenas de maneiras ligeiramente diferentes.

Quando se trata de fornecer instâncias de tempo de execução para beans sintéticos no Quarkus, eu consideraria o uso de gravadores (via @Record) como uma abordagem mais avançada em comparação à geração direta de bytecode
com .creator() ou fornecendo RuntimeValues ​​simples.

Aqui estão alguns motivos pelos quais o uso de gravadores pode ser mais avançado:

  • Mais encapsulamento - A lógica para instanciar beans está contida em uma classe de gravador separada, em vez de diretamente nas etapas de construção. Isso mantém as etapas de construção simples.
  • Reutilizar - Os métodos do gravador podem ser reutilizados em vários beans sintéticos em vez de reescrever a lógica do criador.
  • Dados de tempo de execução - Os métodos do gravador são executados em tempo de execução para que possam aproveitar recursos de tempo de execução, configurações, serviços, etc., para construir beans.
  • Injeção de dependência - Os métodos do gravador podem injetar outros serviços.
  • Controle do ciclo de vida - Os métodos do gravador anotados com @Record(STATIC_INIT) ou @Record(RUNTIME_INIT) fornecem mais controle sobre o ciclo de vida da instanciação do bean.
  • Feans gerenciados - Beans instanciados dentro de gravadores podem ser beans gerenciados por CDI.

Então, em resumo, os métodos de gravador fornecem mais encapsulamento, flexibilidade e acesso a dados e serviços de tempo de execução para instanciar beans sintéticos. Eles permitem uma lógica de produção de bean mais avançada em comparação com a geração direta de bytecode.

No entanto, a geração direta de bytecode com .creator() ainda pode ser útil para casos simples em que os gravadores podem ser um exagero. Mas à medida que as necessidades de feijão sintético aumentam, os gravadores são mais poderosos e
abordagem avançada.

É possível configurar um bean sintético no Quarkus para ser inicializado durante a fase RUNTIME_INIT em vez da fase STATIC_INIT padrão.

Aqui está um exemplo:

@BuildStep
@Record(RUNTIME_INIT)
SyntheticBeanBuildItem lazyBean(BeanRecorder recorder){

    return SyntheticBeanBuildItem
    .configure(MyLazyBean.class)
    .setRuntimeInit() // initialize during RUNTIME_INIT
    .runtimeValue(recorder.createLazyBean());

    }

Os pontos principais são:

  • Use setRuntimeInit() no SyntheticBeanBuildItem para marcá-lo para RUNTIME_INIT
  • O método do gravador deve ser anotado com @Record(RUNTIME_INIT)
  • Os beans sintéticos de inicialização do tempo de execução não podem ser acessados ​​durante STATIC_INIT

Portanto, em resumo, os beans sintéticos podem ser inicializados lentamente durante RUNTIME_INIT para casos em que a instanciação antecipada de STATIC_INIT não é necessária. Isso permite otimizar o tempo de inicialização.

Usar o Feijão Sintético: Agora que seu feijão sintético está registrado, você pode injetá-lo e utilizá-lo em sua aplicação.

package com.iqnev;

import javax.inject.Inject;

public class MyBeanUser {

  @Inject
  MySyntheticBean mySyntheticBean;

  public void useSyntheticBean() {
    // Use the synthetic bean in your code
    mySyntheticBean.printMessage();
  }
}

Executando seu aplicativo: Crie e execute seu aplicativo Quarkus normalmente, e o bean sintético estará disponível para injeção e uso.

Conclusão

Beans sintéticos no Quarkus fornecem um mecanismo poderoso para integrar bibliotecas externas, registrar beans dinamicamente e personalizar o comportamento do bean em seus aplicativos baseados em CDI. Esses beans, cujos atributos são definidos por extensões em vez de classes Java, oferecem flexibilidade e versatilidade no gerenciamento de dependências.

Como exploramos neste artigo, criar e usar beans sintéticos no Quarkus é um processo simples. Ao aproveitar as extensões SyntheticBeanBuildItem e Quarkus, você pode preencher perfeitamente a lacuna entre o CDI tradicional e os requisitos de registro de beans mais especializados ou dinâmicos.

No cenário em constante evolução das estruturas Java, a Quarkus continua a se destacar por oferecer soluções inovadoras como beans sintéticos, tornando-se uma escolha atraente para o desenvolvimento de aplicações modernas, eficientes e flexíveis. Aproveite o poder dos feijões sintéticos no Quarkus e leve sua injeção de dependência para o próximo nível!

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/yanev/exploring-synthetic-beans-in-quarkus-a-powerful-extension-mechanism-fbd?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3