Что такое аннотация @Inject?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Аннотация @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 приложениях. Она делает код более модульным, тестируемым и поддерживаемым, позволяя контейнеру управлять созданием и жизненным циклом объектов.