Descrição
neste artigo, vamos introduzir os conceitos de IoC (Inversão de Controle) e DI (Injeção de Dependência), e nós vamos então dar uma olhada em como estes são implementados no Spring framework.,
bibliografia:
Fiação na Primavera: @Autowired, @Recurso e @Injetar
@Component vs @Repository and @Service in Spring
o que é a inversão do controlo?,
inversão de controle é um princípio em Engenharia de software pelo qual o controle de objetos ou porções de um programa é transferido para um recipiente ou estrutura. É mais usado no contexto da programação orientada a objetos.
em contraste com a programação tradicional, na qual o nosso código personalizado faz chamadas para uma biblioteca, o COI permite que um framework assuma o controle do fluxo de um programa e faça chamadas para o nosso código personalizado. Para permitir isso, frameworks usam abstrações com comportamento adicional incorporado., Se queremos adicionar o nosso próprio comportamento, precisamos estender as classes do framework ou plugin nossas próprias classes.,
As vantagens desta arquitetura são:
- dissociar a execução de uma tarefa a partir de sua implementação
- tornando mais fácil para alternar entre diferentes implementações
- maior modularidade de um programa
- maior facilidade em testar um programa de isolamento de um componente ou zombando de suas dependências e permitindo a comunicação entre componentes através de contratos
Inversão de Controle pode ser conseguido através de vários mecanismos, tais como: A estratégia padrão de design, Serviço de Localizador padrão de Fábrica padrão de Injeção de Dependência (DI).,vamos ver o DI a seguir.
Qual é a injecção de Dependência?
injeção de dependência é um padrão através do qual implementar o COI, onde o Controle sendo invertido é a configuração das dependências do objeto.
O ato de conectar objetos com outros objetos, ou “injetar” objetos em outros objetos, é feito por um montador ao invés dos próprios objetos.,
Aqui está como você criaria uma dependência de objeto na programação tradicional:
public class Store { private Item item; public Store() { item = new ItemImpl1(); }}
no exemplo acima, precisamos instanciar uma implementação da interface de Item dentro da própria classe de armazenamento.
usando o DI, podemos reescrever o exemplo sem especificar a aplicação do Item que queremos:
public class Store { private Item item; public Store(Item item) { this.item = item; }}
Nas próximas seções, vamos ver como nós podemos fornecer a implementação do Item através de metadados.,tanto o COI como o DI são conceitos simples, mas têm implicações profundas na forma como estruturamos os nossos sistemas, pelo que vale a pena compreendê-los bem.
o recipiente de mola de Coi
um recipiente de COI é uma característica comum dos quadros que implementam coi.
na mola, o container do COI é representado pelo Interface ApplicationContext. O contêiner de molas é responsável pela instanciação, configuração e montagem de objetos conhecidos como feijões, bem como pela gestão de seu ciclo de vida.,
The Spring framework provides several implementations of the ApplicationContext interface-ClassPathXmlApplicationContext and FileSystemXmlApplicationContext for standalone applications, and WebApplicationContext for web applications.
A fim de montar feijões, o recipiente usa metadados de configuração, que pode ser na forma de configuração XML ou anotações.
Aqui está uma maneira de instanciar manualmente um recipiente:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
para definir o atributo do item no exemplo acima, podemos usar metadados., Em seguida, o container vai ler esses metadados e usá-lo para montar feijões no período de execução.a injecção de dependência de
na primavera pode ser feita através de construtores, setters ou campos.
injeção de Dependência baseada no Construtor
No caso da injeção de dependência baseada no construtor, o recipiente irá invocar um construtor com argumentos cada um representando uma dependência que queremos definir.
Spring resolve cada argumento primariamente por tipo, seguido pelo nome do atributo e índice para desambiguação., Vamos ver a configuração de um bean e suas dependências usando anotações:
a anotação de configuração @indica que a classe é uma fonte de definições de bean. Além disso, podemos adicioná-lo a várias classes de configuração.
a anotação @Bean é usada em um método para definir um bean. Se não especificarmos um nome personalizado, o nome do feijão padrão para o nome do método.
para um feijão com o escopo singleton padrão, a primeira primavera verifica se uma instância do bean em cache já existe e só cria uma nova se não existir., Se estamos usando o escopo do protótipo, o recipiente retorna uma nova instância de feijão para cada chamada de método.
outra forma de criar a configuração dos feijões é através da configuração XML:
Setter-Based Dependency Injection
para setter-based DI, o contentor irá invocar os métodos setter da nossa classe, depois de invocar um construtor sem argumentos ou um método de fábrica estática sem argumentos para instanciar o bean., Vamos criar essa configuração usando as anotações:
@Beanpublic Store store() { Store store = new Store(); store.setItem(item1()); return store;}
podemos também utilizar o XML para a mesma configuração de feijão:
<bean class="org.baeldung.store.Store"> <property name="item" ref="item1" /></bean>
Construtor de base e setter baseado em tipos de injeção pode ser combinado para o mesmo feijão. A documentação da primavera recomenda a utilização de injeção baseada em construtores para dependências obrigatórias, e injeção baseada em setter para as opcionais.
7., Baseado no campo de Injeção de Dependência
No caso do Campo, com DI, podemos injetar as dependências, marcando-as com um @Autowired anotação:
public class Store { @Autowired private Item item; }
Durante a construção do objeto de Armazenamento, se não há nenhum construtor ou método setter para injetar o Item de feijão, o recipiente que vai usar a reflexão para injetar Item na Loja.
também podemos conseguir isso usando a configuração XML.,
Esta abordagem pode parecer mais simples e limpo, mas não é recomendado o uso de porque ele tem alguns inconvenientes, tais como:
- Este método usa a reflexão para injetar as dependências, que é mais caro do que o construtor ou com base em setter baseado em injeção
- É muito fácil manter a adição de várias dependências usando esta abordagem. Se você estivesse usando injeção Construtora tendo vários argumentos teria nos feito pensar que a classe faz mais do que uma coisa que pode violar o princípio de Responsabilidade Única.,
Mais informações sobre a anotação @Autocolada podem ser encontradas na cablagem no artigo da Primavera.
Autowiring Dependencies
cablagem permite que o container de mola resolva automaticamente as dependências entre os feijões colaborantes inspeccionando os feijões que foram definidos.,
Existem quatro modos de autowiring um bean usando uma configuração XML:
- não: o valor padrão – isto significa que não autowiring é usado para o feijão e temos de o fazer explicitamente o nome de dependências
- byName: autowiring é feito com base no nome da propriedade, portanto, a Primavera vai olhar para um bean com o mesmo nome que a propriedade que precisa ser definido
- byType: semelhante ao byName autowiring, apenas com base no tipo de propriedade. Isso significa que a primavera vai procurar um feijão com o mesmo tipo de propriedade para definir., Se houver mais de um feijão desse tipo, o framework abre uma excepção.,também pode injetar beans usando o @Autowired anotação de autowiring por tipo:
public class Store { @Autowired private Item item;}
Se houver mais de um bean do mesmo tipo, podemos usar o @Qualificador de anotação para fazer referência a um grão de feijão por nome:
public class Store { @Autowired @Qualifier("item1") private Item item;}
Agora, vamos autowire feijão por tipo através de XML de configuração:
<bean class="org.baeldung.store.Store" autowire="byType"> </bean>
em seguida, vamos injetar um bean chamado de item em item de propriedade de armazenamento de grão em nome através de XML:
<bean class="org.baeldung.store.ItemImpl1" /><bean class="org.baeldung.store.Store" autowire="byName"></bean>
também podemos substituir o autowiring pela definição de dependências explicitamente através de argumentos do construtor ou setters.,
feijões inicializados preguiçosos
por omissão, o contentor cria e configura todos os feijões singleton durante a inicialização. Para evitar isso, você pode usar o atributo lazy-init com o valor verdadeiro na configuração do bean:
<bean class="org.baeldung.store.ItemImpl1" lazy-init="true" />
como consequência, o item1 bean será inicializado apenas quando for solicitado pela primeira vez, e não no arranque., A vantagem disso é o tempo de inicialização mais rápido, mas o trade-off é que os erros de configuração podem ser descobertos apenas após o bean é solicitado, o que pode ser várias horas ou até mesmo dias após a aplicação já estar em execução.
conclusão
neste artigo, apresentamos os conceitos de inversão da injecção de controlo e dependência e exemplificamo-los na mola.
pode ler mais sobre estes conceitos nos artigos de Martin Fowler:
- inversão dos recipientes de controlo e o padrão de injecção de Dependência.,inversão do controlo
- inversão dos recipientes de controlo e o padrão de injecção de Dependência.,inversão do controlo