← Назад к вопросам

Что такое аннотация @Inject?

2.0 Middle🔥 171 комментариев
#Docker, Kubernetes и DevOps#JVM и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Аннотация @Inject

@Inject — это аннотация из стандарта Java CDI (Contexts and Dependency Injection), которая используется для автоматического внедрения зависимостей в поля, методы или конструкторы класса. Она позволяет контейнеру (Spring, Quarkus, Weld и др.) автоматически создавать и передавать нужные объекты вместо того, чтобы вы создавали их вручную.

Основное назначение

@Inject говорит DI контейнеру: "Пожалуйста, найди подходящий объект для этого поля/параметра и вложи его сюда".

Где использовать @Inject?

1. Инъекция в поле (Field Injection)

import javax.inject.Inject;

public class UserService {
    // @Inject инжектирует UserRepository
    @Inject
    private UserRepository userRepository;
    
    public void registerUser(String email) {
        // userRepository будет автоматически инициализирован
        userRepository.save(new User(email));
    }
}

2. Инъекция в конструктор (Constructor Injection) - РЕКОМЕНДУЕТСЯ

import javax.inject.Inject;

public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
    
    // @Inject на конструкторе
    @Inject
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
    
    public void registerUser(String email, String password) {
        User user = new User(email, password);
        userRepository.save(user);
        emailService.sendWelcomeEmail(email);
    }
}

3. Инъекция в setter метод (Setter Injection)

import javax.inject.Inject;

public class UserService {
    private UserRepository userRepository;
    
    @Inject
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public void registerUser(String email) {
        userRepository.save(new User(email));
    }
}

@Inject vs @Autowired (Spring)

Это разные аннотации, хотя делают похожее:

// @Inject - стандарт Java CDI (javax.inject)
import javax.inject.Inject;

public class UserService {
    @Inject
    private UserRepository userRepository;
}

// @Autowired - специфично для Spring (org.springframework.beans.factory.annotation)
import org.springframework.beans.factory.annotation.Autowired;

public class UserService {
    @Autowired
    private UserRepository userRepository;
}

Таблица сравнения:

Признак@Inject@Autowired
СтандартCDI (JSR 330)Spring
ПортативностьДа (работает везде)Только Spring
Strict modeОбязательно требует beanМожет быть required=false
ИспользованиеРекомендуетсяЕсли привязан к Spring

Как работает @Inject?

// Шаг 1: Определишь bean (управляемый объект)
@ApplicationScoped // Область видимости
public class UserRepository {
    public void save(User user) {
        // реализация
    }
}

// Шаг 2: Используешь @Inject для внедрения
public class UserService {
    @Inject
    private UserRepository userRepository; // Контейнер создаёт и передаёт
    
    public void registerUser(User user) {
        userRepository.save(user);
    }
}

// Шаг 3: Контейнер управляет жизненным циклом
public class Application {
    public static void main(String[] args) {
        // Контейнер CDI создаёт экземпляры автоматически
        SeContainer container = SeContainerInitializer.newInstance().initialize();
        UserService userService = container.select(UserService.class).get();
        userService.registerUser(new User("test@example.com"));
    }
}

Области видимости (Scopes) для @Inject

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.inject.Singleton;

// @ApplicationScoped - один экземпляр на всё приложение
@ApplicationScoped
public class DatabaseConnection {
    public void connect() { }
}

// @RequestScoped - новый экземпляр на каждый HTTP запрос
@RequestScoped
public class UserRequest {
    public void processRequest() { }
}

// @Singleton - один экземпляр (эквивалент ApplicationScoped)
@Singleton
public class ConfigService {
    public String getConfig() { return ""; }
}

// @Dependent - новый экземпляр каждый раз (по умолчанию)
public class SessionData {
    public void setupSession() { }
}

Практический пример в Spring с @Inject

import javax.inject.Inject;
import javax.inject.Named;

// Интерфейс
public interface PaymentService {
    void processPayment(double amount);
}

// Реализация 1
@Component
@Named("creditCardPayment")
public class CreditCardPaymentService implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing credit card payment: " + amount);
    }
}

// Реализация 2
@Component
@Named("paypalPayment")
public class PayPalPaymentService implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing PayPal payment: " + amount);
    }
}

// Использование с @Inject и @Named
@Service
public class OrderService {
    @Inject
    @Named("creditCardPayment")
    private PaymentService paymentService;
    
    public void placeOrder(Order order) {
        // Используем инжектированный сервис
        paymentService.processPayment(order.getTotal());
    }
}

@Inject с квалификаторами (Qualifiers)

import javax.inject.Inject;
import javax.inject.Qualifier;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;

// Создаём квалификатор
@Qualifier
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface FastCache {
}

@Qualifier
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SlowCache {
}

// Реализации с квалификаторами
@ApplicationScoped
@FastCache
public class RedisCacheService implements CacheService {
    public void put(String key, Object value) { }
}

@ApplicationScoped
@SlowCache
public class DatabaseCacheService implements CacheService {
    public void put(String key, Object value) { }
}

// Использование квалификаторов
@Service
public class UserCacheService {
    @Inject
    @FastCache
    private CacheService fastCache; // Инжектирует RedisCacheService
    
    @Inject
    @SlowCache
    private CacheService slowCache; // Инжектирует DatabaseCacheService
}

Лучшие практики

// ✅ ХОРОШО - конструктор (immutable, тестируемо)
@Service
public class OrderService {
    private final PaymentService paymentService;
    private final NotificationService notificationService;
    
    @Inject
    public OrderService(PaymentService paymentService, 
                       NotificationService notificationService) {
        this.paymentService = paymentService;
        this.notificationService = notificationService;
    }
}

// ❌ ПЛОХО - поля (mutable, сложнее тестировать)
@Service
public class OrderService {
    @Inject
    private PaymentService paymentService;
    
    @Inject
    private NotificationService notificationService;
}

// ❌ ПЛОХО - множественные аннотации
@Service
public class OrderService {
    @Inject
    @Autowired // Зачем две?
    private PaymentService paymentService;
}

Когда @Inject не сработает?

public class ManualInstantiation {
    public static void main(String[] args) {
        // @Inject НЕ сработает здесь!
        UserService service = new UserService(); // Неправильно
        // userRepository будет null, потому что контейнер не инжектировал
        
        // Правильно - создавай через контейнер
        SeContainer container = SeContainerInitializer.newInstance().initialize();
        UserService service = container.select(UserService.class).get();
    }
}

@Inject — это ключевой механизм для применения Dependency Injection в Java приложениях. Она делает код более модульным, тестируемым и поддерживаемым, позволяя контейнеру управлять созданием и жизненным циклом объектов.

Что такое аннотация @Inject? | PrepBro