JavaRush /Blogue Java /Random-PT /Estrutura Primavera. Introdução
Marchello
Nível 20
Санкт-Петербург

Estrutura Primavera. Introdução

Publicado no grupo Random-PT
Olá! Enquanto a administração do JavaRush trabalha em novos níveis, quero iniciar uma série de artigos de treinamento sobre o Spring Framework. Sim, eu sei que já existe muito material sobre esse assunto na Internet, mas, como mostra a prática, estão todos no nível Hello World. Quero falar não sobre como colocar anotações corretamente, mas sobre como tudo funciona “nos bastidores”. O artigo é destinado a quem já trabalhou de uma forma ou de outra com esse framework e está familiarizado com os conceitos básicos. Estrutura Primavera.  Introdução - 1

Inicializando o contexto.

Então, vamos começar com o básico. Na minha opinião, um dos pontos mais importantes é entender como o contexto é configurado e os beans são inicializados. Como você sabe, antes do Spring começar a funcionar, ele precisa ser configurado. Nos tempos antediluvianos, isso era feito usando arquivos xml (em alguns projetos, principalmente nos antigos, eles continuam fazendo isso até hoje). Aqui está um pequeno exemplo desse arquivo de configuração:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
Em geral, isso é suficiente para criar alguns controladores e iniciar uma inicialização (que não decolará). Mas como essa configuração fará o Spring funcionar? E é aqui que as coisas ficam interessantes. Para que nossa configuração seja compreendida pelo Spring, existe um arquivo XmlBeanDefinitionReader. BeanDefinitionEste é um componente interno do Spring que verifica (analisa) xml e cria com base no que escrevemos lá . BeanDefinitioné um objeto que armazena informações sobre o bean. Isto inclui: de qual classe ele (o bean) deve ser criado; escopo; se a inicialização lenta está instalada; É necessário inicializar antes deste bean outra e outras propriedades que estão descritas no xml. Todos os recebidos BeanDefinitionsão adicionados a HashMap, em que o identificador é o nome do bean (definido por você ou atribuído pelo Spring) e BeanDefinitiono próprio objeto. Depois que tudo BeanDefinitionestiver criado, um novo herói aparece no palco - BeanFactory. Este objeto itera HashMap’es BeanDefinition, cria beans com base neles e os coloca em um contêiner IoC. Há uma nuance aqui: quando o aplicativo é iniciado, o contêiner IoC conterá beans que possuem um escopo Singleton (definido por padrão), enquanto o restante será criado quando necessário (protótipo, solicitação, sessão). E agora uma pequena digressão, vamos conhecer outro personagem.

Conheça o BeanPostProcessor. (BPP)

pós-processador de feijãoO fato é que um bean não é necessariamente uma classe de lógica de negócios para sua aplicação. Um bean também é chamado de bean de infraestrutura. Resumindo, um bean de infraestrutura é uma classe que configura seus beans lógicos de negócios (sim, muitos beans). Contarei mais sobre isso a seguir, mas para deixar um pouco mais claro o que exatamente o BPP configura, darei um exemplo. Todos estão familiarizados com o resumo @Autowired? Portanto, você AutowiredAnnotationBeanPostProcessoré responsável por garantir que todas as suas aulas estejam integradas umas nas outras. desconhecido

Vamos voltar ao BeanFactory

Conhecendo agora o BPP, você precisa esclarecer que, ao iterar sobre HashMap's, BeanDefinitiontodos os' são primeiro criados e colocados separadamente (não no contêiner IoC) BeanPostProcessor. Depois disso, os beans regulares da nossa lógica de negócios são criados, colocados em um contêiner IoC e sua configuração começa usando BPPs diferidos separadamente. E é assim que acontece, cada BPP possui 2 métodos:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
Itera em nossas caixas duas vezes. Na primeira vez o método é chamado postProcessorBeforeInitializatione na segunda vez o método é chamado postProcessorAfterInitialization. Certamente surgiu a questão de por que dois métodos são necessários, deixe-me explicar. O fato é que para processar algumas anotações (como @Transactional, por exemplo), nosso bean é substituído por uma classe proxy. Para entender por que isso é feito, você precisa saber como funciona @Transactionale é assim que funciona. Você precisa adicionar mais algumas linhas de código ao método marcado com esta anotação imediatamente. Como fazer isso? Isso mesmo, criando uma classe proxy, dentro da qual o código necessário será adicionado ao método requerido. Agora imagine esta situação, temos uma classe:
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
Esta classe tem 2 anotações @Autowirede @Transactional. Ambas as anotações são processadas por diferentes BPPs. Se funcionar primeiro AutowiredBPP, tudo ficará bem, mas se não, encontraremos esse problema. O fato é que quando a classe proxy é criada, todas as metainformações são perdidas. Ou seja, não haverá informações sobre a anotação @Autowiredna classe proxy e, portanto AutowiredBPP, não funcionará, o que significa que nosso campo someClassterá o valor null, o que provavelmente levará a um NPE. Também vale a pena saber que entre chamadas de métodos, o -method postProcessorBeforeInitializationé postProcessorAfterInitializationchamado init, se houver. Este é basicamente o segundo construtor, mas a diferença é que neste momento todas as nossas dependências já estão embutidas na classe e podemos acessá-las a partir initdo método -. Então, mais uma vez o algoritmo de inicialização de contexto:
  1. XmlBeanDefinitionReaderverifica nosso arquivo de configuração xml.
  2. Cria BeanDefinitione os coloca em HashMap.
  3. Vem BeanFactorye disso HashMapsoma separadamente todos os BeanPostProcessor's.
  4. Cria BeanDefinitionbeans a partir de e os coloca em um contêiner IoC.
  5. Aqui os BPPs vêm e configuram esses beans usando 2 métodos.
  6. Preparar.
Na verdade, isso é tudo, escreva se gostou do artigo e se vale a pena continuar escrevendo esses tutoriais.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION