Eu te saúdo, Habr!
Este artigo será útil para aqueles que já começaram a aprender Java e até conseguiram obter algum sucesso no entendimento do Java Core, e agora ouvi a palavra Spring. E, talvez, nem uma vez: o conhecimento do Spring Framework, pelo menos, aparece nas descrições de muitas vagas para javistas. Este artigo o ajudará a escalar o primeiro passo: entender a idéia geral de uma estrutura tão popular.
Vamos começar de longe. Existe algo como Inversão de controle, em russo - Inversão de controle, de forma abreviada - IoC. IoC é um dos princípios que aproxima nosso código da frouxidão. IoC é a delegação de parte de nossas responsabilidades a um componente externo.
Existem diferentes implementações da abordagem de IoC, estamos interessados em uma delas - injeção de dependência, injeção de dependência. O que é isso, o nome fala por si, então tentarei divulgá-lo usando um exemplo. Estamos escrevendo um aplicativo que automatiza a operação de uma cadeia de lojas. Existem classes Loja (loja) e Vendedor (vendedor). A classe Vendedor possui um campo do tipo Loja - a loja na qual o vendedor trabalha. Portanto, somos confrontados com o vício: o vendedor depende da loja. Agora vamos pensar em como o objeto Shop entra no objeto Seller? Existem opções:
- Implemente-o através do designer e, imediatamente, ao criar o vendedor, especifique a loja em que ele trabalha:
public class Seller { private Shop shop; public Seller(Shop shop) { this.shop = shop; } }
- Crie um levantador e, usando a chamada dele, defina a loja para o vendedor:
public class Seller { private Shop shop; public void setShop(Shop shop) { this.shop = shop; } }
Os dois métodos listados são a implementação da injeção de dependência. E, finalmente, chegamos à primavera: fornece outra maneira de injetar dependências.
De um modo geral, o Spring é uma gama muito ampla de bibliotecas para muitas ocasiões. Há o Spring MVC para criar rapidamente aplicativos da Web, o Spring Security para implementar a autorização no aplicativo e o Spring Data para trabalhar com bancos de dados e muito mais. Mas o Spring IoC fica sozinho - esse é o tipo básico de primavera que implementa o tópico que estamos estudando - injeção de dependência. O Spring IoC merece atenção no início do estudo das bibliotecas da primavera por outro motivo. Como você verá no processo de trabalho prático com outros tipos de mola, para todas as outras molas, o Spring IoC é usado como estrutura.
Começaremos nossa introdução ao Spring IoC com o termo principal: bean. Nas palavras mais simples
Um bean é um objeto de classe criado pelo Spring que pode ser incorporado como um valor de campo em outro objeto.
Você quer palavras mais complicadas? E por favor:
Um bean é um objeto de classe, que é um elemento completo do programa com uma função comercial específica ou uma função Spring interna, cujo ciclo de vida é controlado pelo container bin.
Como você já entendeu, para que a Loja possa implementá-la, a Loja deve se tornar uma lixeira. Existem várias maneiras de dizer à aplicação quais objetos têm o direito de serem chamados de beans, todos eles nos levando ao conceito de ApplicationContext.
O ApplicationContext é o coração da primavera. Como regra, ele é criado no início do aplicativo ("sobe") e controla o ciclo de vida dos beans. Portanto, também é chamado de contêiner bin.
Estamos chegando ao ponto principal. Como precisamos reescrever nossas classes para que o Spring IoC e seu servidor ApplicationContext substituam o campo Shop pelo objeto Seller? Assim:
@Component public class Shop { }
@Component public class Seller { @Autowired private Shop shop; }
É simples? Muito mais fácil! Elegante? Bastante. Aqui aconteceu o seguinte: a anotação Component disse ao Spring que a classe que anotou é uma lixeira. Anotação A Autowired solicitou ao Spring que substituísse um valor no campo que ele anotou. Esta operação é chamada injetar. Qual valor exato será substituído? Mais sobre isso mais tarde, primeiro, descobriremos como as classes se tornam bin em geral.
Já sabemos que, no início do aplicativo, o guardião de todos os beans ApplicationContext deve aumentar. Ele cria todas as caixas de uma só vez. Quase tudo. O fato é que, por padrão, qualquer bean tem o escopo da propriedade intraspring no valor singleton. Intraspringovoe, uma vez que, no sentido literal da palavra, ele não é um singleton. É o singleton da primavera: quando o contexto é gerado, o Spring cria exatamente um objeto bin da classe especificada. Se você deseja alterar esse comportamento - por favor, o Spring permite controlar o tempo de criação do bean e seu número para uma classe, mas agora não é sobre isso.
Portanto, ao aumentar o ApplicationContext, todos os compartimentos são criados. Vamos descobrir exatamente onde o contexto vive e o mais importante: como ele determina de quais classes criar bins. Existem várias opções, para simplificar, falaremos sobre uma delas: configuração usando o arquivo xml. Aqui está um exemplo disso:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:beans="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="product" class="main.java.Product"></bean> <context:component-scan base-package="main"/> </beans>
Este arquivo demonstra como criar beans de duas maneiras. O primeiro, digamos, é manual. Veja bem, existe uma tag de
bean com uma indicação da classe. Este é o feijão. De tudo o que está registrado neste arquivo com uma tag de
bean , os
beans serão criados.
A segunda maneira é menos detalhada. Lembre-se, nas classes, colocamos a anotação Component. De todas as classes anotadas com esta anotação, os beans serão criados. Graças a esta linha do arquivo xml:
<context:component-scan base-package="main"/>
Ela diz à primavera: digitalize o pacote principal inteiro e, a partir de tudo o que a anotação Component (ou outras anotações que são componentes do Component) permanecerão, crie compartimentos. Compacto, não é? Apenas dizemos quais pacotes contêm as classes a partir da qual os beans serão criados e anotamos essas classes.
Você pode aumentar o contexto usando o arquivo xml com a seguinte linha de código:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
onde beans.xml é o caminho para o apelido xml discutido acima.
Com a criação dos feijões descobertos. Como o Spring preenche o campo Shop ao criar um vendedor? Ao elevar o contexto, um objeto bin da classe Shop é criado. Um objeto bin da classe Seller também é criado e também anotado por Component. Tem um tipo de loja anotado pela Autowired. A anotação com fio automático informa a primavera: você precisa injetar a bandeja nesse campo. No nosso caso, temos apenas um compartimento adequado para essa função, ou seja, o tipo que corresponde ao tipo do campo: este é um compartimento - uma instância da classe Shop. Ele será injetado no objeto Vendedor, conforme necessário. Entendo que agora as perguntas subiram como worms: o que acontecerá se o Spring não encontrar o bean desejado ou encontrar vários adequados (especialmente considerando que você também pode injetar pela interface e não por classe). A primavera é inteligente, mas exige o mesmo de nós. Precisamos ter exatamente um bean no sistema adequado para cada Autowired ou treinar o Spring para agir em tais conflitos (não falaremos sobre isso agora, você já está cansado, aperte o cinto, o artigo está chegando ao fim).
Observe que o vendedor também é uma lixeira. Se não fosse um compartimento, mas criado por meio de um novo, nada seria injetado automaticamente nele.
Talvez agora você esteja pensando por que todas essas dificuldades são necessárias. Mas imagine que nosso aplicativo não seja de 2 classes, mas várias ordens de magnitude maiores e o gerenciamento de dependências não seja mais a tarefa mais trivial.
Talvez agora você pense o quão bonito, simples e conciso o Spring permite implementar dependências. Mas imagine que algo deu errado e você precisa depurar o aplicativo. E não é mais tão fácil ...
Por fim, algumas dicas:
- Se você implementou o projeto e agora não sabe como obter uma lixeira da primavera para examiná-la, faça o seguinte:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Seller seller = (Seller) context.getBean(Seller.class);
Essa é uma maneira legal de obter uma lixeira, embora nas realidades modernas isso geralmente não seja feito. Mas, para um estudo de caso, você pode.
- Como o Spring é uma estrutura, você precisa incluí-la no seu projeto. Crio um aplicativo usando o maven e adiciono dependências spring-core e spring-context ao arquivo pom.xml.
O Spring IoC contém enormes oportunidades para criar, configurar e injetar beans. Examinamos uma pequena parte da ponta do iceberg, uma das maneiras de trabalhar com a primavera, mas espero que possamos dar uma olhada nítida e ter uma idéia geral do que está acontecendo.