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

Как создать объект с помощью Spring?

1.2 Junior🔥 221 комментариев
#Spring Boot и Spring Data#Spring Framework#ООП

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

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

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

Создание объектов (Bean) в Spring Framework

Spring Framework использует инверсию управления (IoC) и инъекцию зависимостей (DI) для создания и управления объектами. Существует несколько способов создать Bean в Spring.

1. Аннотация @Component (и её специализированные версии)

Самый простой способ — пометить класс аннотацией:

@Component
public class UserService {
    public void saveUser(User user) {
        System.out.println("Пользователь сохранён: " + user.getName());
    }
}

// Использование
@Autowired
private UserService userService;

userService.saveUser(new User("Alice"));

Специализированные версии:

// @Repository — для DAO/Repository слоя
@Repository
public class UserRepository {
    public User findById(Long id) { ... }
}

// @Service — для бизнес-логики
@Service
public class UserService {
    @Autowired
    private UserRepository repository;
}

// @Controller — для REST контроллеров
@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserService userService;
}

// @Configuration — для конфигурационных классов
@Configuration
public class AppConfig { }

2. Метод @Bean в конфигурационном классе

Для большей гибкости используй явное определение Bean:

@Configuration
public class AppConfig {
    
    @Bean
    public UserService userService() {
        return new UserService();
    }
    
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
    
    // Bean с зависимостью
    @Bean
    public OrderService orderService(UserRepository userRepository) {
        return new OrderService(userRepository);
    }
}

// Использование
@Autowired
private UserService userService;  // Spring подинжектирует Bean

3. Инъекция через конструктор (рекомендуется)

@Service
public class OrderService {
    private final UserRepository userRepository;
    private final NotificationService notificationService;
    
    // Конструктор с инъекцией
    public OrderService(UserRepository userRepository,
                       NotificationService notificationService) {
        this.userRepository = userRepository;
        this.notificationService = notificationService;
    }
    
    public void createOrder(Long userId, Order order) {
        User user = userRepository.findById(userId);
        // Обработка заказа
        notificationService.sendEmail(user.getEmail());
    }
}

// Spring автоматически создаст экземпляры зависимостей

4. Инъекция через setter

@Service
public class EmailService {
    private EmailProvider emailProvider;
    
    @Autowired
    public void setEmailProvider(EmailProvider emailProvider) {
        this.emailProvider = emailProvider;
    }
}

5. Инъекция через поле (НЕ рекомендуется)

@Service
public class PaymentService {
    @Autowired
    private PaymentGateway paymentGateway;  // Не очень хорошая практика
    
    public void processPayment(double amount) {
        paymentGateway.charge(amount);
    }
}

Полный пример: многоуровневое приложение

// 1. Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;
    
    private String name;
    private String email;
    
    // Геттеры и сеттеры
}

// 2. Repository
@Repository
public class UserRepository extends JpaRepository<User, UUID> {
    Optional<User> findByEmail(String email);
}

// 3. Service
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
    
    public UserService(UserRepository userRepository,
                      EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
    
    public User createUser(String name, String email) {
        User user = new User();
        user.setName(name);
        user.setEmail(email);
        
        User saved = userRepository.save(user);
        emailService.sendWelcome(email);
        return saved;
    }
}

// 4. Controller
@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody UserRequest request) {
        User user = userService.createUser(request.getName(), request.getEmail());
        return ResponseEntity.ok(user);
    }
}

// 5. Configuration
@Configuration
public class AppConfig {
    
    @Bean
    public EmailService emailService() {
        return new GmailEmailService();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Жизненный цикл Bean

@Component
public class MyBean implements InitializingBean, DisposableBean {
    
    @PostConstruct
    public void init() {
        System.out.println("Bean инициализирован");
        // Инициализация ресурсов
    }
    
    @PreDestroy
    public void destroy() {
        System.out.println("Bean уничтожается");
        // Закрытие ресурсов
    }
    
    // Альтернатива
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("После инициализации свойств");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("Уничтожение");
    }
}

Scopes (область видимости Bean)

@Component
@Scope("singleton")        // По умолчанию, один экземпляр на приложение
public class SingletonBean { }

@Component
@Scope("prototype")        // Новый экземпляр каждый раз
public class PrototypeBean { }

@Component
@Scope("request")         // Один экземпляр на HTTP запрос
public class RequestScopedBean { }

@Component
@Scope("session")         // Один экземпляр на HTTP сессию
public class SessionScopedBean { }

Условное создание Bean (@Conditional)

@Configuration
public class PaymentConfig {
    
    @Bean
    @ConditionalOnProperty(name = "payment.stripe.enabled", havingValue = "true")
    public StripePaymentGateway stripePaymentGateway() {
        return new StripePaymentGateway();
    }
    
    @Bean
    @ConditionalOnMissingBean
    public MockPaymentGateway mockPaymentGateway() {
        return new MockPaymentGateway();
    }
}

Профили (Profiles)

@Configuration
@Profile("development")
public class DevelopmentConfig {
    @Bean
    public DataSource devDataSource() {
        return new H2DataSource();
    }
}

@Configuration
@Profile("production")
public class ProductionConfig {
    @Bean
    public DataSource prodDataSource() {
        return new PostgresDataSource();
    }
}

Автоматический wiring (связывание)

@Service
public class OrderService {
    
    @Autowired(required = false)  // Опциональная зависимость
    private EmailService emailService;
    
    @Autowired
    private List<PaymentGateway> gateways;  // Все реализации
    
    @Autowired
    @Qualifier("stripePayment")   // Конкретная реализация
    private PaymentGateway paymentGateway;
}

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

  • Используй конструктор для инъекции — это делает зависимости явными
  • Используй @Service, @Repository — это лучше, чем просто @Component
  • Избегай @Autowired на полях — это скрывает зависимости
  • Используй Lazy инициализацию для тяжёлых Bean — с @Lazy
  • Определяй Bean в конфиге, а не в классе — если нужна гибкость

Spring управляет жизненным циклом всех Bean, поэтому ты можешь сосредоточиться на бизнес-логике.