image

Acesse bootcamps ilimitados e +650 cursos

50
%OFF
Giovanni Rozza
Giovanni Rozza28/04/2023 17:37
Compartilhe

[updated] Porque não devemos usar a anotação @Autowired (injeção de dependência)

    No link abaixo está um artigo do dev Felix Coutinho do site dev.to onde ele argumenta que não devemos usar @Autowired em nosso código mas sim declarar explicitamente as dependências, ele cita algumas razões que cito a seguir:

    • O uso excessivo da anotação @Autowired pode tornar o código difícil de entender e manter.
    • A anotação @Autowired pode tornar o código menos flexível e mais difícil de testar.
    • O uso da anotação @Autowired pode criar dependências desnecessárias e acoplar diferentes camadas da aplicação.
    • Em vez disso, o autor recomenda o uso de injeção de dependência explícita e construtores para instanciar as dependências necessárias.

    https://dev.to/felixcoutinho/you-should-stop-using-spring-autowired-p8i

    Update:

    Eu acabei implementando em uma entidade essa estratégia (não usar @Autowired) na camada de Service:

    ANTES:

      // SERVICE CLASS
      @Service
      public class CadastroRestauranteService {
      
    
          @Autowired
          private RestauranteRepository restauranteRepository;
      
    
          @Autowired
          private CozinhaRepository cozinhaRepository;
      
    
          // modelmapper pode mapear classes dentro do Dto...
          @Autowired
          ModelMapper modelMapper; 
    .
    .
    .
    ---------------------------------------------------------------------------------------------------
      // CONTROLLER CLASS
      @RestController
      @RequestMapping(value = "/restaurantes")
      public class RestauranteController {
      
          @Autowired
          private CadastroRestauranteService restauranteService;
    
    .
    .
    .
    

    DEPOIS

    // SERVICE CLASS
    @Service
    
    public class CadastroRestauranteService {
    
     
      private final RestauranteRepository restauranteRepository;
    
      private final CozinhaRepository cozinhaRepository;
    
      private final ModelMapper modelMapper;
    
      public CadastroRestauranteService(RestauranteRepository restauranteRepository, 
                                        CozinhaRepository cozinhaRepository, 
                                        ModelMapper modelMapper) {
    
          this.restauranteRepository = restauranteRepository;
          this.cozinhaRepository = cozinhaRepository;
          this.modelMapper = modelMapper;
    
      }
    .
    .
    .
    ----------------------------------------------------------------------------------------------
    // CONTROLLER CLASS
    @RestController
    @RequestMapping(value = "/restaurantes")
    
    public class RestauranteController {
    
      private final CadastroRestauranteService restauranteService;
      
      public RestauranteController( CadastroRestauranteService restauranteService)
    
      {
    
          this.restauranteService = restauranteService;
    
      }
    
    .
    .
    .
    -------------------------------------------------------------------------------------------------------
    // modelmapper é um Bean
    @Configuration
    
    public class ModelMapperConfig {
    
      @Bean
      ModelMapper modelMapper() {
    
          return new ModelMapper();
    
      }
    }
    
    
    
    

    Veja que eu apenas criei o construtor nas classe service e na classe controller e atribui as dependências explicitamente, a instanciação dos objetos é feito automaticamente pelo Spring, inclusive o bean do ModelMapper

    Compartilhe
    Comentários (2)
    Giovanni Rozza
    Giovanni Rozza - 28/04/2023 20:34

    Na realidade nem precisa do @Autowired no construtor, o Spring injeta automaticamente uma vez definido o construtor, exemplo que testei (usei inclusive um bean do ModelMapper)


    Na classe Service:

      private final RestauranteRepository restauranteRepository;
    
      private final CozinhaRepository cozinhaRepository;
    
      private final ModelMapper modelMapper;
    
    
    
    
      public CadastroRestauranteService(RestauranteRepository restauranteRepository, CozinhaRepository cozinhaRepository, ModelMapper modelMapper) {
    
          this.restauranteRepository = restauranteRepository;
    
          this.cozinhaRepository = cozinhaRepository;
    
          this.modelMapper = modelMapper;
    
      }
    


    Na classe Controller:


      private final CadastroRestauranteService restauranteService;
    
      
    
      public RestauranteController( CadastroRestauranteService restauranteService)
    
      {
    
          this.restauranteService = restauranteService;
    
      }
    


    Victor Leme
    Victor Leme - 28/04/2023 20:16

    Na verdade não é tão restritivo assim.

    Você pode declarar as dependências e iniciá-las no construtor, e anotar o construtor com @Autowired.

    Dessa forma, permite que o Spring injete pra você, e permite setar as dependências conforme necessário para teste.