← Retour au blog
Java Publié le 2025-12-24 · 12 min de lecture

Injection de Dépendances Spring Boot : Guide Complet

Maîtrisez l'injection de dépendances avec l'injection par constructeur, champ et setter

Injection de Dépendances Spring Boot : Guide Complet

L'injection de dépendances Spring Boot est le cœur du framework Spring. C'est ce qui rend votre code testable, maintenable et faiblement couplé.

Points Clés

  • L'injection de dépendances permet à Spring de gérer la création et le câblage des objets
  • L'injection par constructeur est l'approche recommandée — elle garantit l'immutabilité
  • L'injection par champ (@Autowired) est pratique mais cache les dépendances
  • Utilisez @Qualifier avec plusieurs implémentations de la même interface
  • Utilisez @Primary pour définir une implémentation par défaut

Qu'est-ce que l'Injection de Dépendances ?

Considérez cette approche problématique :

java
// ❌ Bad: Class creates its own dependency
public class OrderService {
    private final OrderRepository repository = new OrderRepository();

    public Order findById(Long id) {
        return repository.findById(id);
    }
}

Voici la bonne façon avec Spring :

java
// ✅ Good: Spring injects the dependency
@Service
public class OrderService {
    private final OrderRepository repository;

    public OrderService(OrderRepository repository) {
        this.repository = repository;
    }

    public Order findById(Long id) {
        return repository.findById(id);
    }
}

Les Trois Types d'Injection

Injection par Constructeur (Recommandée)

java
@Service
public class PaymentService {
    private final PaymentGateway paymentGateway;
    private final NotificationService notificationService;

    // No @Autowired needed with single constructor
    public PaymentService(PaymentGateway paymentGateway,
                          NotificationService notificationService) {
        this.paymentGateway = paymentGateway;
        this.notificationService = notificationService;
    }

    public PaymentResult processPayment(Order order) {
        PaymentResult result = paymentGateway.charge(order.getTotal());
        if (result.isSuccessful()) {
            notificationService.sendConfirmation(order.getCustomerEmail());
        }
        return result;
    }
}

Injection par Champ

java
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    public User createUser(String email, String password) {
        User user = new User();
        user.setEmail(email);
        user.setPassword(passwordEncoder.encode(password));
        return userRepository.save(user);
    }
}

Injection par Setter

java
@Service
public class ReportService {
    private ReportGenerator reportGenerator;
    private EmailService emailService;

    @Autowired
    public void setReportGenerator(ReportGenerator reportGenerator) {
        this.reportGenerator = reportGenerator;
    }

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }

    public void generateAndSendReport(Long userId) {
        Report report = reportGenerator.generate(userId);
        emailService.send(report);
    }
}

Stéréotypes Spring

@Component

java
@Component
public class EmailValidator {
    private static final Pattern EMAIL_PATTERN =
        Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");

    public boolean isValid(String email) {
        return email != null && EMAIL_PATTERN.matcher(email).matches();
    }
}

@Service

java
@Service
public class InventoryService {
    private final ProductRepository productRepository;
    private final WarehouseClient warehouseClient;

    public InventoryService(ProductRepository productRepository,
                            WarehouseClient warehouseClient) {
        this.productRepository = productRepository;
        this.warehouseClient = warehouseClient;
    }

    public boolean isInStock(Long productId, int quantity) {
        Product product = productRepository.findById(productId)
            .orElseThrow(() -> new ProductNotFoundException(productId));

        int available = warehouseClient.getAvailableQuantity(product.getSku());
        return available >= quantity;
    }
}

@Repository

java
@Repository
public class JpaOrderRepository implements OrderRepository {
    private final EntityManager entityManager;

    public JpaOrderRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public Optional<Order> findById(Long id) {
        Order order = entityManager.find(Order.class, id);
        return Optional.ofNullable(order);
    }

    @Override
    public Order save(Order order) {
        entityManager.persist(order);
        return order;
    }
}

Gérer Plusieurs Implémentations

Avec @Qualifier

java
@Service
public class AlertService {
    private final NotificationSender emailSender;
    private final NotificationSender smsSender;

    public AlertService(
            @Qualifier("emailNotificationSender") NotificationSender emailSender,
            @Qualifier("smsNotificationSender") NotificationSender smsSender) {
        this.emailSender = emailSender;
        this.smsSender = smsSender;
    }

    public void sendUrgentAlert(String recipient, String message) {
        emailSender.send(recipient, message);
        smsSender.send(recipient, message);
    }
}

Avec @Primary

java
@Component
@Primary
public class EmailNotificationSender implements NotificationSender {
    @Override
    public void send(String recipient, String message) {
        // Email is the default notification method
    }
}

@Component
public class SmsNotificationSender implements NotificationSender {
    @Override
    public void send(String recipient, String message) {
        // SMS is used only when explicitly requested
    }
}
spring-bootdependency-injectionjavabackendarchitecture

Créé avec Angular & PrimeNG

© 2026 Blog Java Angular