Compartilhamento de tecnologia

@RequiredArgsConstructor implementa injeção de construtor

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

@RequiredArgsConstructor implementa injeção de construtor

1. @Autowired e@Resource anotação

@Autowired
  • @Autowired É uma anotação fornecida pelo framework Spring e é usada para montar dependências automaticamente.
  • Pode ser usado em campos, construtores e métodos setter.
@Autowired
private ISysUserService userService;
  • 1
  • 2
@Resource
  • @Resource É uma anotação fornecida pelo Java EE e o Spring também oferece suporte para montagem automática de dependências.
  • Geralmente usado para campos e métodos setter.
@Resource
private ISysUserService userService;
  • 1
  • 2

2. Injeção de construtor

Usando Lombok @RequiredArgsConstructor

O conceito e uso de springboot @RequiredArgsConstructor-Tencent Cloud Developer Community-Tencent Cloud (tencent.com)

  • @RequiredArgsConstructor é uma anotação fornecida pelo Lombok, que irá gerar automaticamente todosfinal Construtor de campo.
  • O uso da injeção de construtor garante que a injeção de dependência seja concluída quando o objeto for criado, garantindo que todas as dependências não sejam nulas.
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private final ISysUserService userService;
    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysDeptService deptService;
    private final ISysUserPostService userPostService;
    
    // 构造函数由 Lombok 自动生成,注入所有 final 字段
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3. Comparação e vantagens

injeção de campo (@Autowired e@Resource
  • vantagem: O código é conciso e anotado diretamente nos campos.
  • deficiência
    • Difícil testar a unidade porque os objetos simulados precisam ser injetados por meio de reflexão ou outros meios.
    • A injeção de dependência ocorre após a criação do objeto, o que pode fazer com que as dependências sejam inicializadas de forma incompleta.
    • Violando o princípio de inversão de dependência, a classe depende diretamente do contêiner.
injeção de construtor
  • vantagem
    • Força as dependências a serem totalmente inicializadas quando o objeto é criado, garantindo que todas as dependências sejam não nulas.
    • Mais fácil de testar a unidade, pois objetos simulados podem ser injetados por meio do construtor.
    • Está mais alinhado com o princípio de inversão de dependência e torna a classe mais independente do contêiner.
    • Melhor legibilidade e manutenção do código, especialmente quando há muitas dependências.
  • deficiência: Requer código construtor adicional, mas usa o Lombok @RequiredArgsConstructor Este fardo pode ser aliviado.

4. Exemplo de comparação

usar @Autowired
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    
    @Autowired
    private ISysUserService userService;
    
    @Autowired
    private ISysRoleService roleService;
    
    @Autowired
    private ISysPostService postService;
    
    @Autowired
    private ISysDeptService deptService;
    
    @Autowired
    private ISysUserPostService userPostService;

    // 其他代码
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
Usar injeção de construtor
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private final ISysUserService userService;
    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysDeptService deptService;
    private final ISysUserPostService userPostService;

    // 其他代码
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Através deste método de injeção de construtor, não apenas a robustez e a capacidade de manutenção do código podem ser aprimoradas, mas também os recursos de injeção de dependência do Spring e as vantagens do código simplificado do Lombok podem ser melhor utilizados.

beneficiar

Construtor do Spring Injection_spring Construtor Injection-CSDN Blog
Adicione a descrição da imagem

5. Sobre anotações

Ao usar injeção de construtor, não há necessidade de adicionar anotações adicionais, você só precisa fornecer o construtor. O Spring detectará automaticamente seu construtor e executará a injeção de dependência.

Use injeção de construtor, sem necessidade de anotações adicionais
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
    private final ISysUserService userService;
    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysDeptService deptService;
    private final ISysUserPostService userPostService;

    // 自己编写构造函数
    public SysUserController(ISysUserService userService, 
                             ISysRoleService roleService, 
                             ISysPostService postService, 
                             ISysDeptService deptService, 
                             ISysUserPostService userPostService) {
        this.userService = userService;
        this.roleService = roleService;
        this.postService = postService;
        this.deptService = deptService;
        this.userPostService = userPostService;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
Pontos-chave do uso de injeção de construtor
  1. Defina o construtor:
    • Defina um construtor na classe que contenha todas as dependências necessárias.
  2. Injeção automática de mola:
    • Quando o Spring cria uma instância do Bean, ele identifica e chama automaticamente o construtor e injeta as dependências necessárias.

Código de amostra

package com.example.demo.controller;

import com.example.demo.service.ISysUserService;
import com.example.demo.service.ISysRoleService;
import com.example.demo.service.ISysPostService;
import com.example.demo.service.ISysDeptService;
import com.example.demo.service.ISysUserPostService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/system/user")
public class SysUserController {

    private final ISysUserService userService;
    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysDeptService deptService;
    private final ISysUserPostService userPostService;

    // 构造函数注入
    public SysUserController(ISysUserService userService, 
                             ISysRoleService roleService, 
                             ISysPostService postService, 
                             ISysDeptService deptService, 
                             ISysUserPostService userPostService) {
        this.userService = userService;
        this.roleService = roleService;
        this.postService = postService;
        this.deptService = deptService;
        this.userPostService = userPostService;
    }

    // 你的控制器方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Neste exemplo, não há necessidade de usar nenhuma anotação adicional para anotar o construtor, o Spring identificará e injetará automaticamente a dependência. (Claro, nenhum erro será relatado se marcado, mas apenas @Autowired pode ser usado e @Resouce não pode ser usado.@Resource As anotações são normalmente usadas para injeção de método de campo ou setter)

circunstâncias adicionais
  1. Vários construtores:
    • Se houver vários construtores em uma classe e apenas um deles tiver parâmetros de injeção, o Spring usará esse construtor para injeção.
    • Se houver vários construtores com parâmetros injetados, você precisará usar @Autowired anotação para especificar explicitamente qual construtor usar.

Código de exemplo (múltiplos construtores)

package com.example.demo.controller;

import com.example.demo.service.ISysUserService;
import com.example.demo.service.ISysRoleService;
import com.example.demo.service.ISysPostService;
import com.example.demo.service.ISysDeptService;
import com.example.demo.service.ISysUserPostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/system/user")
public class SysUserController {

    private final ISysUserService userService;
    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysDeptService deptService;
    private final ISysUserPostService userPostService;

    // 使用 @Autowired 明确指定使用哪个构造函数
    @Autowired
    public SysUserController(ISysUserService userService, 
                             ISysRoleService roleService, 
                             ISysPostService postService, 
                             ISysDeptService deptService, 
                             ISysUserPostService userPostService) {
        this.userService = userService;
        this.roleService = roleService;
        this.postService = postService;
        this.deptService = deptService;
        this.userPostService = userPostService;
    }

    // 另一个构造函数
    public SysUserController(ISysUserService userService) {
        this.userService = userService;
        this.roleService = null;
        this.postService = null;
        this.deptService = null;
        this.userPostService = null;
    }

    // 你的控制器方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

Neste exemplo, como existem vários construtores, você precisa usar @Autowired Anotações para especificar explicitamente qual construtor o Spring usa para injeção de dependência.