Setter DI vs. Construtor DI na primavera?

A primavera tem dois tipos de DI: setter DI e construção DI.

O DI baseado em construtor fixa a ordem em que as dependencies precisam ser injetadas. A DI baseada no setter não oferece isso.

A DI baseada em setter nos ajuda a injetar a dependência somente quando é necessária, em vez de exigi-la em tempo de construção.

Eu não vejo nenhuma outra diferença significativa, já que os dois tipos de Spring DI fornecem os mesmos resources – tanto o setter quanto o construtor DI injetam a dependência quando o código é inicializado. Concedido, o DI do construtor fará isso através do construtor, enquanto o DI do setter o fará através de um setter logo após a construção do object, mas não faz nenhuma diferença para o desenvolvedor em termos de desempenho, etc. Ambos também oferecem meios para especificar o pedido de injeção de dependência também.

Eu estou procurando um cenário onde um fornece uma vantagem distinta sobre o outro ou onde um tipo é completamente inutilizável.

Quando se trata de prós e contras específicos da Spring:

  • A injeção de construtor (da definição) não permite criar dependencies circulares entre beans. Esta limitação é na verdade uma vantagem da injeção de construtor – o Spring pode resolver dependencies circulares quando a injeção de setter é usada sem que você perceba.

  • Por outro lado, se você usar a injeção de construtor, o CGLIB não poderá criar um proxy, forçando-o a usar proxies baseados em interface ou um construtor no-arg falso. Consulte: SPR-3150

Você deve estar decidindo com base em considerações de design, e não em considerações de ferramentas (Spring). Infelizmente, Spring nos treinou para usar injeção de setter porque quando foi originalmente concebido, não existia uma “anotação” em Java, e em XML, a injeção de setter funciona e parece muito melhor. Hoje, estamos livres dessas restrições, permitindo que seja uma decisão de design novamente. Seus beans devem usar injeção de construtor para quaisquer dependencies que sejam requeridas pelo bean e injeção de setter para dependencies opcionais e que tenham um padrão razoável, mais ou menos como o OOD nos disse desde o início.

Injeção de Construtor: Estamos injetando as dependencies através do Construtor.

Geralmente podemos usar para dependencies obrigatórias.

Se você usar a injeção de construtor, há uma desvantagem chamada “Dependência Circular”.

Dependência Circular: Suponha que A e B. A depende de B. B é dependente de A. Neste construtor, a injeção falhará. Nesse momento, a injeção Setter é útil.

Se o estado do object não for inconsistente, ele não criará o object.

Setter Injection: Estamos injetando as dependencies através dos methods Setter.

Isso é útil para dependencies não obrigatórias.

É possível injetar dependencies usando Setter Injection. Não é possível na injeção de construtor.

Prefira injeção setter.

Pense o que seria sem a primavera (como Ryan observou). Você passaria as dependencies no construtor? Se houver muitas dependencies, isso parece errado. Por outro lado, o construtor pode ser usado para impor o estado válido do object – requer todas as dependencies e verifica se elas são não-nulas.

Proxies são outra coisa (como observou Tomasz) – você precisará de um construtor falho que derrote toda a idéia.

Existe uma terceira opção btw – injeção de campo. Eu tenho a tendência de estar usando isso, embora não seja uma decisão de design tão boa, porque ele economiza um setter extra, mas se isso for usado fora da primavera, terei que adicionar o setter.

Não, mesmo que a Injeção do Construtor aconteça, a injeção ainda está funcionando, mas apenas a boot limitada, a injeção do setter é opcional e flexível. mas geralmente pode para a class de parâmetro, um bean de primavera com outros grãos de primavera

Desde que você pode misturar ambos,
Construtor DI – e DI baseado em Setter ,
é uma boa regra geral usar argumentos de construtor para dependencies obrigatórias e setters para dependencies opcionais .

Observe que o uso de uma anotação @Required em um setter pode ser usado para tornar as dependencies necessárias dos setters.

De acordo com o conteúdo do spring.io da spring 5 em diante

Como você pode misturar DI baseado em construtor e baseado em setter, é uma boa regra usar construtores para dependencies obrigatórias e methods setter ou methods de configuração para dependencies opcionais. Observe que o uso da anotação @Required em um método setter pode ser usado para tornar a propriedade uma dependência necessária.

A equipe do Spring geralmente defende a injeção de construtor, pois permite implementar os componentes do aplicativo como objects imutáveis ​​e garantir que as dependencies necessárias não sejam nulas. Além disso, os componentes injetados por construtor são sempre retornados ao código do cliente (chamada) em um estado totalmente inicializado. Como uma nota lateral, um grande número de argumentos de construtor é um mau cheiro de código, implicando que a class provavelmente tem muitas responsabilidades e deve ser refatorada para melhor abordar a separação adequada de preocupações.

A injeção do Setter deve ser usada principalmente apenas para dependencies opcionais que podem receber valores padrão razoáveis ​​dentro da class. Caso contrário, as verificações não nulas devem ser executadas em todos os lugares em que o código usa a dependência. Um benefício da injeção setter é que os methods setter tornam os objects dessa class passíveis de reconfiguração ou reinjeção posterior. O gerenciamento por meio dos MBeans JMX é, portanto, um caso de uso atraente para a injeção de setter.

Aqui está o link para a citação acima

Mas todos os tipos de injeções estão disponíveis e nenhum deles é obsoleto. Em um nível alto, você obtém a mesma funcionalidade em todos os tipos de injeção.

Em resumo, escolha o tipo de injeção que funciona melhor para sua equipe e projeto.

Recomendações da equipe da spring e posts independentes no blog irão variar ao longo do tempo. Não há regra de hard-fast.

Se um determinado estilo de injeção não fosse recomendado pela equipe do Spring, ele seria marcado como obsoleto ou obsoleto. Esse não é o caso de nenhum dos estilos de injeção.